Skip to content

Commit a22a7b7

Browse files
authored
feat: Add sqlc.narg() for nullable named params (#1536)
* refactor named parameters to use specific type * refactor rewrite.NamedParameters to use types * add "inferred null" vs "user defined null" * test: add tests for named.Param * test: add tests for optional and required parameters * add named.ParamSet to represent a set of parameters in a query * add sqlc.narg for params users can override to nullable * add end-to-end test for sqlc.narg * commit generated output for sqlc.narg
1 parent ad17102 commit a22a7b7

File tree

27 files changed

+1244
-142
lines changed

27 files changed

+1244
-142
lines changed

internal/compiler/parse.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
107107
if err != nil {
108108
return nil, err
109109
}
110+
110111
params, err := c.resolveCatalogRefs(qc, rvs, refs, namedParams)
111112
if err != nil {
112113
return nil, err

internal/compiler/resolve.go

Lines changed: 54 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/kyleconroy/sqlc/internal/sql/ast"
88
"github.com/kyleconroy/sqlc/internal/sql/astutils"
99
"github.com/kyleconroy/sqlc/internal/sql/catalog"
10+
"github.com/kyleconroy/sqlc/internal/sql/named"
1011
"github.com/kyleconroy/sqlc/internal/sql/sqlerr"
1112
)
1213

@@ -18,26 +19,14 @@ func dataType(n *ast.TypeName) string {
1819
}
1920
}
2021

21-
func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, args []paramRef, names map[int]string) ([]Parameter, error) {
22+
func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, args []paramRef, params *named.ParamSet) ([]Parameter, error) {
2223
c := comp.catalog
2324

2425
aliasMap := map[string]*ast.TableName{}
2526
// TODO: Deprecate defaultTable
2627
var defaultTable *ast.TableName
2728
var tables []*ast.TableName
2829

29-
parameterName := func(n int, defaultName string) string {
30-
if n, ok := names[n]; ok {
31-
return n
32-
}
33-
return defaultName
34-
}
35-
36-
isNamedParam := func(n int) bool {
37-
_, ok := names[n]
38-
return ok
39-
}
40-
4130
typeMap := map[string]map[string]map[string]*catalog.Column{}
4231
indexTable := func(table catalog.Table) error {
4332
tables = append(tables, table.Rel)
@@ -92,24 +81,28 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
9281
switch n := ref.parent.(type) {
9382

9483
case *limitOffset:
84+
defaultP := named.NewInferredParam("offset", true)
85+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
9586
a = append(a, Parameter{
9687
Number: ref.ref.Number,
9788
Column: &Column{
98-
Name: parameterName(ref.ref.Number, "offset"),
89+
Name: p.Name(),
9990
DataType: "integer",
100-
NotNull: true,
101-
IsNamedParam: isNamedParam(ref.ref.Number),
91+
NotNull: p.NotNull(),
92+
IsNamedParam: isNamed,
10293
},
10394
})
10495

10596
case *limitCount:
97+
defaultP := named.NewInferredParam("limit", true)
98+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
10699
a = append(a, Parameter{
107100
Number: ref.ref.Number,
108101
Column: &Column{
109-
Name: parameterName(ref.ref.Number, "limit"),
102+
Name: p.Name(),
110103
DataType: "integer",
111-
NotNull: true,
112-
IsNamedParam: isNamedParam(ref.ref.Number),
104+
NotNull: p.NotNull(),
105+
IsNamedParam: isNamed,
113106
},
114107
})
115108

@@ -127,12 +120,16 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
127120
if astutils.Join(n.Name, ".") == "||" {
128121
dataType = "string"
129122
}
123+
124+
defaultP := named.NewParam("")
125+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
130126
a = append(a, Parameter{
131127
Number: ref.ref.Number,
132128
Column: &Column{
133-
Name: parameterName(ref.ref.Number, ""),
129+
Name: p.Name(),
134130
DataType: dataType,
135-
IsNamedParam: isNamedParam(ref.ref.Number),
131+
IsNamedParam: isNamed,
132+
NotNull: p.NotNull(),
136133
},
137134
})
138135
continue
@@ -185,16 +182,19 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
185182
if ref.name != "" {
186183
key = ref.name
187184
}
185+
186+
defaultP := named.NewInferredParam(key, c.IsNotNull)
187+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
188188
a = append(a, Parameter{
189189
Number: ref.ref.Number,
190190
Column: &Column{
191-
Name: parameterName(ref.ref.Number, key),
191+
Name: p.Name(),
192192
DataType: dataType(&c.Type),
193-
NotNull: c.IsNotNull,
193+
NotNull: p.NotNull(),
194194
IsArray: c.IsArray,
195195
Length: c.Length,
196196
Table: table,
197-
IsNamedParam: isNamedParam(ref.ref.Number),
197+
IsNamedParam: isNamed,
198198
},
199199
})
200200
}
@@ -242,15 +242,17 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
242242
}
243243

244244
if c, ok := typeMap[schema][table.Name][key]; ok {
245+
defaultP := named.NewInferredParam(key, c.IsNotNull)
246+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
245247
a = append(a, Parameter{
246248
Number: number,
247249
Column: &Column{
248-
Name: parameterName(ref.ref.Number, key),
250+
Name: p.Name(),
249251
DataType: dataType(&c.Type),
250-
NotNull: c.IsNotNull,
252+
NotNull: p.NotNull(),
251253
IsArray: c.IsArray,
252254
Table: table,
253-
IsNamedParam: isNamedParam(ref.ref.Number),
255+
IsNamedParam: isNamed,
254256
},
255257
})
256258
}
@@ -309,12 +311,16 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
309311
if argName != "" {
310312
defaultName = argName
311313
}
314+
315+
defaultP := named.NewInferredParam(defaultName, false)
316+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
312317
a = append(a, Parameter{
313318
Number: ref.ref.Number,
314319
Column: &Column{
315-
Name: parameterName(ref.ref.Number, defaultName),
320+
Name: p.Name(),
316321
DataType: "any",
317-
IsNamedParam: isNamedParam(ref.ref.Number),
322+
IsNamedParam: isNamed,
323+
NotNull: p.NotNull(),
318324
},
319325
})
320326
continue
@@ -340,13 +346,15 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
340346
paramName = funcName
341347
}
342348

349+
defaultP := named.NewInferredParam(paramName, true)
350+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
343351
a = append(a, Parameter{
344352
Number: ref.ref.Number,
345353
Column: &Column{
346-
Name: parameterName(ref.ref.Number, paramName),
354+
Name: p.Name(),
347355
DataType: dataType(paramType),
348-
NotNull: true,
349-
IsNamedParam: isNamedParam(ref.ref.Number),
356+
NotNull: p.NotNull(),
357+
IsNamedParam: isNamed,
350358
},
351359
})
352360
}
@@ -399,16 +407,18 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
399407
}
400408

401409
if c, ok := tableMap[key]; ok {
410+
defaultP := named.NewInferredParam(key, c.IsNotNull)
411+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
402412
a = append(a, Parameter{
403413
Number: ref.ref.Number,
404414
Column: &Column{
405-
Name: parameterName(ref.ref.Number, key),
415+
Name: p.Name(),
406416
DataType: dataType(&c.Type),
407-
NotNull: c.IsNotNull,
417+
NotNull: p.NotNull(),
408418
IsArray: c.IsArray,
409419
Table: &ast.TableName{Schema: schema, Name: rel},
410420
Length: c.Length,
411-
IsNamedParam: isNamedParam(ref.ref.Number),
421+
IsNamedParam: isNamed,
412422
},
413423
})
414424
} else {
@@ -424,7 +434,11 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
424434
return nil, fmt.Errorf("*ast.TypeCast has nil type name")
425435
}
426436
col := toColumn(n.TypeName)
427-
col.Name = parameterName(ref.ref.Number, col.Name)
437+
defaultP := named.NewInferredParam(col.Name, col.NotNull)
438+
p, _ := params.FetchMerge(ref.ref.Number, defaultP)
439+
440+
col.Name = p.Name()
441+
col.NotNull = p.NotNull()
428442
a = append(a, Parameter{
429443
Number: ref.ref.Number,
430444
Column: col,
@@ -500,15 +514,17 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar,
500514
if ref.name != "" {
501515
key = ref.name
502516
}
517+
defaultP := named.NewInferredParam(key, c.IsNotNull)
518+
p, isNamed := params.FetchMerge(ref.ref.Number, defaultP)
503519
a = append(a, Parameter{
504520
Number: number,
505521
Column: &Column{
506-
Name: parameterName(ref.ref.Number, key),
522+
Name: p.Name(),
507523
DataType: dataType(&c.Type),
508524
NotNull: c.IsNotNull,
509525
IsArray: c.IsArray,
510526
Table: table,
511-
IsNamedParam: isNamedParam(ref.ref.Number),
527+
IsNamedParam: isNamed,
512528
},
513529
})
514530
}

internal/endtoend/testdata/sqlc_narg/mysql/go/db.go

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

internal/endtoend/testdata/sqlc_narg/mysql/go/models.go

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

0 commit comments

Comments
 (0)