Skip to content

Commit 409d2fb

Browse files
fix: change type precedence auto-selection to data type any, to allow user more freedom to choose query column type
1 parent d0cbfe4 commit 409d2fb

File tree

3 files changed

+88
-30
lines changed

3 files changed

+88
-30
lines changed

internal/compiler/output_columns.go

Lines changed: 44 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ func (c *Compiler) outputColumns(qc *QueryCatalog, node ast.Node) ([]*Column, er
132132
if res.Name != nil {
133133
name = *res.Name
134134
}
135-
cols = append(cols, convertAConstToColumn(n, name))
135+
col := convertAConstToColumn(n, name)
136+
if col.DataType == "null" {
137+
col.DataType = "any"
138+
}
139+
cols = append(cols, col)
136140

137141
case *ast.A_Expr:
138142
name := ""
@@ -164,50 +168,67 @@ func (c *Compiler) outputColumns(qc *QueryCatalog, node ast.Node) ([]*Column, er
164168
cols = append(cols, &Column{Name: name, DataType: "bool", NotNull: notNull})
165169

166170
case *ast.CaseExpr:
167-
name := ""
171+
var name string
168172
if res.Name != nil {
169173
name = *res.Name
170174
}
171175

172-
typePrecedence := map[string]int{
173-
"any": 0,
174-
"bool": 1,
175-
"int": 2,
176-
"pg_catalog.int4": 2,
177-
"float": 3,
178-
"pg_catalog.float8": 3,
179-
"text": 4,
180-
}
181-
182-
chosenType := "any"
176+
chosenType := ""
183177
chosenNullable := false
178+
184179
for _, i := range n.Args.Items {
185180
cw := i.(*ast.CaseWhen)
186-
col, err := convertCaseExprCondToColumn(cw.Result, res.Name)
181+
col, err := convertCaseExprCondToColumn(cw.Result, &name)
187182
if err != nil {
188183
return nil, err
189184
}
190-
if typePrecedence[col.DataType] > typePrecedence[chosenType] {
191-
chosenType = col.DataType
185+
if col.DataType == "null" {
186+
// we don't choose type from this column if its value is null, only choose nullability
187+
chosenNullable = true
188+
continue
189+
}
190+
if col.DataType != chosenType {
191+
if chosenType == "" {
192+
chosenType = col.DataType
193+
} else {
194+
chosenType = "any"
195+
}
192196
}
193197
if !col.NotNull {
194198
chosenNullable = true
195199
}
196200
}
197201

198-
if n.Defresult != nil {
199-
defaultCol, err := convertCaseExprCondToColumn(n.Defresult, res.Name)
202+
var defaultCol *Column
203+
if n.Defresult.Pos() != 0 {
204+
defaultCol, err = convertCaseExprCondToColumn(n.Defresult, &name)
200205
if err != nil {
201206
return nil, err
202207
}
203-
if typePrecedence[defaultCol.DataType] > typePrecedence[chosenType] {
204-
chosenType = defaultCol.DataType
208+
} else {
209+
defaultCol = &Column{Name: name, DataType: "null", NotNull: false}
210+
}
211+
212+
if defaultCol.DataType == "null" {
213+
// we don't choose type from this column if its value is null, only choose nullability
214+
chosenNullable = true
215+
} else {
216+
if defaultCol.DataType != chosenType {
217+
if chosenType == "" {
218+
chosenType = defaultCol.DataType
219+
} else {
220+
chosenType = "any"
221+
}
205222
}
206223
if !defaultCol.NotNull {
207224
chosenNullable = true
208225
}
209226
}
210227

228+
if chosenType == "" {
229+
chosenType = "any"
230+
}
231+
211232
chosenColumn := &Column{Name: name, DataType: chosenType, NotNull: !chosenNullable}
212233
cols = append(cols, chosenColumn)
213234

@@ -811,7 +832,7 @@ func convertAExprToColumn(aexpr *ast.A_Expr, name string) *Column {
811832
return col
812833
}
813834

814-
func convertAConstToColumn(aconst *ast.A_Const, name string) *Column {
835+
func convertAConstToColumn(aconst *ast.A_Const, name string) (*Column) {
815836
var col *Column
816837
switch aconst.Val.(type) {
817838
case *ast.String:
@@ -822,6 +843,8 @@ func convertAConstToColumn(aconst *ast.A_Const, name string) *Column {
822843
col = &Column{Name: name, DataType: "float", NotNull: true}
823844
case *ast.Boolean:
824845
col = &Column{Name: name, DataType: "bool", NotNull: true}
846+
case *ast.Null:
847+
col = &Column{Name: name, DataType: "null", NotNull: false}
825848
default:
826849
col = &Column{Name: name, DataType: "any", NotNull: false}
827850
}

internal/endtoend/testdata/json_traversal_as_select_expr_with_type_cast/postgresql/pgx/go/query.sql.go

Lines changed: 37 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/json_traversal_as_select_expr_with_type_cast/postgresql/pgx/query.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,11 @@ SELECT CASE
8080
WHEN id = 2 THEN null
8181
ELSE 7 - id
8282
END
83+
FROM "mytable";
84+
85+
-- name: GetNullable2G :many
86+
SELECT CASE
87+
WHEN id = 2 THEN null
88+
ELSE null
89+
END
8390
FROM "mytable";

0 commit comments

Comments
 (0)