diff --git a/.github/workflows/buf.yml b/.github/workflows/buf.yml index fabfc40023..7ab73c4952 100644 --- a/.github/workflows/buf.yml +++ b/.github/workflows/buf.yml @@ -1,5 +1,9 @@ name: buf -on: pull_request +on: + pull_request: + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b15a5ea75b..aa868ee9fd 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - name: install ./... run: go build ./... env: diff --git a/.github/workflows/ci-kotlin.yml b/.github/workflows/ci-kotlin.yml index a324917ed7..d791c7e727 100644 --- a/.github/workflows/ci-kotlin.yml +++ b/.github/workflows/ci-kotlin.yml @@ -3,7 +3,13 @@ on: push: branches: - main + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' pull_request: + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' jobs: build: if: false @@ -13,7 +19,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - name: install ./... run: go install ./... - uses: actions/checkout@v6 diff --git a/.github/workflows/ci-python.yml b/.github/workflows/ci-python.yml index a59bd402c3..9338a2304e 100644 --- a/.github/workflows/ci-python.yml +++ b/.github/workflows/ci-python.yml @@ -3,7 +3,13 @@ on: push: branches: - main + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' pull_request: + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' jobs: build: if: false @@ -13,7 +19,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - name: install ./... run: go install ./... - uses: actions/checkout@v6 diff --git a/.github/workflows/ci-typescript.yml b/.github/workflows/ci-typescript.yml index 7ec747a91f..5ce9b475e9 100644 --- a/.github/workflows/ci-typescript.yml +++ b/.github/workflows/ci-typescript.yml @@ -3,7 +3,13 @@ on: push: branches: - main + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' pull_request: + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' jobs: build: if: false @@ -13,7 +19,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - name: install ./... run: go install ./... - uses: actions/checkout@v6 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1ee0a8f696..3e97d4c117 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,7 +3,13 @@ on: push: branches: - main + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' pull_request: + paths-ignore: + - 'docs/**' + - '.readthedocs.yaml' jobs: build: strategy: @@ -16,7 +22,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - run: go build ./... env: CGO_ENABLED: "0" @@ -28,7 +34,7 @@ jobs: - uses: actions/checkout@v6 - uses: actions/setup-go@v6 with: - go-version: '1.26.0' + go-version: '1.26.2' - name: install gotestsum run: go install gotest.tools/gotestsum@latest diff --git a/.github/workflows/gen.yml b/.github/workflows/gen.yml index eb83825c39..94ad8f64b9 100644 --- a/.github/workflows/gen.yml +++ b/.github/workflows/gen.yml @@ -32,7 +32,7 @@ jobs: PG_PASSWORD: postgres PG_PORT: ${{ job.services.postgres.ports['5432'] }} - name: Save results - uses: actions/upload-artifact@v6 + uses: actions/upload-artifact@v7 with: name: sqlc-pg-gen-results path: gen diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 9712e405d1..7895c313e4 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,6 +10,14 @@ build: os: ubuntu-22.04 tools: python: "3.11" + jobs: + post_checkout: + # Cancel PR builds that don't touch the docs. + # https://docs.readthedocs.io/en/stable/build-customization.html#cancel-build-based-on-a-condition + - | + if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/main -- docs/ .readthedocs.yaml; then + exit 183 + fi # Build documentation in the docs/ directory with Sphinx sphinx: diff --git a/CLAUDE.md b/CLAUDE.md index 46c623bebf..395c3d7531 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -6,7 +6,7 @@ This document provides essential information for working with the sqlc codebase, ### Prerequisites -- **Go 1.26.0+** - Required for building and testing +- **Go 1.26.2+** - Required for building and testing - **Docker & Docker Compose** - Required for integration tests with databases (local development) - **Git** - For version control @@ -147,7 +147,7 @@ make start # Start database containers ### GitHub Actions Workflow - **File:** `.github/workflows/ci.yml` -- **Go Version:** 1.26.0 +- **Go Version:** 1.26.2 - **Database Setup:** Uses `sqlc-test-setup` (not Docker) to install and start PostgreSQL and MySQL directly on the runner - **Test Command:** `gotestsum --junitfile junit.xml -- --tags=examples -timeout 20m ./...` - **Additional Checks:** `govulncheck` for vulnerability scanning diff --git a/Dockerfile b/Dockerfile index 0c2b2595e3..643223b0fb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # STEP 1: Build sqlc -FROM golang:1.26.1 AS builder +FROM golang:1.26.2 AS builder COPY . /workspace WORKDIR /workspace diff --git a/docs/reference/language-support.rst b/docs/reference/language-support.rst index 20de2817d6..48840e1a3e 100644 --- a/docs/reference/language-support.rst +++ b/docs/reference/language-support.rst @@ -26,6 +26,7 @@ PHP `lcarilla/sqlc-plugin-php-dbal`_ Beta N/A Ruby `DaredevilOSS/sqlc-gen-ruby`_ Beta Beta Beta Zig `tinyzimmer/sqlc-gen-zig`_ N/A Beta Beta Python `rayakame/sqlc-gen-better-python`_ N/A Beta Beta +Rust `mathematic-inc/sqlc-gen-sqlx`_ N/A Beta N/A [Any] `fdietze/sqlc-gen-from-template`_ Stable Stable Stable ======== ================================== =============== =============== =============== @@ -53,4 +54,5 @@ Gleam `daniellionel01/parrot`_ Stable Stable S .. _tinyzimmer/sqlc-gen-zig: https://github.com/tinyzimmer/sqlc-gen-zig .. _daniellionel01/parrot: https://github.com/daniellionel01/parrot .. _rayakame/sqlc-gen-better-python: https://github.com/rayakame/sqlc-gen-better-python +.. _mathematic-inc/sqlc-gen-sqlx: https://github.com/mathematic-inc/sqlc-gen-sqlx .. _github topic: https://github.com/topics/sqlc-plugin diff --git a/docs/requirements.txt b/docs/requirements.txt index b67f41549a..e22349d09d 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,22 +1,22 @@ -Babel==2.17.0 +Babel==2.18.0 Jinja2==3.1.6 MarkupSafe==3.0.3 -Pygments==2.19.2 -Sphinx==7.4.7 -certifi==2026.1.4 -chardet==5.2.0 +Pygments==2.20.0 +Sphinx==8.2.3 +certifi==2026.2.25 +chardet==7.4.3 commonmark==0.9.1 docutils==0.20.1 idna==3.11 -imagesize==1.4.1 -myst-parser==4.0.1 -packaging==25.0 -pyparsing==3.3.1 -pytz==2025.2 -requests==2.32.5 +imagesize==2.0.0 +myst-parser==5.0.0 +packaging==26.1 +pyparsing==3.3.2 +pytz==2026.1.post1 +requests==2.33.1 snowballstemmer==3.0.1 -sphinx-favicon==1.0.1 -sphinx-rtd-theme==3.0.2 +sphinx-favicon==1.1.0 +sphinx-rtd-theme==3.1.0 sphinxcontrib-applehelp==2.0.0 sphinxcontrib-devhelp==2.0.0 sphinxcontrib-htmlhelp==2.1.0 diff --git a/go.mod b/go.mod index 57624c33b1..6cd60dddbf 100644 --- a/go.mod +++ b/go.mod @@ -2,19 +2,20 @@ module github.com/sqlc-dev/sqlc go 1.26.0 +toolchain go1.26.2 + require ( github.com/antlr4-go/antlr/v4 v4.13.1 github.com/cubicdaiya/gonp v1.0.4 github.com/davecgh/go-spew v1.1.1 github.com/fatih/structtag v1.2.0 github.com/go-sql-driver/mysql v1.9.3 - github.com/google/cel-go v0.27.0 + github.com/google/cel-go v0.28.0 github.com/google/go-cmp v0.7.0 - github.com/jackc/pgx/v4 v4.18.3 - github.com/jackc/pgx/v5 v5.8.0 + github.com/jackc/pgx/v5 v5.9.1 github.com/jinzhu/inflection v1.0.0 - github.com/lib/pq v1.12.0 - github.com/ncruces/go-sqlite3 v0.32.0 + github.com/lib/pq v1.12.3 + github.com/ncruces/go-sqlite3 v0.33.3 github.com/pganalyze/pg_query_go/v6 v6.2.2 github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0 github.com/riza-io/grpc-go v0.2.0 @@ -25,7 +26,7 @@ require ( github.com/wasilibs/go-pgquery v0.0.0-20250409022910-10ac41983c07 github.com/xeipuuv/gojsonschema v1.2.0 golang.org/x/sync v0.20.0 - google.golang.org/grpc v1.79.3 + google.golang.org/grpc v1.80.0 google.golang.org/protobuf v1.36.11 gopkg.in/yaml.v3 v3.0.1 ) @@ -34,14 +35,10 @@ require ( cel.dev/expr v0.25.1 // indirect filippo.io/edwards25519 v1.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/jackc/chunkreader/v2 v2.0.1 // indirect - github.com/jackc/pgconn v1.14.3 // indirect - github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect - github.com/jackc/pgtype v1.14.0 // indirect github.com/jackc/puddle/v2 v2.2.2 // indirect + github.com/ncruces/go-sqlite3-wasm v1.1.1-0.20260409221933-87e4b35a38d0 // indirect github.com/ncruces/julianday v1.0.0 // indirect github.com/pingcap/errors v0.11.5-0.20240311024730-e056997136bb // indirect github.com/pingcap/failpoint v0.0.0-20240528011301-b51a646c7c86 // indirect @@ -53,13 +50,12 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.27.0 // indirect - golang.org/x/crypto v0.48.0 // indirect golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b // indirect golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.41.0 // indirect - golang.org/x/text v0.34.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect + golang.org/x/sys v0.43.0 // indirect + golang.org/x/text v0.36.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect ) diff --git a/go.sum b/go.sum index ca0a5c97f4..0dd85cc158 100644 --- a/go.sum +++ b/go.sum @@ -3,18 +3,12 @@ cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= filippo.io/edwards25519 v1.1.1 h1:YpjwWWlNmGIDyXOn8zLzqiD+9TyIlPhGFG96P39uBpw= filippo.io/edwards25519 v1.1.1/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ= github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/cubicdaiya/gonp v1.0.4 h1:ky2uIAJh81WiLcGKBVD5R7KsM/36W6IqqTy6Bo6rGws= github.com/cubicdaiya/gonp v1.0.4/go.mod h1:iWGuP/7+JVTn02OWhRemVbMmG1DOUnmrGTYYACpOI0I= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -22,103 +16,43 @@ 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-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= -github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo= -github.com/google/cel-go v0.27.0/go.mod h1:tTJ11FWqnhw5KKpnWpvW9CJC3Y9GK4EIS0WXnBbebzw= +github.com/google/cel-go v0.28.0 h1:KjSWstCpz/MN5t4a8gnGJNIYUsJRpdi/r97xWDphIQc= +github.com/google/cel-go v0.28.0/go.mod h1:X0bD6iVNR8pkROSOoHVdgTkzmRcosof7WQqCD6wcMc8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= -github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= -github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= -github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= -github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.14.3 h1:bVoTr12EGANZz66nZPkMInAV/KHD2TxH9npjXXgiB3w= -github.com/jackc/pgconn v1.14.3/go.mod h1:RZbme4uasqzybK2RK5c65VsHxoyaml09lx3tXOcO/VM= -github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= -github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= -github.com/jackc/pgmock v0.0.0-20201204152224-4fe30f7445fd/go.mod h1:hrBW0Enj2AZTNpt/7Y5rr2xe/9Mn757Wtb2xeBzPv2c= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65 h1:DadwsjnMwFjfWc9y5Wi/+Zz7xoE5ALHsRQlOctkOiHc= -github.com/jackc/pgmock v0.0.0-20210724152146-4ad1a8207f65/go.mod h1:5R2h2EEX+qri8jOWMbJCtaPWkrrNc7OHwsp2TCqp7ak= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= -github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= -github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.3.3 h1:1HLSx5H+tXR9pW3in3zaztoEwQYRC9SQaYUHjTSUOag= -github.com/jackc/pgproto3/v2 v2.3.3/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= -github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= -github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw= -github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= -github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= -github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -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.3 h1:dE2/TrEsGX3RBprb3qryqSV9Y60iZN1C6i8IrmW9/BA= -github.com/jackc/pgx/v4 v4.18.3/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= -github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo= -github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= -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= +github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc= +github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4= github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.12.0 h1:mC1zeiNamwKBecjHarAr26c/+d8V5w/u4J0I/yASbJo= -github.com/lib/pq v1.12.0/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/ncruces/go-sqlite3 v0.32.0 h1:hNBUXp88LrfQCsuyXLqWTbTUG35sUuktDsqhhgHvU20= -github.com/ncruces/go-sqlite3 v0.32.0/go.mod h1:MIWTK60ONDl0oVY073zYvJP21C3Dly6P9bxVpgkLwdQ= +github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ= +github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/ncruces/go-sqlite3 v0.33.3 h1:6jCR3KuGvJSEwhaQrkHDGeIe2qCQ6nOUDNsPz7ZIotw= +github.com/ncruces/go-sqlite3 v0.33.3/go.mod h1:t2Osfw0wcKzJTgv2EvrkTtVLqlbKTA5Yvwb2ypAlBcY= +github.com/ncruces/go-sqlite3-wasm v1.1.1-0.20260409221933-87e4b35a38d0 h1:ymE9H30x1AyW5VfMNkJC9teuI2W1jjMsQS7kc6zl6Tg= +github.com/ncruces/go-sqlite3-wasm v1.1.1-0.20260409221933-87e4b35a38d0/go.mod h1:/H3+JykPsfSlvKbOxNSx9kKwm3ecqQGzyCs1e9KkNsU= github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M= github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g= github.com/pganalyze/pg_query_go/v6 v6.2.2 h1:O0L6zMC226R82RF3X5n0Ki6HjytDsoAzuzp4ATVAHNo= @@ -133,25 +67,13 @@ github.com/pingcap/log v1.1.0/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoO github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0 h1:W3rpAI3bubR6VWOcwxDIG0Gz9G5rl5b3SL116T0vBt0= github.com/pingcap/tidb/pkg/parser v0.0.0-20250324122243-d51e00e5bbf0/go.mod h1:+8feuexTKcXHZF/dkDfvCwEyBAmgb4paFc3/WeYV2eE= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/riza-io/grpc-go v0.2.0 h1:2HxQKFVE7VuYstcJ8zqpN84VnAoJ4dCL6YFhJewNcHQ= github.com/riza-io/grpc-go v0.2.0/go.mod h1:2bDvR9KkKC3KhtlSHfR3dAXjUMT86kg4UfWFyVGWqi8= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= -github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= -github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= -github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= -github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= @@ -162,12 +84,8 @@ github.com/sqlc-dev/doubleclick v1.0.0/go.mod h1:ODHRroSrk/rr5neRHlWMSRijqOak8Ym github.com/sqlc-dev/mysql v0.0.0-20251129233104-d81e1cac6db2 h1:kmCAKKtOgK6EXXQX9oPdEASIhgor7TCpWxD8NtcqVcU= github.com/sqlc-dev/mysql v0.0.0-20251129233104-d81e1cac6db2/go.mod h1:TrDMWzjNTKvJeK2GC8uspG+PWyPLiY9QKvwdWpAdlZE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= @@ -183,7 +101,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHo github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= -github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48= @@ -196,9 +113,6 @@ go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2W go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA= -go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -207,101 +121,50 @@ go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0 go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= -go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= -go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b h1:M2rDM6z3Fhozi9O7NWsxAkg/yqS/lQJ6PmkyIV3YP+o= golang.org/x/exp v0.0.0-20250620022241-b7579e27df2b/go.mod h1:3//PLf8L/X+8b4vuAfHzxeRUl04Adcb341+IGKfnqS8= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= +golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= +golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= -gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217 h1:fCvbg86sFXwdrl5LgVcTEvNC+2txB5mgROGmRL5mrls= -google.golang.org/genproto/googleapis/api v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:+rXWjjaukWZun3mLfjmVnQi18E1AsFbDN9QdJ5YXLto= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 h1:gRkg/vSppuSQoDjxyiGfN4Upv/h/DQmIR10ZU8dh4Ww= -google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= -google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE= -google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ= +gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4= +gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E= +google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516 h1:vmC/ws+pLzWjj/gzApyoZuSVrDtF1aod4u/+bbj8hgM= +google.golang.org/genproto/googleapis/api v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:p3MLuOwURrGBRoEyFHBT3GjUwaCQVKeNqqWxlcISGdw= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516 h1:sNrWoksmOyF5bvJUcnmbeAmQi8baNhqg5IWaI3llQqU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260120221211-b8f7ae30c516/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM= +google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= @@ -311,4 +174,3 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/internal/cmd/vet_sqlite.go b/internal/cmd/vet_sqlite.go index e1f8c7f9a8..7b3e39afe5 100644 --- a/internal/cmd/vet_sqlite.go +++ b/internal/cmd/vet_sqlite.go @@ -2,5 +2,4 @@ package cmd import ( _ "github.com/ncruces/go-sqlite3/driver" - _ "github.com/ncruces/go-sqlite3/embed" ) diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index 398d01e2e8..62bd73e466 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -503,6 +503,11 @@ func postgresType(req *plugin.GenerateRequest, options *opts.Options, col *plugi return "pgtype.XID" } + case "xid8": + if driver == opts.SQLDriverPGXV5 { + return "pgtype.Uint64" + } + case "box": if driver.IsPGX() { return "pgtype.Box" diff --git a/internal/codegen/golang/result.go b/internal/codegen/golang/result.go index 0820488f9d..216f5e3372 100644 --- a/internal/codegen/golang/result.go +++ b/internal/codegen/golang/result.go @@ -268,8 +268,26 @@ func buildQueries(req *plugin.GenerateRequest, options *opts.Options, structs [] c := query.Columns[0] name := columnName(c, 0) name = strings.Replace(name, "$", "_", -1) + retName := escape(name) + // For :one queries the scan destination lives in the same scope as + // the query parameters, so reusing a parameter's name would cause + // Scan to overwrite the input and leak it back to the caller on + // sql.ErrNoRows (see sqlc-dev/sqlc#4354). Rename the return + // variable when it would collide. + if query.Cmd == metadata.CmdOne { + argNames := map[string]struct{}{} + for _, p := range gq.Arg.Pairs() { + argNames[p.Name] = struct{}{} + } + for { + if _, conflict := argNames[retName]; !conflict { + break + } + retName += "_2" + } + } gq.Ret = QueryValue{ - Name: escape(name), + Name: retName, DBName: name, Typ: goType(req, options, c), SQLDriver: sqlpkg, diff --git a/internal/compiler/analyze.go b/internal/compiler/analyze.go index 0d7d507575..264dbef6f5 100644 --- a/internal/compiler/analyze.go +++ b/internal/compiler/analyze.go @@ -144,14 +144,14 @@ func (c *Compiler) _analyzeQuery(raw *ast.RawStmt, query string, failfast bool) var table *ast.TableName switch n := raw.Stmt.(type) { case *ast.InsertStmt: - if err := check(validate.InsertStmt(n)); err != nil { - return nil, err - } var err error table, err = ParseTableName(n.Relation) if err := check(err); err != nil { return nil, err } + if err := check(validate.InsertStmt(c.catalog, table, n)); err != nil { + return nil, err + } } if err := check(validate.FuncCall(c.catalog, c.combo, raw)); err != nil { diff --git a/internal/compiler/resolve.go b/internal/compiler/resolve.go index b1fbb1990e..d926f2b1fc 100644 --- a/internal/compiler/resolve.go +++ b/internal/compiler/resolve.go @@ -513,10 +513,11 @@ func (comp *Compiler) resolveCatalogRefs(qc *QueryCatalog, rvs []*ast.RangeVar, } col := toColumn(n.TypeName) defaultP := named.NewInferredParam(col.Name, col.NotNull) - p, _ := params.FetchMerge(ref.ref.Number, defaultP) + p, isNamed := params.FetchMerge(ref.ref.Number, defaultP) col.Name = p.Name() col.NotNull = p.NotNull() + col.IsNamedParam = isNamed a = append(a, Parameter{ Number: ref.ref.Number, Column: col, diff --git a/internal/compiler/selector.go b/internal/compiler/selector.go index 04d118ff9c..115c9eb835 100644 --- a/internal/compiler/selector.go +++ b/internal/compiler/selector.go @@ -1,5 +1,7 @@ package compiler +import "strings" + // selector is an interface used by a compiler for generating expressions for // output columns in a `SELECT ...` or `RETURNING ...` statement. // @@ -39,7 +41,7 @@ func (s *sqliteSelector) ColumnExpr(name string, column *Column) string { // outside of the database itself. For jsonb columns in SQLite, wrap values // in `json(col)` to coerce the internal binary format to JSON parsable by // the user-space application. - if column.DataType == "jsonb" { + if strings.EqualFold(column.DataType, "jsonb") { return "json(" + name + ")" } return name diff --git a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/models.go b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/models.go index a8133f8ace..de1bdf846c 100644 --- a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/models.go +++ b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/models.go @@ -9,12 +9,14 @@ import ( ) type TestTable struct { - VCidNull pgtype.Uint32 - VOidNull pgtype.Uint32 - VTidNull pgtype.TID - VXidNull pgtype.Uint32 - VCid pgtype.Uint32 - VOid pgtype.Uint32 - VTid pgtype.TID - VXid pgtype.Uint32 + VCidNull pgtype.Uint32 + VOidNull pgtype.Uint32 + VTidNull pgtype.TID + VXidNull pgtype.Uint32 + VXid8Null pgtype.Uint64 + VCid pgtype.Uint32 + VOid pgtype.Uint32 + VTid pgtype.TID + VXid pgtype.Uint32 + VXid8 pgtype.Uint64 } diff --git a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/query.sql.go index 3e37867bec..409c68f136 100644 --- a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/go/query.sql.go @@ -10,7 +10,7 @@ import ( ) const selectTest = `-- name: SelectTest :many -SELECT v_cid_null, v_oid_null, v_tid_null, v_xid_null, v_cid, v_oid, v_tid, v_xid +SELECT v_cid_null, v_oid_null, v_tid_null, v_xid_null, v_xid8_null, v_cid, v_oid, v_tid, v_xid, v_xid8 from test_table ` @@ -28,10 +28,12 @@ func (q *Queries) SelectTest(ctx context.Context) ([]TestTable, error) { &i.VOidNull, &i.VTidNull, &i.VXidNull, + &i.VXid8Null, &i.VCid, &i.VOid, &i.VTid, &i.VXid, + &i.VXid8, ); err != nil { return nil, err } diff --git a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/schema.sql b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/schema.sql index ecd09ac882..bd6f114255 100644 --- a/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/schema.sql +++ b/internal/endtoend/testdata/cid_oid_tid_xid/pgx/v5/schema.sql @@ -4,9 +4,11 @@ CREATE TABLE test_table v_oid_null oid, v_tid_null tid, v_xid_null xid, + v_xid8_null xid8, v_cid cid not null, v_oid oid not null, v_tid tid not null, - v_xid xid not null + v_xid xid not null, + v_xid8 xid8 not null ); diff --git a/internal/endtoend/testdata/go.mod b/internal/endtoend/testdata/go.mod index e2a7ea704b..502eef7017 100644 --- a/internal/endtoend/testdata/go.mod +++ b/internal/endtoend/testdata/go.mod @@ -1,6 +1,8 @@ module github.com/sqlc-dev/sqlc/endtoend -go 1.18 +go 1.24.0 + +toolchain go1.24.7 require ( github.com/go-sql-driver/mysql v1.7.0 @@ -10,7 +12,7 @@ require ( github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853 github.com/jackc/pgtype v1.6.2 github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904 - github.com/jackc/pgx/v5 v5.4.3 + github.com/jackc/pgx/v5 v5.8.0 github.com/lib/pq v1.9.0 github.com/sqlc-dev/pqtype v0.2.0 github.com/sqlc-dev/sqlc-testdata v1.0.0 @@ -24,12 +26,12 @@ require ( github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgproto3/v2 v2.0.1 // indirect - github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/pgvector/pgvector-go v0.1.1 // indirect github.com/volatiletech/inflect v0.0.1 // indirect github.com/volatiletech/randomize v0.0.1 // indirect github.com/volatiletech/strmangle v0.0.1 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/crypto v0.17.0 // indirect + golang.org/x/text v0.29.0 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/internal/endtoend/testdata/go.sum b/internal/endtoend/testdata/go.sum index a5819e0a3b..0711cb8eaf 100644 --- a/internal/endtoend/testdata/go.sum +++ b/internal/endtoend/testdata/go.sum @@ -49,6 +49,8 @@ github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHF github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= @@ -70,6 +72,14 @@ github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= 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/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw= +github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA= +github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= +github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= +github.com/jackc/pgx/v5 v5.7.0 h1:FG6VLIdzvAPhnYqP14sQ2xhFLkiUQHCs6ySqO91kF4g= +github.com/jackc/pgx/v5 v5.7.0/go.mod h1:awP1KNnjylvpxHuHP63gzjhnGkI1iw+PMoIwvoleN/8= +github.com/jackc/pgx/v5 v5.8.0 h1:TYPDoleBBme0xGSAX3/+NujXXtpZn9HBONkQC7IEZSo= +github.com/jackc/pgx/v5 v5.8.0/go.mod h1:QVeDInX2m9VyzvNeiCJVjCkNFqzsNb43204HshNSZKw= 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.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -152,6 +162,8 @@ golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -177,6 +189,10 @@ golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= diff --git a/internal/endtoend/testdata/jsonb/sqlite/go/models.go b/internal/endtoend/testdata/jsonb/sqlite/go/models.go index 3980b20cad..d8e9fa20bc 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/go/models.go +++ b/internal/endtoend/testdata/jsonb/sqlite/go/models.go @@ -13,4 +13,8 @@ type Foo struct { B json.RawMessage C json.RawMessage D json.RawMessage + E json.RawMessage + F json.RawMessage + G json.RawMessage + H json.RawMessage } diff --git a/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go b/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go index 448182e3dd..c073069515 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/jsonb/sqlite/go/query.sql.go @@ -15,13 +15,21 @@ INSERT INTO foo ( a, b, c, - d + d, + e, + f, + g, + h ) VALUES ( ?1, ?2, ?3, - ?4 -) RETURNING a, json(b), c, json(d) + ?4, + ?5, + ?6, + ?7, + ?8 +) RETURNING a, json(b), c, json(d), e, json(f), g, json(h) ` type InsertFooParams struct { @@ -29,6 +37,10 @@ type InsertFooParams struct { B json.RawMessage C json.RawMessage D json.RawMessage + E json.RawMessage + F json.RawMessage + G json.RawMessage + H json.RawMessage } func (q *Queries) InsertFoo(ctx context.Context, arg InsertFooParams) error { @@ -37,12 +49,16 @@ func (q *Queries) InsertFoo(ctx context.Context, arg InsertFooParams) error { arg.B, arg.C, arg.D, + arg.E, + arg.F, + arg.G, + arg.H, ) return err } const selectFoo = `-- name: SelectFoo :exec -SELECT a, json(b), c, json(d) FROM foo +SELECT a, json(b), c, json(d), e, json(f), g, json(h) FROM foo ` func (q *Queries) SelectFoo(ctx context.Context) error { diff --git a/internal/endtoend/testdata/jsonb/sqlite/query.sql b/internal/endtoend/testdata/jsonb/sqlite/query.sql index 6959bd1a70..baca24c120 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/query.sql +++ b/internal/endtoend/testdata/jsonb/sqlite/query.sql @@ -3,12 +3,20 @@ INSERT INTO foo ( a, b, c, - d + d, + e, + f, + g, + h ) VALUES ( @a, @b, @c, - @d + @d, + @e, + @f, + @g, + @h ) RETURNING *; -- name: SelectFoo :exec diff --git a/internal/endtoend/testdata/jsonb/sqlite/schema.sql b/internal/endtoend/testdata/jsonb/sqlite/schema.sql index 6b4a1bb0fd..cc237ce009 100644 --- a/internal/endtoend/testdata/jsonb/sqlite/schema.sql +++ b/internal/endtoend/testdata/jsonb/sqlite/schema.sql @@ -2,6 +2,10 @@ CREATE TABLE foo ( a json not null, b jsonb not null, c json, - d jsonb + d jsonb, + e JSON not null, + f JSONB not null, + g JSON, + h JSONB ); diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/db.go b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/db.go new file mode 100644 index 0000000000..3b320aa168 --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/models.go b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/models.go new file mode 100644 index 0000000000..92ddc7826f --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/models.go @@ -0,0 +1,13 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package querytest + +import ( + "database/sql" +) + +type Foo struct { + Bar sql.NullString +} diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/query.sql.go b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/query.sql.go new file mode 100644 index 0000000000..258d113473 --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/go/query.sql.go @@ -0,0 +1,37 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const inlineHint = `-- name: InlineHint :one +SELECT /*+ MAX_EXECUTION_TIME(1000) */ bar FROM foo LIMIT 1 +` + +func (q *Queries) InlineHint(ctx context.Context) (sql.NullString, error) { + row := q.db.QueryRowContext(ctx, inlineHint) + var bar sql.NullString + err := row.Scan(&bar) + return bar, err +} + +const multilineHint = `-- name: MultilineHint :one +SELECT +/*+ MAX_EXECUTION_TIME(1000) */ +bar +FROM foo +LIMIT 1 +` + +func (q *Queries) MultilineHint(ctx context.Context) (sql.NullString, error) { + row := q.db.QueryRowContext(ctx, multilineHint) + var bar sql.NullString + err := row.Scan(&bar) + return bar, err +} diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/query.sql b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/query.sql new file mode 100644 index 0000000000..fa90093b66 --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/query.sql @@ -0,0 +1,9 @@ +-- name: InlineHint :one +SELECT /*+ MAX_EXECUTION_TIME(1000) */ bar FROM foo LIMIT 1; + +-- name: MultilineHint :one +SELECT +/*+ MAX_EXECUTION_TIME(1000) */ +bar +FROM foo +LIMIT 1; diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/schema.sql b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/schema.sql new file mode 100644 index 0000000000..d849628fb1 --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/schema.sql @@ -0,0 +1 @@ +CREATE TABLE foo (bar text); diff --git a/internal/endtoend/testdata/mysql_optimizer_hints/mysql/sqlc.json b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/sqlc.json new file mode 100644 index 0000000000..e41c39e8b3 --- /dev/null +++ b/internal/endtoend/testdata/mysql_optimizer_hints/mysql/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "mysql", + "name": "querytest", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/go/db.go b/internal/endtoend/testdata/order_by_binds/sqlite/go/db.go new file mode 100644 index 0000000000..0ca2c6d0dd --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/go/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package order_by_binds + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/go/models.go b/internal/endtoend/testdata/order_by_binds/sqlite/go/models.go new file mode 100644 index 0000000000..e9a4756502 --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/go/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 + +package order_by_binds + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/go/query.sql.go b/internal/endtoend/testdata/order_by_binds/sqlite/go/query.sql.go new file mode 100644 index 0000000000..55c26a5aed --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/go/query.sql.go @@ -0,0 +1,173 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.30.0 +// source: query.sql + +package order_by_binds + +import ( + "context" +) + +const listAuthorsColumnSort = `-- name: ListAuthorsColumnSort :many +SELECT id, name, bio FROM authors +WHERE id > ?1 +ORDER BY CASE WHEN ?2 = 'name' THEN name END +` + +type ListAuthorsColumnSortParams struct { + MinID int64 + SortColumn interface{} +} + +func (q *Queries) ListAuthorsColumnSort(ctx context.Context, arg ListAuthorsColumnSortParams) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsColumnSort, arg.MinID, arg.SortColumn) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listAuthorsColumnSortDirection = `-- name: ListAuthorsColumnSortDirection :many +SELECT id, name, bio FROM authors +WHERE id > ? +ORDER BY + CASE + WHEN ?2 = 'asc' THEN name + END ASC, + CASE + WHEN ?2 = 'desc' OR ?2 IS NULL THEN name + END DESC +` + +type ListAuthorsColumnSortDirectionParams struct { + ID int64 + OrderBy interface{} +} + +func (q *Queries) ListAuthorsColumnSortDirection(ctx context.Context, arg ListAuthorsColumnSortDirectionParams) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsColumnSortDirection, arg.ID, arg.OrderBy) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listAuthorsColumnSortFnWtihArg = `-- name: ListAuthorsColumnSortFnWtihArg :many +SELECT id, name, bio FROM authors +ORDER BY id % ? +` + +func (q *Queries) ListAuthorsColumnSortFnWtihArg(ctx context.Context, id int64) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsColumnSortFnWtihArg, id) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listAuthorsNameSort = `-- name: ListAuthorsNameSort :many +SELECT id, name, bio FROM authors +WHERE id > ?1 +ORDER BY name ASC +` + +func (q *Queries) ListAuthorsNameSort(ctx context.Context, minID int64) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsNameSort, minID) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listAuthorsNamedParamsOnly = `-- name: ListAuthorsNamedParamsOnly :many +SELECT id, name, bio FROM authors +ORDER BY + CASE + WHEN ?1 = 'name' THEN name + WHEN ?1 = 'bio' THEN bio + END ASC +` + +func (q *Queries) ListAuthorsNamedParamsOnly(ctx context.Context, sort interface{}) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthorsNamedParamsOnly, sort) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/query.sql b/internal/endtoend/testdata/order_by_binds/sqlite/query.sql new file mode 100644 index 0000000000..4fa2e5d88e --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/query.sql @@ -0,0 +1,32 @@ +-- name: ListAuthorsColumnSort :many +SELECT * FROM authors +WHERE id > sqlc.arg(min_id) +ORDER BY CASE WHEN sqlc.arg(sort_column) = 'name' THEN name END; + +-- name: ListAuthorsColumnSortDirection :many +SELECT * FROM authors +WHERE id > ? +ORDER BY + CASE + WHEN @order_by = 'asc' THEN name + END ASC, + CASE + WHEN @order_by = 'desc' OR @order_by IS NULL THEN name + END DESC; + +-- name: ListAuthorsColumnSortFnWtihArg :many +SELECT * FROM authors +ORDER BY id % ?; + +-- name: ListAuthorsNameSort :many +SELECT * FROM authors +WHERE id > sqlc.arg(min_id) +ORDER BY name ASC; + +-- name: ListAuthorsNamedParamsOnly :many +SELECT * FROM authors +ORDER BY + CASE + WHEN @sort = 'name' THEN name + WHEN @sort = 'bio' THEN bio + END ASC; diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/schema.sql b/internal/endtoend/testdata/order_by_binds/sqlite/schema.sql new file mode 100644 index 0000000000..eaa9aab806 --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + bio TEXT +); diff --git a/internal/endtoend/testdata/order_by_binds/sqlite/sqlc.json b/internal/endtoend/testdata/order_by_binds/sqlite/sqlc.json new file mode 100644 index 0000000000..36d9a495cc --- /dev/null +++ b/internal/endtoend/testdata/order_by_binds/sqlite/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "sqlite", + "name": "order_by_binds", + "schema": "schema.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/params_duplicate/mysql/go/models.go b/internal/endtoend/testdata/params_duplicate/mysql/go/models.go index cab9171aaf..c47ceb80a6 100644 --- a/internal/endtoend/testdata/params_duplicate/mysql/go/models.go +++ b/internal/endtoend/testdata/params_duplicate/mysql/go/models.go @@ -12,4 +12,5 @@ type User struct { ID int32 FirstName sql.NullString LastName sql.NullString + Age sql.NullInt32 } diff --git a/internal/endtoend/testdata/params_duplicate/mysql/go/query.sql.go b/internal/endtoend/testdata/params_duplicate/mysql/go/query.sql.go index 332cb9b26e..33a8e53d75 100644 --- a/internal/endtoend/testdata/params_duplicate/mysql/go/query.sql.go +++ b/internal/endtoend/testdata/params_duplicate/mysql/go/query.sql.go @@ -10,6 +10,39 @@ import ( "database/sql" ) +const selectUserByAgeCast = `-- name: SelectUserByAgeCast :many +SELECT first_name FROM users +WHERE age > CAST(? AS SIGNED) + OR age < CAST(? AS SIGNED) +` + +type SelectUserByAgeCastParams struct { + Threshold int64 +} + +func (q *Queries) SelectUserByAgeCast(ctx context.Context, arg SelectUserByAgeCastParams) ([]sql.NullString, error) { + rows, err := q.db.QueryContext(ctx, selectUserByAgeCast, arg.Threshold, arg.Threshold) + if err != nil { + return nil, err + } + defer rows.Close() + var items []sql.NullString + for rows.Next() { + var first_name sql.NullString + if err := rows.Scan(&first_name); err != nil { + return nil, err + } + items = append(items, first_name) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + const selectUserByID = `-- name: SelectUserByID :many SELECT first_name from users where (? = id OR ? = 0) diff --git a/internal/endtoend/testdata/params_duplicate/mysql/query.sql b/internal/endtoend/testdata/params_duplicate/mysql/query.sql index cd661993c7..3924f57ad7 100644 --- a/internal/endtoend/testdata/params_duplicate/mysql/query.sql +++ b/internal/endtoend/testdata/params_duplicate/mysql/query.sql @@ -11,3 +11,8 @@ WHERE first_name = sqlc.arg(name) /* name: SelectUserQuestion :many */ SELECT first_name from users where (? = id OR ? = 0); + +/* name: SelectUserByAgeCast :many */ +SELECT first_name FROM users +WHERE age > CAST(sqlc.arg(threshold) AS SIGNED) + OR age < CAST(sqlc.arg(threshold) AS SIGNED); diff --git a/internal/endtoend/testdata/params_duplicate/mysql/schema.sql b/internal/endtoend/testdata/params_duplicate/mysql/schema.sql index e93e087e50..497fa29b7d 100644 --- a/internal/endtoend/testdata/params_duplicate/mysql/schema.sql +++ b/internal/endtoend/testdata/params_duplicate/mysql/schema.sql @@ -1,5 +1,6 @@ CREATE TABLE users ( id integer NOT NULL AUTO_INCREMENT PRIMARY KEY, first_name varchar(255), - last_name varchar(255) + last_name varchar(255), + age int ) ENGINE=InnoDB; diff --git a/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go index e3ba139207..44385a7b9d 100644 --- a/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/mysql/go/query.sql.go @@ -32,8 +32,9 @@ LIMIT 1 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRowContext(ctx, getAuthorIDByID, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } const getUser = `-- name: GetUser :one @@ -45,6 +46,7 @@ LIMIT 1 func (q *Queries) GetUser(ctx context.Context, sub string) (string, error) { row := q.db.QueryRowContext(ctx, getUser, sub) - err := row.Scan(&sub) - return sub, err + var sub_2 string + err := row.Scan(&sub_2) + return sub_2, err } diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go index 1912659d8b..05f0540e5c 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v4/go/query.sql.go @@ -34,8 +34,9 @@ LIMIT 1 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRow(ctx, getAuthorIDByID, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } const getUser = `-- name: GetUser :one @@ -47,8 +48,9 @@ LIMIT 1 func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) { row := q.db.QueryRow(ctx, getUser, sub) - err := row.Scan(&sub) - return sub, err + var sub_2 uuid.UUID + err := row.Scan(&sub_2) + return sub_2, err } const setDefaultName = `-- name: SetDefaultName :one @@ -62,6 +64,7 @@ RETURNING id // https://github.com/sqlc-dev/sqlc/issues/1235 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRow(ctx, setDefaultName, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go index daa903d8c2..6db0c091dd 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/pgx/v5/go/query.sql.go @@ -34,8 +34,9 @@ LIMIT 1 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRow(ctx, getAuthorIDByID, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } const getUser = `-- name: GetUser :one @@ -47,8 +48,9 @@ LIMIT 1 func (q *Queries) GetUser(ctx context.Context, sub pgtype.UUID) (pgtype.UUID, error) { row := q.db.QueryRow(ctx, getUser, sub) - err := row.Scan(&sub) - return sub, err + var sub_2 pgtype.UUID + err := row.Scan(&sub_2) + return sub_2, err } const setDefaultName = `-- name: SetDefaultName :one @@ -62,6 +64,7 @@ RETURNING id // https://github.com/sqlc-dev/sqlc/issues/1235 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRow(ctx, setDefaultName, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } diff --git a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go index 0b99078536..4f4bd175be 100644 --- a/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/postgresql/stdlib/go/query.sql.go @@ -34,8 +34,9 @@ LIMIT 1 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRowContext(ctx, getAuthorIDByID, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } const getUser = `-- name: GetUser :one @@ -47,8 +48,9 @@ LIMIT 1 func (q *Queries) GetUser(ctx context.Context, sub uuid.UUID) (uuid.UUID, error) { row := q.db.QueryRowContext(ctx, getUser, sub) - err := row.Scan(&sub) - return sub, err + var sub_2 uuid.UUID + err := row.Scan(&sub_2) + return sub_2, err } const setDefaultName = `-- name: SetDefaultName :one @@ -62,6 +64,7 @@ RETURNING id // https://github.com/sqlc-dev/sqlc/issues/1235 func (q *Queries) SetDefaultName(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRowContext(ctx, setDefaultName, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } diff --git a/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go b/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go index e3ba139207..44385a7b9d 100644 --- a/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go +++ b/internal/endtoend/testdata/single_param_conflict/sqlite/go/query.sql.go @@ -32,8 +32,9 @@ LIMIT 1 func (q *Queries) GetAuthorIDByID(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRowContext(ctx, getAuthorIDByID, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } const getUser = `-- name: GetUser :one @@ -45,6 +46,7 @@ LIMIT 1 func (q *Queries) GetUser(ctx context.Context, sub string) (string, error) { row := q.db.QueryRowContext(ctx, getUser, sub) - err := row.Scan(&sub) - return sub, err + var sub_2 string + err := row.Scan(&sub_2) + return sub_2, err } diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json index ee1b7ecd9e..2e996ca79d 100644 --- a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/exec.json @@ -1,3 +1,3 @@ { - "contexts": ["managed-db"] + "contexts": ["base"] } diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql index 3f9e9d9b86..2484d998b6 100644 --- a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/query.sql @@ -1,4 +1,23 @@ --- name: UpsertServer :exec -INSERT INTO servers(code, name) VALUES ($1, $2) -ON CONFLICT (code) -DO UPDATE SET name_typo = 1111; \ No newline at end of file +-- name: UpsertServerSetColumnTypo :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT (code) +DO UPDATE SET name_typo = 1111; + +-- name: UpsertServerConflictTargetTypo :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT (code_typo) +DO UPDATE SET name = 1111; + +-- name: UpsertServerExcludedColumnTypo :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT (code) +DO UPDATE SET name = EXCLUDED.name_typo; + +-- name: UpsertServerMissingConflictTarget :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT DO UPDATE SET name = EXCLUDED.name; + +-- name: UpsertServerOnConstraintExcludedTypo :exec +INSERT INTO servers(code, name) VALUES ($1, $2) +ON CONFLICT ON CONSTRAINT servers_pkey DO UPDATE SET name = EXCLUDED.name_typo; + diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql index 3ff1ccd6b3..c3dec12e49 100644 --- a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/schema.sql @@ -1,4 +1,4 @@ CREATE TABLE servers ( - code varchar PRIMARY KEY, - name text NOT NULL -); \ No newline at end of file + code varchar PRIMARY KEY, + name text NOT NULL +); diff --git a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt index adbb13a418..b9692daa64 100644 --- a/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt +++ b/internal/endtoend/testdata/update_set_on_conflict/postgresql/pgx/stderr.txt @@ -1,2 +1,6 @@ # package querytest -query.sql:4:15: column "name_typo" of relation "servers" does not exist \ No newline at end of file +query.sql:4:15: column "name_typo" of relation "servers" does not exist +query.sql:8:13: column "code_typo" of relation "servers" does not exist +query.sql:14:22: column "name_typo" of relation "EXCLUDED" does not exist +query.sql:17:1: ON CONFLICT DO UPDATE requires inference specification or constraint name +query.sql:22:61: column "name_typo" of relation "EXCLUDED" does not exist diff --git a/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go b/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go index cef6fbff90..9a11dd5328 100644 --- a/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go +++ b/internal/endtoend/testdata/vet_explain/mysql/db/query.sql.go @@ -438,6 +438,7 @@ WHERE id = ? LIMIT 1 func (q *Queries) SelectById(ctx context.Context, id int64) (int64, error) { row := q.db.QueryRowContext(ctx, selectById, id) - err := row.Scan(&id) - return id, err + var id_2 int64 + err := row.Scan(&id_2) + return id_2, err } diff --git a/internal/engine/sqlite/analyzer/analyze.go b/internal/engine/sqlite/analyzer/analyze.go index 3af9f99a30..3909afdaf5 100644 --- a/internal/engine/sqlite/analyzer/analyze.go +++ b/internal/engine/sqlite/analyzer/analyze.go @@ -7,7 +7,6 @@ import ( "sync" "github.com/ncruces/go-sqlite3" - _ "github.com/ncruces/go-sqlite3/embed" core "github.com/sqlc-dev/sqlc/internal/analysis" "github.com/sqlc-dev/sqlc/internal/config" diff --git a/internal/engine/sqlite/convert.go b/internal/engine/sqlite/convert.go index e9868f5be6..35259a6597 100644 --- a/internal/engine/sqlite/convert.go +++ b/internal/engine/sqlite/convert.go @@ -512,8 +512,11 @@ func (c *cc) convertMultiSelect_stmtContext(n *parser.Select_stmtContext) ast.No } limitCount, limitOffset := c.convertLimit_stmtContext(n.Limit_stmt()) + sortClause := c.convertOrderby_stmtContext(n.Order_by_stmt()) + selectStmt.LimitCount = limitCount selectStmt.LimitOffset = limitOffset + selectStmt.SortClause = sortClause // Only set WithClause if there are CTEs if len(ctes.Items) > 0 { selectStmt.WithClause = &ast.WithClause{Ctes: &ctes} @@ -621,22 +624,59 @@ func (c *cc) convertWildCardField(n *parser.Result_columnContext) *ast.ColumnRef } } -func (c *cc) convertOrderby_stmtContext(n parser.IOrder_by_stmtContext) ast.Node { - if orderBy, ok := n.(*parser.Order_by_stmtContext); ok { - list := &ast.List{Items: []ast.Node{}} - for _, o := range orderBy.AllOrdering_term() { - term, ok := o.(*parser.Ordering_termContext) - if !ok { - continue +func (c *cc) convertOrderby_stmtContext(n parser.IOrder_by_stmtContext) *ast.List { + if n == nil { + return nil + } + + orderBy, ok := n.(*parser.Order_by_stmtContext) + if !ok { + if debug.Active { + log.Printf("sqlite.convertOrderby_stmtContext: unexpected type %T", n) + } + return nil + } + + if len(orderBy.AllOrdering_term()) == 0 { + return nil + } + + sortItems := &ast.List{Items: []ast.Node{}} + for _, o := range orderBy.AllOrdering_term() { + term, ok := o.(*parser.Ordering_termContext) + if !ok { + continue + } + + // Sort direction: ASC, DESC, or default + sortByDir := ast.SortByDirDefault + if adNode := term.Asc_desc(); adNode != nil { + if adNode.ASC_() != nil { + sortByDir = ast.SortByDirAsc + } else if adNode.DESC_() != nil { + sortByDir = ast.SortByDirDesc } - list.Items = append(list.Items, &ast.CaseExpr{ - Xpr: c.convert(term.Expr()), - Location: term.Expr().GetStart().GetStart(), - }) } - return list + + // Nulls ordering: NULLS FIRST, NULLS LAST, or default + sortByNulls := ast.SortByNullsDefault + if term.NULLS_() != nil { + if term.FIRST_() != nil { + sortByNulls = ast.SortByNullsFirst + } else if term.LAST_() != nil { + sortByNulls = ast.SortByNullsLast + } + } + + sortItems.Items = append(sortItems.Items, &ast.SortBy{ + Node: c.convert(term.Expr()), + SortbyDir: sortByDir, + SortbyNulls: sortByNulls, + UseOp: &ast.List{}, + Location: term.GetStart().GetStart(), + }) } - return todo("convertOrderby_stmtContext", n) + return sortItems } func (c *cc) convertLimit_stmtContext(n parser.ILimit_stmtContext) (ast.Node, ast.Node) { @@ -826,7 +866,7 @@ func (c *cc) convertUnaryExpr(n *parser.Expr_unaryContext) ast.Node { if opCtx.MINUS() != nil { // Negative number: -expr return &ast.A_Expr{ - Name: &ast.List{Items: []ast.Node{&ast.String{Str: "-"}}}, + Name: &ast.List{Items: []ast.Node{&ast.String{Str: "-"}}}, Rexpr: expr, } } @@ -837,7 +877,7 @@ func (c *cc) convertUnaryExpr(n *parser.Expr_unaryContext) ast.Node { if opCtx.TILDE() != nil { // Bitwise NOT: ~expr return &ast.A_Expr{ - Name: &ast.List{Items: []ast.Node{&ast.String{Str: "~"}}}, + Name: &ast.List{Items: []ast.Node{&ast.String{Str: "~"}}}, Rexpr: expr, } } @@ -1313,9 +1353,6 @@ func (c *cc) convert(node node) ast.Node { case *parser.Insert_stmtContext: return c.convertInsert_stmtContext(n) - case *parser.Order_by_stmtContext: - return c.convertOrderby_stmtContext(n) - case *parser.Select_stmtContext: return c.convertMultiSelect_stmtContext(n) diff --git a/internal/source/code.go b/internal/source/code.go index 8b88a24136..783682a2ee 100644 --- a/internal/source/code.go +++ b/internal/source/code.go @@ -115,6 +115,12 @@ func StripComments(sql string) (string, []string, error) { continue } if strings.HasPrefix(t, "/*") && strings.HasSuffix(t, "*/") { + // Preserve MySQL optimizer hints, which share block-comment + // syntax but are semantically part of the query. + if strings.HasPrefix(t, "/*+") { + lines = append(lines, t) + continue + } t = strings.TrimPrefix(t, "/*") t = strings.TrimSuffix(t, "*/") comments = append(comments, t) diff --git a/internal/sql/rewrite/parameters.go b/internal/sql/rewrite/parameters.go index d1ea1a22cc..c0454049d6 100644 --- a/internal/sql/rewrite/parameters.go +++ b/internal/sql/rewrite/parameters.go @@ -140,10 +140,10 @@ func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, // TODO: This code assumes that @foo::bool is on a single line var replace string - if engine == config.EngineMySQL || !dollar { - replace = "?" - } else if engine == config.EngineSQLite { + if engine == config.EngineSQLite { replace = fmt.Sprintf("?%d", argn) + } else if engine == config.EngineMySQL || !dollar { + replace = "?" } else { replace = fmt.Sprintf("$%d", argn) } @@ -168,10 +168,10 @@ func NamedParameters(engine config.Engine, raw *ast.RawStmt, numbs map[int]bool, // TODO: This code assumes that @foo is on a single line var replace string - if engine == config.EngineMySQL || !dollar { - replace = "?" - } else if engine == config.EngineSQLite { + if engine == config.EngineSQLite { replace = fmt.Sprintf("?%d", argn) + } else if engine == config.EngineMySQL || !dollar { + replace = "?" } else { replace = fmt.Sprintf("$%d", argn) } diff --git a/internal/sql/validate/insert_stmt.go b/internal/sql/validate/insert_stmt.go index dd8041ea23..236ddbfceb 100644 --- a/internal/sql/validate/insert_stmt.go +++ b/internal/sql/validate/insert_stmt.go @@ -1,11 +1,16 @@ package validate import ( + "strings" + "github.com/sqlc-dev/sqlc/internal/sql/ast" + "github.com/sqlc-dev/sqlc/internal/sql/catalog" "github.com/sqlc-dev/sqlc/internal/sql/sqlerr" ) -func InsertStmt(stmt *ast.InsertStmt) error { +const excludedTable = "EXCLUDED" + +func InsertStmt(c *catalog.Catalog, fqn *ast.TableName, stmt *ast.InsertStmt) error { sel, ok := stmt.SelectStmt.(*ast.SelectStmt) if !ok { return nil @@ -35,5 +40,102 @@ func InsertStmt(stmt *ast.InsertStmt) error { Message: "INSERT has more expressions than target columns", } } + + return onConflictClause(c, fqn, stmt) +} + +// onConflictClause validates an ON CONFLICT DO UPDATE clause against the target +// table. It checks: +// - ON CONFLICT (col, ...) conflict target columns exist +// - DO UPDATE SET col = ... assignment target columns exist +// - EXCLUDED.col references exist +func onConflictClause(c *catalog.Catalog, fqn *ast.TableName, n *ast.InsertStmt) error { + if fqn == nil || n.OnConflictClause == nil || n.OnConflictClause.Action != ast.OnConflictActionUpdate { + return nil + } + + table, err := c.GetTable(fqn) + if err != nil { + return err + } + + // Build set of column names for existence checks. + colNames := make(map[string]struct{}, len(table.Columns)) + for _, col := range table.Columns { + colNames[col.Name] = struct{}{} + } + + // DO UPDATE requires a conflict target: ON CONFLICT (col) or ON CONFLICT ON CONSTRAINT name. + if n.OnConflictClause.Infer == nil { + return &sqlerr.Error{ + Code: "42601", + Message: "ON CONFLICT DO UPDATE requires inference specification or constraint name", + } + } + + // Validate ON CONFLICT (col, ...) conflict target columns. + if n.OnConflictClause.Infer.IndexElems != nil { + for _, item := range n.OnConflictClause.Infer.IndexElems.Items { + elem, ok := item.(*ast.IndexElem) + if !ok || elem.Name == nil { + continue + } + + if _, exists := colNames[*elem.Name]; !exists { + e := sqlerr.ColumnNotFound(table.Rel.Name, *elem.Name) + e.Location = n.OnConflictClause.Infer.Location + return e + } + } + } + + // Validate DO UPDATE SET col = ... assignment target columns and EXCLUDED.col references. + if n.OnConflictClause.TargetList == nil { + return nil + } + + for _, item := range n.OnConflictClause.TargetList.Items { + target, ok := item.(*ast.ResTarget) + if !ok || target.Name == nil { + continue + } + + if _, exists := colNames[*target.Name]; !exists { + e := sqlerr.ColumnNotFound(table.Rel.Name, *target.Name) + e.Location = target.Location + return e + } + + if ref, ok := target.Val.(*ast.ColumnRef); ok { + if excludedCol, ok := excludedColumnRef(ref); ok { + if _, exists := colNames[excludedCol]; !exists { + e := sqlerr.ColumnNotFound(excludedTable, excludedCol) + e.Location = ref.Location + return e + } + } + } + } + return nil } + +// excludedColumnRef returns the column name if the ColumnRef is an EXCLUDED.col +// reference, and ok=true. Returns "", false otherwise. +func excludedColumnRef(ref *ast.ColumnRef) (string, bool) { + if ref.Fields == nil || len(ref.Fields.Items) != 2 { + return "", false + } + + first, ok := ref.Fields.Items[0].(*ast.String) + if !ok || !strings.EqualFold(first.Str, excludedTable) { + return "", false + } + + second, ok := ref.Fields.Items[1].(*ast.String) + if !ok { + return "", false + } + + return second.Str, true +} diff --git a/internal/sqltest/pgx.go b/internal/sqltest/pgx.go deleted file mode 100644 index 73e01701bd..0000000000 --- a/internal/sqltest/pgx.go +++ /dev/null @@ -1,88 +0,0 @@ -package sqltest - -import ( - "context" - "fmt" - "math/rand" - "os" - "path/filepath" - "testing" - "time" - - "github.com/sqlc-dev/sqlc/internal/sql/sqlpath" - - "github.com/jackc/pgx/v4" -) - -func init() { - rand.Seed(time.Now().UnixNano()) -} - -func PostgreSQLPgx(t *testing.T, migrations []string) (*pgx.Conn, func()) { - t.Helper() - - pgUser := os.Getenv("PG_USER") - pgHost := os.Getenv("PG_HOST") - pgPort := os.Getenv("PG_PORT") - pgPass := os.Getenv("PG_PASSWORD") - pgDB := os.Getenv("PG_DATABASE") - - if pgUser == "" { - pgUser = "postgres" - } - - if pgPass == "" { - pgPass = "mysecretpassword" - } - - if pgPort == "" { - pgPort = "5432" - } - - if pgHost == "" { - pgHost = "127.0.0.1" - } - - if pgDB == "" { - pgDB = "dinotest" - } - - source := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", pgUser, pgPass, pgHost, pgPort, pgDB) - t.Logf("db: %s", source) - - db, err := pgx.Connect(context.Background(), source) - if err != nil { - t.Fatal(err) - } - - // For each test, pick a new schema name at random. - schema := "sqltest_postgresql_" + id() - if _, err := db.Exec(context.Background(), "CREATE SCHEMA "+schema); err != nil { - t.Fatal(err) - } - - sdb, err := pgx.Connect(context.Background(), source+"&search_path="+schema) - if err != nil { - t.Fatal(err) - } - - files, err := sqlpath.Glob(migrations) - if err != nil { - t.Fatal(err) - } - for _, f := range files { - blob, err := os.ReadFile(f) - if err != nil { - t.Fatal(err) - } - if _, err := sdb.Exec(context.Background(), string(blob)); err != nil { - t.Fatalf("%s: %s", filepath.Base(f), err) - } - } - - return sdb, func() { - if _, err := db.Exec(context.Background(), "DROP SCHEMA "+schema+" CASCADE"); err != nil { - t.Fatal(err) - } - } -} diff --git a/internal/sqltest/sqlite.go b/internal/sqltest/sqlite.go index 3ad04bb78d..a3e5db2611 100644 --- a/internal/sqltest/sqlite.go +++ b/internal/sqltest/sqlite.go @@ -7,7 +7,6 @@ import ( "testing" _ "github.com/ncruces/go-sqlite3/driver" - _ "github.com/ncruces/go-sqlite3/embed" "github.com/sqlc-dev/sqlc/internal/sql/sqlpath" ) diff --git a/internal/tools/sqlc-pg-gen/main.go b/internal/tools/sqlc-pg-gen/main.go index d70dcb9595..317b377f90 100644 --- a/internal/tools/sqlc-pg-gen/main.go +++ b/internal/tools/sqlc-pg-gen/main.go @@ -13,7 +13,7 @@ import ( "strings" "text/template" - "github.com/jackc/pgx/v4" + "github.com/jackc/pgx/v5" ) // https://dba.stackexchange.com/questions/255412/how-to-select-functions-that-belong-in-a-given-extension-in-postgresql diff --git a/internal/tools/sqlc-pg-gen/proc.go b/internal/tools/sqlc-pg-gen/proc.go index 07629ed6ea..e4e1c2f89d 100644 --- a/internal/tools/sqlc-pg-gen/proc.go +++ b/internal/tools/sqlc-pg-gen/proc.go @@ -4,7 +4,7 @@ import ( "context" "strings" - pgx "github.com/jackc/pgx/v4" + pgx "github.com/jackc/pgx/v5" ) // https://stackoverflow.com/questions/25308765/postgresql-how-can-i-inspect-which-arguments-to-a-procedure-have-a-default-valu diff --git a/internal/tools/sqlc-pg-gen/relation.go b/internal/tools/sqlc-pg-gen/relation.go index 3b61489392..af8d51eca1 100644 --- a/internal/tools/sqlc-pg-gen/relation.go +++ b/internal/tools/sqlc-pg-gen/relation.go @@ -3,7 +3,7 @@ package main import ( "context" - pgx "github.com/jackc/pgx/v4" + pgx "github.com/jackc/pgx/v5" ) // Relations are the relations available in pg_tables and pg_views diff --git a/internal/x/expander/expander_test.go b/internal/x/expander/expander_test.go index 52d62c6b5e..98cf22981b 100644 --- a/internal/x/expander/expander_test.go +++ b/internal/x/expander/expander_test.go @@ -11,7 +11,6 @@ import ( "github.com/go-sql-driver/mysql" "github.com/jackc/pgx/v5/pgxpool" "github.com/ncruces/go-sqlite3" - _ "github.com/ncruces/go-sqlite3/embed" "github.com/sqlc-dev/sqlc/internal/engine/dolphin" "github.com/sqlc-dev/sqlc/internal/engine/postgresql"