Repository: sqlc-dev/sqlc
Pull request #2660 (2023-08-26 14:44:05)

refactor(astutils): remove redundant nil check in `Walk`
From the Go docs:

>  "For a nil slice, the number of iterations is 0." https://go.dev/ref/spec#For_range

Therefore, an additional nil check for before the loop is unnecessary. Example: https://go.dev/play/p/tMQ9JcUOMcI


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e2e3a2f63..a163dd023 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,7 +12,7 @@ jobs:
     - uses: actions/checkout@v3
     - uses: actions/setup-go@v4
       with:
-        go-version: '1.20.7'
+        go-version: '1.21.0'
     - run: go build ./...
 
   darwin-build:
@@ -22,7 +22,7 @@ jobs:
     - uses: actions/checkout@v3
     - uses: actions/setup-go@v4
       with:
-        go-version: '1.20.7'
+        go-version: '1.21.0'
     - run: go build ./...
 
   build:
@@ -53,7 +53,7 @@ jobs:
     - uses: actions/checkout@v3
     - uses: actions/setup-go@v4
       with:
-        go-version: '1.20.7'
+        go-version: '1.21.0'
 
     - name: gotestsum
       run: go install gotest.tools/gotestsum@latest
@@ -92,6 +92,6 @@ jobs:
     - uses: actions/checkout@v3
     - uses: actions/setup-go@v4
       with:
-        go-version: '1.20.7'
+        go-version: '1.21.0'
     - run: go install golang.org/x/vuln/cmd/govulncheck@latest
-    - run: govulncheck ./...
+    - run: govulncheck ./...
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 038cc5bde..39961ebb0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
 /.idea/
 __pycache__
 .DS_Store
+.*.swp
 
 # Devenv
 .envrc
diff --git a/Dockerfile b/Dockerfile
index ad3b62088..e6c258e69 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 # STEP 1: Build sqlc
-FROM golang:1.20.7 AS builder
+FROM golang:1.21.0 AS builder
 
 COPY . /workspace
 WORKDIR /workspace
diff --git a/docs/requirements.txt b/docs/requirements.txt
index c4ce70119..eeb70a317 100644
--- a/docs/requirements.txt
+++ b/docs/requirements.txt
@@ -9,7 +9,7 @@ imagesize==1.4.1
 Jinja2==3.1.2
 MarkupSafe==2.1.3
 packaging==23.1
-Pygments==2.15.1
+Pygments==2.16.1
 pyparsing==3.1.1
 pytz==2023.3
 recommonmark==0.7.1
@@ -18,10 +18,10 @@ snowballstemmer==2.2.0
 Sphinx==6.2.1
 sphinx-favicon==1.0.1
 sphinx-rtd-theme==1.2.2
-sphinxcontrib-applehelp==1.0.4
+sphinxcontrib-applehelp==1.0.7
 sphinxcontrib-devhelp==1.0.2
-sphinxcontrib-serializinghtml==1.1.5
+sphinxcontrib-serializinghtml==1.1.9
 sphinxcontrib-htmlhelp==2.0.1
 sphinxcontrib-jsmath==1.0.1
-sphinxcontrib-qthelp==1.0.3
+sphinxcontrib-qthelp==1.0.6
 urllib3==2.0.4
