-
Notifications
You must be signed in to change notification settings - Fork 813
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
Generate nullable value from subselect statements #2275
base: main
Are you sure you want to change the base?
Conversation
03ea5bc
to
c99d5f6
Compare
internal/endtoend/testdata/nullable_subselect/mysql/go/query.sql.go
Outdated
Show resolved
Hide resolved
internal/endtoend/testdata/nullable_subselect/postgresql/pgx/v4/go/query.sql.go
Outdated
Show resolved
Hide resolved
internal/endtoend/testdata/select_nested_count/mysql/go/query.sql.go
Outdated
Show resolved
Hide resolved
a3bbb0d
to
c99d5f6
Compare
👀 |
@ryu-ichiroh Could you please rebase and regenerate your test output with 1.19.1? I am a bit concerned about this being a backwards incompatible change, but am leaning towards accepting this as subselects that can return NULL can't be used today without |
Sure. |
c99d5f6
to
f78aaca
Compare
I've finished. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me have more time. I'll improve.
093ea55
to
ccf2267
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kyleconroy
I've finished to fix all. Could you please review this again?
if !(first.IsFuncCall && strings.EqualFold(first.FuncName, "count")) { | ||
first.NotNull = false | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've researched about cases a subselect returns null.
A column of no rows returns null. but if count()
return 0.
- https://www.postgresql.org/docs/15/functions-aggregate.html
- https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html
- https://www.sqlite.org/lang_aggfunc.html
According to above documentation, total()
also returns 0 in sqlite.
Other aggregate functions returns null.
const countRowsEmptyTable = `-- name: CountRowsEmptyTable :many | ||
SELECT a, (SELECT count(a) FROM empty) as "count" FROM foo | ||
` | ||
|
||
type CountRowsEmptyTableRow struct { | ||
A int32 | ||
Count int64 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
count() returns non-null.
const firstRowFromEmptyTable = `-- name: FirstRowFromEmptyTable :many | ||
SELECT a, (SELECT a FROM empty limit 1) as "first" FROM foo | ||
` | ||
|
||
type FirstRowFromEmptyTableRow struct { | ||
A int32 | ||
First sql.NullInt32 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When retrieving the first row, it returns null.
|
||
func (q *Queries) BarExists(ctx context.Context, id int64) (int64, error) { | ||
func (q *Queries) BarExists(ctx context.Context, id int64) (sql.NullInt64, error) { | ||
row := q.db.QueryRowContext(ctx, barExists, id) | ||
var column_1 int64 | ||
var column_1 sql.NullInt64 | ||
err := row.Scan(&column_1) | ||
return column_1, err | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-- name: BarExists :one
SELECT
EXISTS (
SELECT
1
FROM
bar
where
id = ?
)
This is a regression. 😞
I understand that EXISTS
doesn't return null. so It should be generated as non-null.
There are no tests of select_exists
in MySQL, I think the same issue occur.
It doesn't occurred the issue in MySQL, because it is parsed ast.SubLink
.
This is the issue specific to SQLite only.
I displayed the ast, but I couldn't find EXISTS clause.
Do you have any idea?
Expand to see AST.
&ast.SelectStmt{
DistinctClause: (*ast.List)(nil),
IntoClause: (*ast.IntoClause)(nil),
TargetList: &ast.List{
Items: []ast.Node{
&ast.ResTarget{
Name: (*string)(nil),
Indirection: (*ast.List)(nil),
Val: &ast.SelectStmt{
DistinctClause: (*ast.List)(nil),
IntoClause: (*ast.IntoClause)(nil),
TargetList: &ast.List{
Items: []ast.Node{
&ast.ResTarget{
Name: (*string)(nil),
Indirection: (*ast.List)(nil),
Val: &ast.A_Const{
Val: &ast.Integer{
Ival: 1,
},
Location: 134,
},
Location: 134,
},
},
},
FromClause: &ast.List{
Items: []ast.Node{
&ast.RangeVar{
Catalogname: (*string)(nil),
Schemaname: (*string)(nil),
Relname: &"bar",
Inh: false,
Relpersistence: 0x00,
Alias: (*ast.Alias)(nil),
Location: 161,
},
},
},
WhereClause: &ast.A_Expr{
Kind: 0x0,
Name: &ast.List{
Items: []ast.Node{
&ast.String{
Str: "=",
},
},
},
Lexpr: &ast.ColumnRef{
Name: "",
Fields: &ast.List{
Items: []ast.Node{
&ast.String{
Str: "id",
},
},
},
Location: 191,
},
Rexpr: &ast.ParamRef{
Number: 1,
Location: 196,
Dollar: false,
},
Location: 0,
},
GroupClause: &ast.List{
Items: []ast.Node{},
},
HavingClause: nil,
WindowClause: &ast.List{
Items: []ast.Node{},
},
ValuesLists: &ast.List{
Items: []ast.Node{},
},
SortClause: (*ast.List)(nil),
LimitOffset: nil,
LimitCount: nil,
LockingClause: (*ast.List)(nil),
WithClause: &ast.WithClause{
Ctes: &ast.List{
Items: []ast.Node{},
},
Recursive: false,
Location: 0,
},
Op: 0x0,
All: false,
Larg: (*ast.SelectStmt)(nil),
Rarg: (*ast.SelectStmt)(nil),
},
Location: 98,
},
},
},
FromClause: &ast.List{
Items: []ast.Node{},
},
WhereClause: nil,
GroupClause: &ast.List{
Items: []ast.Node{},
},
HavingClause: nil,
WindowClause: &ast.List{
Items: []ast.Node{},
},
ValuesLists: &ast.List{
Items: []ast.Node{},
},
SortClause: (*ast.List)(nil),
LimitOffset: nil,
LimitCount: nil,
LockingClause: (*ast.List)(nil),
WithClause: &ast.WithClause{
Ctes: &ast.List{
Items: []ast.Node{},
},
Recursive: false,
Location: 0,
},
Op: 0x0,
All: false,
Larg: (*ast.SelectStmt)(nil),
Rarg: (*ast.SelectStmt)(nil),
}
4af7fac
to
bc23ccc
Compare
Hi maintainers.
Change subselect statements containing WHERE/HAVING clauses to be NULL.
Resolves: #1208