Repository navigation
Arguments to SQL functions are nullable by default #940
Description
Activity
- addedenhancementNew feature or requestNew feature or request
on Mar 11, 2021 I looked into this in a more detail and it looks like the underlying
github.com/lfittl/pg_query_godoes not return the correct information.Given the following example:
package main import ( "fmt" pg_query "github.com/lfittl/pg_query_go" ) func main() { tree, err := pg_query.ParseToJSON(`CREATE OR REPLACE FUNCTION select1(_id INTEGER) RETURNS SETOF foo as $func$ BEGIN IF _id IS NULL THEN RETURN QUERY EXECUTE 'select * from foo where id IS NULL'; ELSE RETURN QUERY EXECUTE FORMAT('select * from foo where id = %L', _id); END IF; END $func$ LANGUAGE plpgsql CALLED ON NULL INPUT;`) if err != nil { panic(err) } fmt.Printf("%s\n", tree) }
I get this output:
[ { "RawStmt": { "stmt": { "CreateFunctionStmt": { "replace": true, "funcname": [ { "String": { "str": "select1" } } ], "parameters": [ { "FunctionParameter": { "name": "_id", "argType": { "TypeName": { "names": [ { "String": { "str": "pg_catalog" } }, { "String": { "str": "int4" } } ], "typemod": -1, "location": 39 } }, "mode": 105 } } ], "returnType": { "TypeName": { "names": [ { "String": { "str": "foo" } } ], "setof": true, "typemod": -1, "location": 64 } }, "options": [ { "DefElem": { "defname": "as", "arg": [ { "String": { "str": "\nBEGIN\n IF _id IS NULL THEN\n RETURN QUERY EXECUTE 'select * from foo where id IS NULL';\n ELSE\n RETURN QUERY EXECUTE FORMAT('select * from foo where id = %L', _id);\n END IF;\nEND\n" } } ], "defaction": 0, "location": 68 } }, { "DefElem": { "defname": "language", "arg": { "String": { "str": "plpgsql" } }, "defaction": 0, "location": 270 } }, { "DefElem": { "defname": "strict", "arg": { "Integer": { "ival": 0 } }, "defaction": 0, "location": 287 } } ] } }, "stmt_len": 307 } } ]The interesting part is the last DefElem, which is
strict, but we would expect it to becalled on null input.In order to allow nullable inputs for sql functions, the this line (https://github.com/kyleconroy/sqlc/blob/master/internal/compiler/resolve.go#L267) would needed to be changed returning
falseinstead oftrue.
But this change obviously breaks several unit tests as well as it would break the code for all existing users. So the question is, what is the best way to fix this. Either some sort of configuration or the above mentioned breaking change.I believe that both
sqlc.nargand #2800 solve this issue. We'll also want to revisit the default nullability at some point in the future, but it's a backwards incompatible change right now.
While working on a solution for #364 which is based on SQL functions, I hit the following problem.
Arguments for SQL functions in PostgreSQL are nullable by default. With
CALLED ON NULL INPUT, this can even be explicitly stated, but this is ignored bysqlc.Given the following definition for PostgreSQL:
the following SQL calls are valid:
With the query definition:
the following Go method signature is generated:
With this method signature it is not possible to pass
nil(or SQLnull) as argument forID.Update: fix typo