diff --git a/go.mod b/go.mod
index abda565ec..0c9f4e145 100644
--- a/go.mod
+++ b/go.mod
@@ -8,11 +8,11 @@ require (
 	github.com/cubicdaiya/gonp v1.0.4
 	github.com/davecgh/go-spew v1.1.1
 	github.com/go-sql-driver/mysql v1.7.1
-	github.com/google/cel-go v0.17.1
+	github.com/google/cel-go v0.17.6
 	github.com/google/go-cmp v0.5.9
 	github.com/jackc/pgconn v1.14.1
 	github.com/jackc/pgx/v4 v4.18.1
-	github.com/jackc/pgx/v5 v5.4.2
+	github.com/jackc/pgx/v5 v5.4.3
 	github.com/jinzhu/inflection v1.0.0
 	github.com/lib/pq v1.10.9
 	github.com/mattn/go-sqlite3 v1.14.17
@@ -33,6 +33,7 @@ require (
 
 require (
 	github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
+	github.com/fatih/structtag v1.2.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/inconshreveable/mousetrap v1.1.0 // indirect
 	github.com/jackc/chunkreader/v2 v2.0.1 // indirect
diff --git a/go.sum b/go.sum
index 0c2b1ab1f..7ac2f0456 100644
--- a/go.sum
+++ b/go.sum
@@ -20,6 +20,8 @@ github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
+github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
 github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
@@ -36,8 +38,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
 github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/google/cel-go v0.17.1 h1:s2151PDGy/eqpCI80/8dl4VL3xTkqI/YubXLXCFw0mw=
-github.com/google/cel-go v0.17.1/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
+github.com/google/cel-go v0.17.6 h1:QDvHTIJunIsbgN8yVukx0HGnsqVLSY6xGqo+17IjIyM=
+github.com/google/cel-go v0.17.6/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY=
 github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@@ -93,8 +95,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ
 github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
 github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
 github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
-github.com/jackc/pgx/v5 v5.4.2 h1:u1gmGDwbdRUZiwisBm/Ky2M14uQyUP65bG8+20nnyrg=
-github.com/jackc/pgx/v5 v5.4.2/go.mod h1:q6iHT8uDNXWiFNOlRqJzBTaSH3+2xCXkokxHZC5qWFY=
+github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
+github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
 github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
 github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
diff --git a/internal/config/go_type.go b/internal/config/go_type.go
index 078360e57..14765e5f3 100644
--- a/internal/config/go_type.go
+++ b/internal/config/go_type.go
@@ -6,6 +6,8 @@ import (
 	"go/types"
 	"regexp"
 	"strings"
+
+	"github.com/fatih/structtag"
 )
 
 type GoType struct {
@@ -171,16 +173,12 @@ type GoStructTag string
 // `a:"b" x:"y,z"`   {"a": "b", "x": "y,z"}
 func (s GoStructTag) Parse() (map[string]string, error) {
 	m := make(map[string]string)
-	fields := strings.Fields(string(s))
-	for _, f := range fields {
-		k, v, ok := strings.Cut(f, ":")
-		if !ok {
-			return nil, fmt.Errorf("Failed to parse Go struct tag: no colon in field %q", f)
-		}
-		if len(v) < 2 || v[0] != '"' || v[len(v)-1] != '"' {
-			return nil, fmt.Errorf("Failed to parse Go struct tag: missing quotes around value in field %q", f)
-		}
-		m[k] = v[1 : len(v)-1] // trim quotes off of v
+	tags, err := structtag.Parse(string(s))
+	if err != nil {
+		return nil, err
+	}
+	for _, tag := range tags.Tags() {
+		m[tag.Key] = tag.Value()
 	}
 	return m, nil
 }
diff --git a/internal/sql/astutils/walk.go b/internal/sql/astutils/walk.go
index 9f26617ad..0943379f0 100644
--- a/internal/sql/astutils/walk.go
+++ b/internal/sql/astutils/walk.go
@@ -2158,10 +2158,8 @@ func Walk(f Visitor, node ast.Node) {
 		}
 
 	case *ast.In:
-		if n.List != nil {
-			for _, l := range n.List {
-				Walk(f, l)
-			}
+		for _, l := range n.List {
+			Walk(f, l)
 		}
 		if n.Sel != nil {
 			Walk(f, n.Sel)


Test patch:
diff --git a/internal/endtoend/testdata/overrides_go_struct_tags/invalid_tags/stderr.txt b/internal/endtoend/testdata/overrides_go_struct_tags/invalid_tags/stderr.txt
index 4624d612a..cb6fb84ae 100644
--- a/internal/endtoend/testdata/overrides_go_struct_tags/invalid_tags/stderr.txt
+++ b/internal/endtoend/testdata/overrides_go_struct_tags/invalid_tags/stderr.txt
@@ -1,1 +1,1 @@
-error parsing sqlc.json: Failed to parse Go struct tag: no colon in field "abc"
+error parsing sqlc.json: bad syntax for struct tag pair
diff --git a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/go/models.go b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/go/models.go
index 5942323c9..bb63a04c3 100644
--- a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/go/models.go
+++ b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/go/models.go
@@ -9,14 +9,17 @@ import ()
 type Bar struct {
 	Other      string
 	AlsoTagged string `also:"tagged"`
+	Tag3       string `tag_with_space:" it's legal!"`
 }
 
 type Baz struct {
 	Other      string
 	AlsoTagged string `also:"tagged"`
+	Tag3       string `tag_with_space:" it's legal!"`
 }
 
 type Foo struct {
 	Other  string
 	Tagged string `a:"b" x:"y,z"`
+	Tag3   string `tag_with_space:" it's legal!"`
 }
diff --git a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/schema.sql b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/schema.sql
index 4d5233cc3..f908060db 100644
--- a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/schema.sql
+++ b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/schema.sql
@@ -1,14 +1,17 @@
 CREATE TABLE foo (
     other     text NOT NULL,
-    tagged    text NOT NULL
+    tagged    text NOT NULL,
+    tag3      text NOT NULL
 );
 
 CREATE TABLE bar (
     other          text NOT NULL,
-    also_tagged    text NOT NULL
+    also_tagged    text NOT NULL,
+    tag3           text NOT NULL
 );
 
 CREATE TABLE baz (
     other          text NOT NULL,
-    also_tagged    text NOT NULL
+    also_tagged    text NOT NULL,
+    tag3           text NOT NULL
 );
diff --git a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/sqlc.json b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/sqlc.json
index 0be626d44..a4d54cc3d 100644
--- a/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/sqlc.json
+++ b/internal/endtoend/testdata/overrides_go_struct_tags/sqlite/sqlc.json
@@ -15,6 +15,10 @@
         {
           "go_struct_tag": "also:\"tagged\"",
           "column": "*.also_tagged"
+        },
+        {
+          "go_struct_tag": "tag_with_space:\" it's legal!\"",
+          "column": "*.tag3"
         }
       ]
     }