function sign(json, unknown) does not exist - jwt

I'm following the tutorial on https://postgrest.org/en/v5.0/auth.html#jwt-from-sql
I created this function:
create or replace function
login(email text, pass text) returns basic_auth.jwt_token
language plpgsql
as $$
declare
_role name;
result basic_auth.jwt_token;
begin
-- check email and password
select basic_auth.user_role(email, pass) into _role;
if _role is null then
raise invalid_password using message = 'invalid user or password';
end if;
select sign(
row_to_json(r), 'reallyreallyreallyreallyverysafe'
) as token
from (
select _role as role, login.email as email,
extract(epoch from now())::integer + 60*60 as exp
) r
into result;
return result;
end;
$$;
When I try to do the login request, I get the following error message:
{
"hint": "No function matches the given name and argument types. You might need to add explicit type casts.",
"details": null,
"code": "42883",
"message": "function public.sign(json, unknown) does not exist" }
I don't see the sign function anywhere in the tutorial, does anyone know what is going on here?

The sign function is created when you install pgjwt.
Also, make sure that you install the extension on a schema that is included in your search_path(a list of imported schemas). This can be specified by doing CREATE EXTENSION pgjwt WITH SCHEMA public.
PostgREST adds the public schema by default on the search_path, so the extension should work with no additional config.

Related

How to check for custom Postgres exceptions raised via RAISE EXCEPTION in Golang?

I'm using Postgres with Golang via pgx
I've a trigger function something like the following:
CREATE OR REPLACE FUNCTION foo()
RETURNS TRIGGER AS
$$
BEGIN
IF (bar = 'baz') THEN
-- something
ELSE
RAISE EXCEPTION 'oops error';
END IF;
RETURN NEW;
END;
$$
LANGUAGE plpgsql;
How do I check for oops error in Go code?
The way I'm doing it now is:
errOops := errors.New("ERROR: oops error (SQLSTATE P0001)")
err := myDBFunc()
if errors.Is(err, errOops) {
}
But I wonder if there's a better way other than relying on the hardcoded message.
Should have read the Wiki: Error Handling in pgx
So I can do:
var pgErr *pgconn.PgError
if errors.As(err, &pgErr) && pgErr.Code == "P0001" {
}
or something similar.
You can find that information in appendix A of the documentation: it will be a raise_exception, and the SQLSTATE is P0001.

Can SQL Server return an informational message to .NET System.Data.SqlClient program in contexts that do not involve any error

Is it possible with a .NET client program, communicating with back-end SQL Server using the System.Data.SqlClient library, for the server to send an informational message to the client program in contexts that do not involve any error and for the client program to obtain the message that was sent?
create proc NewFoo
#value text,
#userid text
as
begin
insert foo
(name, createdby) values (#value, #userid);
declare #recordcount int
select #recordcount = count(*) from foo where createdby= #userid;
if #recordcount = 100
begin
-- let user know they've created their 100th record. Woo-hoo!!
end
end
Here is an additional pseudo-code example, closer to the actual use case; note the differing severity:
if #value > #maxallowed
begin
if #userlevel = 'manager'
raiserror('Exceeded max. Intentional?',10,1)
else
raiserror('Exceeds max. Your edit was not saved',11,1)
end
P.S. Without using an OUT parameter or RETURN value parameter in the client-side command object.
P.P.S. I am using the SqlDataAdapter.Update method and some of the code uses a DataReader on the SqlCommand object.
You can use PRINT in your stored procedure, and to capture it in the code by subscribing to the InfoMessage event in the SqlConnection object.
In your sql just put:
PRINT 'Exceeded max. Intentional'
and in your code grab it like this:
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
string msg = null;
connection.InfoMessage += (sender, e) => { msg = e.Message; };
// execute the procedure
// check msg
}

PostgreSQL/JPA - Import functions in import.sql file?

