Skip to content

RETURNS SETOF <table name> should return the correct DB model instead of []interface{} #941

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
breml opened this issue Mar 11, 2021 · 2 comments

Comments

@breml
Copy link

breml commented Mar 11, 2021

While working on a solution for #364 which is based on SQL functions, I hit the following problem.

The Go methods generated from calls to SQL functions, that return SETOF, should return the correct DB model.

Same example as in #940.

Given the following definition for PostgreSQL:

CREATE TABLE foo (
            id     INTEGER,
            bar    varchar(100)
);

INSERT INTO foo VALUES (null, 'foo'), (1, 'bar');

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;

and the query definition:

-- name: GetSelect1 :many
SELECT select1($1);

the following Go method signature is generated:

func (q *Queries) GetSelect1(ctx context.Context, ID int32) ([]interface{}, error) {

This Go method does return []interface{} instead of []Foo from models.go.

Update: fix typo

@breml
Copy link
Author

breml commented Mar 18, 2021

With to small extensions, it is possible to let sqlc generate the correct return value for this (see: breml@f2ffd6a). The resulting code does not (yet) work though, because the postgresql driver does not manage to scan the result into the given struct. I assume, that there is a problem in the way the return value of type record is handled by the driver. The error message is:

2021/03/18 07:28:37 sql: Scan error on column index 0, name "select1": unsupported Scan, storing driver.Value type string into type *db.Foo2

The current result is always of type string, where the fields are enclosed in brackets like this: (1, bar).

@kyleconroy
Copy link
Collaborator

kyleconroy commented Oct 6, 2023

By using the SELECT select1($1) form, you're returning a row type. Composite types aren't supported in lib/pq, but are in pgx. That said, sqlc doesn't support them yet. We're tracking that here #2760.

That said, if you select from the function instead, sqlc generates the correct code.

-- name: GetSelect1 :many
SELECT * FROM select1($1);

https://play.sqlc.dev/p/bc5f900f6b4e5a891dbc7b47b3175c22f5e8eb6003d83ba0ab78bc7aba331c96

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants