Skip to content

Commit 02d449f

Browse files
authored
fix(compiler): Detect invalid INSERT expression (#1231)
Return an error if you're trying to insert too many columns for the given table. Before the same query would have paniced.
1 parent fab267e commit 02d449f

File tree

11 files changed

+86
-6
lines changed

11 files changed

+86
-6
lines changed

internal/compiler/find_params.go

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
package compiler
22

33
import (
4+
"fmt"
5+
46
"github.com/kyleconroy/sqlc/internal/sql/ast"
57
"github.com/kyleconroy/sqlc/internal/sql/astutils"
68
)
79

8-
func findParameters(root ast.Node) []paramRef {
10+
func findParameters(root ast.Node) ([]paramRef, error) {
911
refs := make([]paramRef, 0)
10-
v := paramSearch{seen: make(map[int]struct{}), refs: &refs}
12+
errors := make([]error, 0)
13+
v := paramSearch{seen: make(map[int]struct{}), refs: &refs, errs: &errors}
1114
astutils.Walk(v, root)
12-
return refs
15+
if len(*v.errs) > 0 {
16+
problems := *v.errs
17+
return nil, problems[0]
18+
} else {
19+
return refs, nil
20+
}
1321
}
1422

1523
type paramRef struct {
@@ -24,6 +32,7 @@ type paramSearch struct {
2432
rangeVar *ast.RangeVar
2533
refs *[]paramRef
2634
seen map[int]struct{}
35+
errs *[]error
2736

2837
// XXX: Gross state hack for limit
2938
limitCount ast.Node
@@ -45,6 +54,10 @@ func (l *limitOffset) Pos() int {
4554
}
4655

4756
func (p paramSearch) Visit(node ast.Node) astutils.Visitor {
57+
if len(*p.errs) > 0 {
58+
return p
59+
}
60+
4861
switch n := node.(type) {
4962

5063
case *ast.A_Expr:
@@ -64,7 +77,10 @@ func (p paramSearch) Visit(node ast.Node) astutils.Visitor {
6477
if !ok {
6578
continue
6679
}
67-
// TODO: Out-of-bounds panic
80+
if len(n.Cols.Items) <= i {
81+
*p.errs = append(*p.errs, fmt.Errorf("INSERT has more expressions than target columns"))
82+
return p
83+
}
6884
*p.refs = append(*p.refs, paramRef{parent: n.Cols.Items[i], ref: ref, rv: n.Relation})
6985
p.seen[ref.Location] = struct{}{}
7086
}
@@ -78,7 +94,10 @@ func (p paramSearch) Visit(node ast.Node) astutils.Visitor {
7894
if !ok {
7995
continue
8096
}
81-
// TODO: Out-of-bounds panic
97+
if len(n.Cols.Items) <= i {
98+
*p.errs = append(*p.errs, fmt.Errorf("INSERT has more expressions than target columns"))
99+
return p
100+
}
82101
*p.refs = append(*p.refs, paramRef{parent: n.Cols.Items[i], ref: ref, rv: n.Relation})
83102
p.seen[ref.Location] = struct{}{}
84103
}

internal/compiler/parse.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
7979

8080
raw, namedParams, edits := rewrite.NamedParameters(c.conf.Engine, raw, numbers, dollar)
8181
rvs := rangeVars(raw.Stmt)
82-
refs := findParameters(raw.Stmt)
82+
refs, err := findParameters(raw.Stmt)
83+
if err != nil {
84+
return nil, err
85+
}
8386
if o.UsePositionalParameters {
8487
edits, err = rewriteNumberedParameters(refs, raw, rawSQL)
8588
if err != nil {
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE foo (bar text);
2+
3+
-- name: InsertFoo :exec
4+
INSERT INTO foo (bar)
5+
SELECT 1, ?, ?;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"engine": "mysql",
6+
"path": "go",
7+
"name": "querytest",
8+
"schema": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# package querytest
2+
query.sql:4:1: INSERT has more expressions than target columns
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE foo (bar text);
2+
3+
-- name: InsertFoo :exec
4+
INSERT INTO foo (bar)
5+
SELECT 1, $1, $2;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"path": "go",
6+
"engine": "postgresql",
7+
"sql_package": "pgx/v4",
8+
"name": "querytest",
9+
"schema": "query.sql",
10+
"queries": "query.sql"
11+
}
12+
]
13+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# package querytest
2+
query.sql:4:1: INSERT has more expressions than target columns
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
CREATE TABLE foo (bar text);
2+
3+
-- name: InsertFoo :exec
4+
INSERT INTO foo (bar)
5+
SELECT 1, $1, $2;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"engine": "postgresql",
6+
"path": "go",
7+
"name": "querytest",
8+
"schema": "query.sql",
9+
"queries": "query.sql"
10+
}
11+
]
12+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# package querytest
2+
query.sql:4:1: INSERT has more expressions than target columns

0 commit comments

Comments
 (0)