I'm trying to define some PostgreSQL functions and triggers in my JPA import.sql file. I'm using Hibernate 5.x as my underlying JPA provider. Since my import.sql file has commands that are multiple lines, I've got this property set in my persistence.xml file:
<property name="hibernate.hbm2ddl.import_files_sql_extractor" value="org.hibernate.tool.hbm2ddl.MultipleLinesSqlCommandExtractor" />
From there, I'm trying to define my functions in import.sql. They look something like this:
DROP FUNCTION IF EXISTS update_total_feedback_count() CASCADE;
CREATE FUNCTION update_total_feedback_count() RETURNS TRIGGER AS
$$
DECLARE
application_version_id BIGINT := 0;
app_version_metadata_id BIGINT:= 0;
application_id BIGINT := 0;
app_metadata_id BIGINT := 0;
BEGIN
IF (TG_OP = 'INSERT') THEN
SELECT INTO application_version_id tbl_application_version.id
FROM tbl_application_version
INNER JOIN tbl_feedback ON tbl_feedback.application_version_id = tbl_application_version.id
WHERE tbl_feedback.id = NEW.id;
SELECT INTO app_version_metadata_id tbl_application_version.application_version_metadata_id
FROM tbl_application_version
WHERE id = application_version_id;
SELECT INTO app_metadata_id registered_application_metadata_id
FROM tbl_registered_application
INNER JOIN tbl_application_version ON tbl_application_version.registered_application_id = tbl_registered_application.id
WHERE tbl_application_version.id = application_version_id;
UPDATE tbl_registered_application_metadata SET feedbackcount = (feedbackcount + 1), lastfeedbackdate = NEW.createddate WHERE id = app_metadata_id;
UPDATE tbl_application_version_metadata SET feedbackcount = (feedbackcount + 1), lastfeedbackdate = NEW.createddate WHERE id = app_version_metadata_id;
RETURN NEW;
ELSIF (TG_OP = 'DELETE') THEN
-- IMPLEMENT THIS TRIGGER
RETURN NULL;
END IF;
END;
$$
LANGUAGE 'plpgsql';
ALTER FUNCTION update_total_feedback_count() OWNER TO feedback_tracker;
However, when I deploy my WAR file, I get an error saying something like this:
Unterminated dollar quote started at position 65 in SQL CREATE
FUNCTION my_function() RETURNS TRIGGER AS $$
So, clearly it's dying on the $$ in my function declaration. Is there a way around this? Should I be declaring my function/trigger differently? Is there a property I can set in my persistence.xml file that will get around this?
the problem with hibernate's default SqlStatementParser implementation, which is used in multiline sql command extractor.
if you look at grammar definition hibernate-core/src/main/antlr/sql-stmt.g there is definition of Statement End:
STMT_END
: ';' ( '\t' | ' ' | '\r' | '\n' )*
;
NOT_STMT_END
: ~( ';' )
;
This tells that statement end is semicolon symbol followed by "Space" "tab" "carret return" or "new line" symbols.
THUS: DEFAULT IMPLEMENTATION IN HIBERNATE DOESN'T SUPPORT DOLLAR QUOTING.
If you don't want to implement custom hibernate's parser you can rewrite all functions without dollar quoting, using simple ' quoting. But you will need to carefully escape ' chars.
UPDATE: you can create your custom ImportSqlCommandExtractor. For example: separate your commands with --****** (6 star symbols in comment, just to make your file proper SQL file, but with custom command separation in comments, or choose any insane combination, which you like) and then split those in simple implementation
public class ImportSqlCE implements ImportSqlCommandExtractor {
private static final Logger log = LoggerFactory.getLogger(ImportSqlCE.class);
#Override
public String[] extractCommands(Reader reader) {
try {
String allCommands = IOUtils.toString(reader);
return allCommands.split("--******");
} catch (IOException e) {
log.error("error reading import commands", e);
log.info("sengind default empty command set");
return new String[0];
}
}
}
and then configure hibernate to use it <property name="hibernate.hbm2ddl.import_files_sql_extractor" value="example.ImportSqlCE" />
with this your import.sql will support dollar quoting (i.e. it will simply ignore any sql awareness of what is happening.)

How to pass a null value received on msg.req.query to msg.payload

I am developing an application using Dashdb on Bluemix and nodered, my PHP application uses the call to webservice to invoke the node-red, whenever my function on PHP invokes the node to insert on table and the field GEO_ID is null, the application fails, I understand the issue, it seems the third parameter was not informed, I have just tried to check the param before and passing something like NULL but it continues not working.
See the code:
msg.account_id = msg.req.query.account_id;
msg.user_id = msg.req.query.user_id;
msg.geo_id=msg.req.query.geo_id;
msg.payload = "INSERT INTO ACCOUNT_USER (ACCOUNT_ID, USER_ID, GEO_ID) VALUES (?,?,?) ";
return msg;
And on Dashdb component I have set the parameter as below:
msg.account_id,msg.user_id,msg.geo_id
The third geo_id is the issue, I have tried something like the code below:
if(msg.req.query.geo_id===null){msg.geo_id=null}
or
if(msg.req.query.geo_id===null){msg.geo_id="null"}
The error I got is the one below:
dashDB query node: Error: [IBM][CLI Driver][DB2/LINUXX8664] SQL0420N Invalid character found in a character string argument of the function "DECIMAL". SQLSTATE=22018
I really appreciate if someone could help me on it .
Thanks,
Eduardo Diogo Garcia
Is it possible that msg.req.query.geo_id is set to an empty string?
In that case neither if statement above would get executed, and you would be trying to insert an empty string into a DECIMAL column. Maybe try something like this:
if (! msg.req.query.geo_id || msg.req.query.geo_id == '') {
msg.geo_id = null;
}

What is the purpose of this test case here?

Could someone explain what this code is doing to me? I don't understand the purpose of the system.debug lines.
Test.startTest();
// 1. First check to see if it's a brand new Owner ID
System.debug('first test'); // Creating a new opportunity to start Trigger
Opportunity newtestOpp1 = TestUtil.initOpportunity(TestUtil.initAccount(),TestUtil.initContact());
User testUser1 = TestUtil.initUser();
newtestOpp1.OwnerId = testUser1.Id;//setting OwnerId
System.debug('The opp owner should be null' + newtestOpp1.Op_Owner__c);
try{
insert newtestOpp1;
} catch ( DMLException d ) {
System.debug(d);
}
System.debug('The opp owner should not be null' + newtestOpp1.Op_Owner__c);
Looks to me like it's supposed to be testing whether some kind of workflow or trigger is setting a value in the Op_Owner__c field upon inserting an Opportunity record. The debug statements should actually be System.assert or System.assertEquals calls though, if the test is meant to actually verify the application's functionality. Debug statements aren't typically viewed during test case execution.
Here's a cleaned-up version that actually makes assertions about the Op_Owner__c field's value (which is the purpose of a test case), rather than just printing something to the debug log.
Test.startTest();
Opportunity newtestOpp1 = TestUtil.initOpportunity(TestUtil.initAccount(),TestUtil.initContact());
User testUser1 = TestUtil.initUser();
newtestOpp1.OwnerId = testUser1.Id;//setting OwnerId
System.assertEquals(null, newtestOpp1.Op_Owner__c, 'The opp owner should be null');
try{
insert newtestOpp1;
} catch ( DMLException d ) {
System.debug(d);
}
System.assertNotEquals(null, newtestOpp1.Op_Owner__c, 'The opp owner should not be null');