diff --git a/.coderabbit.yaml b/.coderabbit.yaml index 0591de4..26878c5 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -43,7 +43,7 @@ reviews: path_instructions: - path: "**/*.go" instructions: >- - Go 1.26; modern idioms expected (range-over-int, `any`, compile-time + Go 1.27; modern idioms expected (range-over-int, `any`, compile-time interface asserts `var _ I = (*T)(nil)`). Keep the core dependency-light: analyzer, middleware and reporter must stay free of third-party deps and of YAML. Flag new external imports in those packages. Watch for diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8c6d84..9833f71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go-version: ["1.26"] + go-version: ["1.27"] steps: - uses: actions/checkout@v7 with: @@ -109,7 +109,7 @@ jobs: - uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27" - name: Run integration tests run: make test-integration @@ -139,14 +139,71 @@ jobs: - uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27" + + # Version comes from the Makefile so a local `make lint` and this gate + # run the same linter. Nothing bumps it automatically — Dependabot does + # not track action `with:` inputs — so refresh GOLANGCI_LINT_VERSION + # deliberately. + - name: Resolve golangci-lint version + id: golangci-lint-version + run: echo "version=$(make -s print-golangci-lint-version)" >> "$GITHUB_OUTPUT" - uses: golangci/golangci-lint-action@v9 with: - version: v2.12.2 + version: ${{ steps.golangci-lint-version.outputs.version }} working-directory: ${{ matrix.module }} args: --timeout=5m + # Not redundant with Dependabot or CodeQL, which cover different things: + # Dependabot reports that a dependency is behind, CodeQL looks for bug + # patterns in our own code. govulncheck cross-references the Go + # vulnerability database against the call graph, so it reports only + # advisories this code actually reaches. + # + # Scanned per module for the same reason `lint` is: the root module's + # ./... stops at nested go.mod boundaries, so the satellites' own + # dependency trees are invisible to a scan run from the root. + vuln: + name: govulncheck (${{ matrix.module }}) + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + module: + - . + - integrations/gormguard + - integrations/sqlxguard + - integrations/pgxguard + - integrations/bunguard + - integrations/xormguard + - integrations/entguard + - parsers/pgparser + - parsers/mysqlparser + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - uses: actions/setup-go@v7 + with: + go-version: "1.27" + + # Version comes from the Makefile so a local `make vuln` and this gate + # run the same scanner. Nothing bumps it automatically — Dependabot + # does not track `go install` lines — so refresh GOVULNCHECK_VERSION + # deliberately. The advisory database is still fetched at run time, so + # an older scanner still reports current advisories. + - name: Install govulncheck + run: | + version="$(make -s print-govulncheck-version)" + echo "govulncheck $version" + go install "golang.org/x/vuln/cmd/govulncheck@$version" + + - name: Scan + working-directory: ${{ matrix.module }} + run: govulncheck ./... + build: runs-on: ubuntu-latest steps: @@ -156,7 +213,7 @@ jobs: - uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27" - name: Build CLI run: go build -o bin/sqlguard ./cmd/sqlguard @@ -170,7 +227,7 @@ jobs: - uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27" # `make coverage` runs every module and merges into a single coverage.out # (root go test does not reach the satellite modules). diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d422ffe..ee3ae0d 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -31,7 +31,7 @@ jobs: - name: Setup Go uses: actions/setup-go@v7 with: - go-version: "1.26" + go-version: "1.27" - name: Initialize CodeQL uses: github/codeql-action/init@v4 diff --git a/.golangci.yml b/.golangci.yml index 13ac280..d9cec3e 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,5 +1,11 @@ version: "2" +# Report every occurrence. The defaults (max-same-issues: 3) hide duplicates, +# which makes a lint failure look smaller than it is. +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + linters: enable: - errcheck @@ -15,10 +21,31 @@ linters: # Security & correctness (sqlguard is a security-adjacent tool). - gosec # SAST — SQL injection, unhandled crypto/file ops, etc. - errorlint # correct error wrapping / errors.Is / errors.As usage + - errname # sentinel errors must be named Err*, error types *Error - bodyclose # response/rows bodies must be closed - nilerr # returning nil after a non-nil error check + - nilnesserr # returning a nil error while a wrapped error is still live + # Concurrency and context correctness — the driver chain and QueryTracker + # are concurrent, and every analysis entry point takes a context.Context. + - contextcheck + - fatcontext + - noctx + - durationcheck - unconvert # remove redundant type conversions - usestdlibvars # prefer stdlib constants (http.MethodGet, sql.LevelReadOnly…) + # Guard.Check/Observe run on every query through the driver chain and are + # documented as allocation-light — keep the hot path honest. + - perfsprint + - makezero + - wastedassign + - asasalint + - reassign + # Modern Go idioms expected repo-wide (see AGENTS.md): range-over-int, + # no unnecessary loop-var copies now that Go 1.22+ scopes them per-iteration. + - copyloopvar + - intrange + # Keep //nolint directives specific and explained. + - nolintlint settings: gocyclo: min-complexity: 15 @@ -31,14 +58,31 @@ linters: # and file/crypto checks (G201/G202/G3xx/G4xx) stay on. excludes: - G115 + errcheck: + # An unchecked type assertion panics; deliberate `_ =` discards still pass. + check-type-assertions: true + nolintlint: + require-explanation: true + require-specific: true exclusions: rules: - linters: - errcheck - gosec # test fixtures use lax file perms / ignore setup errors path: _test\.go + # Tests may assert on unwrapped errors, build requests/queries without a + # context, and use fmt.Sprintf freely; none of that ships to consumers. + - linters: + - bodyclose + - errorlint + - noctx + - perfsprint + path: _test\.go formatters: enable: - gofmt - goimports + settings: + gofmt: + simplify: true diff --git a/AGENTS.md b/AGENTS.md index 879a84a..0c9fba8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,12 +12,13 @@ or `parsers/*`, which are separate Go modules. The `MODULES` variable drives the loop so a target can't silently skip a satellite. - `make all` — `tidy fmt vet lint build test` across all modules. -- `make ci` — the CI pipeline: `fmt-check vet lint test-race`. +- `make ci` — the CI pipeline: `fmt-check vet lint vuln test-race`. - `make build` — `go build ./...` in every module (compile check). `make cli` builds the `bin/sqlguard` binary; `make install` installs it. - `make test` — `go test -count=1 ./...` in every module. `make test-race` adds `-race`; `make coverage` writes a merged `coverage.out`. - `make lint` — `golangci-lint run` in every module (config in `.golangci.yml`, v2 schema). `make fmt` / `make fmt-check` run `gofmt -s` + `goimports`. -- `make tidy` — `go mod tidy` across all nine modules. Run after any dependency change; tidying only the root leaves the others stale. -- `make setup` — installs pinned `golangci-lint` / `goimports` if missing (a prereq of `lint`/`fmt`). +- `make tidy` — `go mod tidy` across all nine modules. Run after any dependency change; tidying only the root leaves the others stale. `make tidy-check` fails (without leaving the change behind) if any module's go.mod/go.sum is stale — CI hygiene, not part of `all`/`ci`. +- `make vuln` — `govulncheck` in every module, filtered to advisories the code actually reaches. Needs network access (fetches the advisory database each run). +- `make setup` — installs pinned `golangci-lint` / `goimports` / `govulncheck` if missing (a prereq of `lint`/`fmt`/`vuln`). `make print-golangci-lint-version` / `make print-govulncheck-version` print the pinned versions so CI resolves them from here instead of a second hardcoded copy. - The committed `go.work` makes every satellite compile against this tree, not the published core it `require`s — so a breaking change to `analyzer/`/`middleware/` fails their tests. No `go.mod` here has a `replace`. Use `GOWORK=off` to see a consumer's build. Releasing is manual (see CONTRIBUTING.md). - `make db-up` / `make test-integration` / `make db-down` — run `explain/` against live Postgres, MySQL and MariaDB (`test/integration/`, behind the `integration` build tag). @@ -27,7 +28,7 @@ Run a single test: `go test ./middleware/ -run TestDriver_QueryDetectsSelectStar ## Module topology -Nine Go modules, all on **Go 1.26**, kept in lockstep: +Nine Go modules, all on **Go 1.27**, kept in lockstep: - root (`github.com/KARTIKrocks/sqlguard`) — core analyzer, middleware, reporter, `config`, CLI. Near-zero-dependency: `analyzer`/`middleware`/`reporter` stay dependency-free; the only third-party deps are sqlite3 (CLI `db`/tests), cobra (CLI), and `gopkg.in/yaml.v3` (isolated to the `config` package). Importing `analyzer`/`middleware` does not pull YAML. - `parsers/pgparser`, `parsers/mysqlparser` — opt-in real SQL grammars, isolated in their own modules so the heavy parser deps never enter a consumer's build unless explicitly imported. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9f9025b..b6f8887 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ project-specific things that aren't obvious from a quick look at the repo. ## Project layout -sqlguard is a **multi-module repo** — nine Go modules on Go 1.26, kept in +sqlguard is a **multi-module repo** — nine Go modules on Go 1.27, kept in lockstep: - **root** (`github.com/KARTIKrocks/sqlguard`) — core analyzer, middleware, @@ -32,9 +32,9 @@ depends on these modules. To reproduce a consumer's build, set `GOWORK=off`. ## Development workflow ```bash -make setup # install pinned golangci-lint + goimports (one-time) +make setup # install pinned golangci-lint + goimports + govulncheck (one-time) make all # tidy, fmt, vet, lint, build, test across all nine modules -make ci # what CI runs: fmt-check, vet, lint, test-race +make ci # what CI runs: fmt-check, vet, lint, vuln, test-race make test-race # race detector (required for anything touching middleware) make help # list every target ``` diff --git a/Makefile b/Makefile index 6c618da..05964b2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ -GOLANGCI_LINT_VERSION := v2.12.2 +GOLANGCI_LINT_VERSION := v2.13.2 GOIMPORTS_VERSION := v0.45.0 +GOVULNCHECK_VERSION := v1.8.0 # Sub-modules carry their own go.mod (heavy/opt-in deps kept out of the core # import graph). `go test ./...` from root does NOT reach them, so every @@ -28,7 +29,7 @@ SQLGUARD_TEST_PG_DSN ?= postgres://sqlguard:sqlguard@localhost:55432/sqlguard?ss SQLGUARD_TEST_MYSQL_DSN ?= root:sqlguard@tcp(localhost:53306)/sqlguard SQLGUARD_TEST_MARIADB_DSN ?= root:sqlguard@tcp(localhost:53307)/sqlguard -.PHONY: all help setup deps ci test test-v test-race coverage lint lint-fix fix fmt fmt-check vet tidy build cli install bench clean db-up db-down test-integration vet-integration +.PHONY: all help setup deps ci test test-v test-race coverage lint lint-fix fix fmt fmt-check vet tidy tidy-check build cli install bench clean db-up db-down test-integration vet-integration vuln print-golangci-lint-version print-govulncheck-version all: tidy fmt vet lint build test @@ -53,6 +54,8 @@ help: @echo " fmt - Format code (gofmt -s + goimports)" @echo " fmt-check - Verify formatting without modifying files" @echo " tidy - Run go mod tidy (all modules)" + @echo " tidy-check - Fail if go.mod/go.sum are not tidy (all modules)" + @echo " vuln - Run govulncheck (all modules)" @echo " build - Build all packages (all modules)" @echo " cli - Build the sqlguard CLI to bin/sqlguard" @echo " install - Install the CLI to \$$GOPATH/bin" @@ -69,6 +72,10 @@ setup: echo "Installing goimports $(GOIMPORTS_VERSION)..."; \ go install golang.org/x/tools/cmd/goimports@$(GOIMPORTS_VERSION); \ } + @command -v govulncheck >/dev/null 2>&1 || { \ + echo "Installing govulncheck $(GOVULNCHECK_VERSION)..."; \ + go install golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION); \ + } ## Download module dependencies across all modules deps: @@ -77,8 +84,8 @@ deps: (cd $$mod && go mod download) || exit 1; \ done -## CI: run formatting check, vet, lint and tests with race detector -ci: fmt-check vet lint test-race +## CI: run formatting check, vet, lint, vulnerability scan and tests with race detector +ci: fmt-check vet lint vuln test-race ## Build all packages across all modules (compile check) build: @@ -189,6 +196,47 @@ tidy: (cd $$mod && go mod tidy) || exit 1; \ done +## Fail if any go.mod/go.sum is not tidy, without leaving the change behind. +## Suitable for CI, where a stale go.sum should block the merge. +tidy-check: + @status=$$(git status --porcelain -- $(foreach mod,$(MODULES),$(mod)/go.mod $(mod)/go.sum)); \ + if [ -n "$$status" ]; then \ + echo "go.mod/go.sum already modified; commit or stash before running tidy-check"; \ + exit 1; \ + fi + @$(MAKE) --no-print-directory tidy + @if ! git diff --quiet -- '*go.mod' '*go.sum'; then \ + echo "go.mod/go.sum are not tidy — run 'make tidy' and commit:"; \ + git diff --stat -- '*go.mod' '*go.sum'; \ + git checkout -- '*go.mod' '*go.sum'; \ + exit 1; \ + fi + @echo "all modules tidy" + +## Scan every module for known vulnerabilities, filtered to advisories the code +## actually reaches. Needs network access — the advisory database is fetched on +## every run. Note this also scans the standard library of whichever Go +## toolchain you have installed, so it can fail locally on a green branch when +## your Go is a patch release behind the one CI pins — that is a real finding +## about your machine, not a false positive. +vuln: setup + @for mod in $(MODULES); do \ + echo "==> Scanning $$mod"; \ + (cd $$mod && govulncheck ./...) || exit 1; \ + done + +## Print the pinned linter version. CI resolves golangci-lint-action's version +## input from this rather than hardcoding a second copy of the number, so the +## workflow and this file cannot drift apart. +print-golangci-lint-version: + @echo $(GOLANGCI_LINT_VERSION) + +## Print the pinned scanner version. CI installs govulncheck with this rather +## than hardcoding a second copy of the number, so the workflow and this file +## cannot drift apart. +print-govulncheck-version: + @echo $(GOVULNCHECK_VERSION) + ## Run benchmarks across all modules bench: @for mod in $(MODULES); do \ diff --git a/analyzer/fallback.go b/analyzer/fallback.go index 53e43df..41185b6 100644 --- a/analyzer/fallback.go +++ b/analyzer/fallback.go @@ -250,7 +250,7 @@ func hasUnsafeAddNotNull(sanitized string) bool { func splitTopLevelCommas(s string) []string { var segs []string depth, start := 0, 0 - for i := 0; i < len(s); i++ { + for i := range len(s) { switch s[i] { case '(': depth++ diff --git a/cmd/sqlguard/db.go b/cmd/sqlguard/db.go index 649a0ef..fcaf220 100644 --- a/cmd/sqlguard/db.go +++ b/cmd/sqlguard/db.go @@ -1,12 +1,13 @@ package main import ( + "context" "database/sql" "fmt" ) // openDB opens a database connection using the appropriate driver. -func openDB(dialect, dsn string) (*sql.DB, error) { +func openDB(ctx context.Context, dialect, dsn string) (*sql.DB, error) { var driverName string switch dialect { case "postgres": @@ -22,7 +23,7 @@ func openDB(dialect, dsn string) (*sql.DB, error) { return nil, err } - if err := db.Ping(); err != nil { + if err := db.PingContext(ctx); err != nil { _ = db.Close() return nil, fmt.Errorf("cannot reach database: %w", err) } diff --git a/cmd/sqlguard/explain.go b/cmd/sqlguard/explain.go index 8379b73..93c8a30 100644 --- a/cmd/sqlguard/explain.go +++ b/cmd/sqlguard/explain.go @@ -41,7 +41,10 @@ func runExplain(cmd *cobra.Command, args []string) error { query := args[0] - db, err := openDB(explainDialect, explainDSN) + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + db, err := openDB(ctx, explainDialect, explainDSN) if err != nil { return fmt.Errorf("failed to connect: %w", err) } @@ -56,9 +59,6 @@ func runExplain(cmd *cobra.Command, args []string) error { return err } - ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) - defer cancel() - result, err := analyzer.Analyze(ctx, query) if err != nil { return err diff --git a/explain/explain.go b/explain/explain.go index 0f8c9ac..aa3c08a 100644 --- a/explain/explain.go +++ b/explain/explain.go @@ -7,6 +7,7 @@ import ( "context" "database/sql" "encoding/json" + "errors" "fmt" "strconv" "strings" @@ -38,7 +39,7 @@ func WithAllowDML() Option { // dialect must be "postgres" or "mysql". func New(db *sql.DB, dialect string, opts ...Option) (*PlanAnalyzer, error) { if db == nil { - return nil, fmt.Errorf("explain: db is nil") + return nil, errors.New("explain: db is nil") } dialect = strings.ToLower(dialect) if dialect != "postgres" && dialect != "mysql" { @@ -106,10 +107,10 @@ func (p *PlanAnalyzer) Analyze(ctx context.Context, query string) (*Result, erro func (p *PlanAnalyzer) validate(query string) (string, analyzer.StmtKind, error) { q := strings.TrimSpace(query) if q == "" { - return "", analyzer.StmtUnknown, fmt.Errorf("explain: refusing to explain an empty query") + return "", analyzer.StmtUnknown, errors.New("explain: refusing to explain an empty query") } if analyzer.IsMultiStatement(q) { - return "", analyzer.StmtUnknown, fmt.Errorf("explain: refusing to explain multi-statement input") + return "", analyzer.StmtUnknown, errors.New("explain: refusing to explain multi-statement input") } q = strings.TrimRight(q, "; \t\r\n") @@ -119,11 +120,11 @@ func (p *PlanAnalyzer) validate(query string) (string, analyzer.StmtKind, error) return q, st.Kind, nil case analyzer.StmtInsert, analyzer.StmtUpdate, analyzer.StmtDelete: if !p.allowDML { - return "", st.Kind, fmt.Errorf("explain: refusing to EXPLAIN a data-modifying statement by default; construct the analyzer with explain.WithAllowDML to opt in") + return "", st.Kind, errors.New("explain: refusing to EXPLAIN a data-modifying statement by default; construct the analyzer with explain.WithAllowDML to opt in") } return q, st.Kind, nil default: - return "", st.Kind, fmt.Errorf("explain: refusing to explain a non-SELECT/WITH/DML statement (DDL, SET, transaction control, or unrecognized)") + return "", st.Kind, errors.New("explain: refusing to explain a non-SELECT/WITH/DML statement (DDL, SET, transaction control, or unrecognized)") } } @@ -155,9 +156,6 @@ func (p *PlanAnalyzer) analyzePostgres(ctx context.Context, query string) (*Resu // unavoidable; safety comes from validate() plus the rolled-back, // read-only transaction below. We never use EXPLAIN ANALYZE, so the // statement is planned, not executed. - //nolint:gosec // G202: EXPLAIN takes no bind params, so concatenation is by - // design; the defense is validate() + the rolled-back read-only tx, not - // parameterization. explainQuery := "EXPLAIN (FORMAT JSON) " + query tx, err := p.db.BeginTx(ctx, &sql.TxOptions{ReadOnly: true}) @@ -234,10 +232,8 @@ func (p *PlanAnalyzer) analyzeMySQL(ctx context.Context, query string, dml bool) // @@explain_format to TREE, which yields one free-text column and no // per-table rows to inspect; the clause restores the classic output and is // also accepted by MySQL 5.7/8 and MariaDB. - // //nolint:gosec // G202: EXPLAIN takes no bind params, so concatenation is by - // design; the defense is validate() + the rolled-back tx, not - // parameterization. + // design; the defense is validate() + the rolled-back tx, not parameterization. explainQuery := "EXPLAIN FORMAT=TRADITIONAL " + query // MySQL and MariaDB reject *any* statement inside a READ ONLY transaction @@ -337,7 +333,7 @@ func mysqlRowIssues(query string, col func(string) string) []analyzer.Result { RuleName: "no-index-used", Severity: analyzer.SeverityWarning, Query: query, - Message: fmt.Sprintf("No index used on table %s", table), + Message: "No index used on table " + table, Suggestion: "Consider adding an index on the filtered/joined columns.", }) } @@ -348,7 +344,7 @@ func mysqlRowIssues(query string, col func(string) string) []analyzer.Result { RuleName: "filesort", Severity: analyzer.SeverityInfo, Query: query, - Message: fmt.Sprintf("Filesort detected on table %s", table), + Message: "Filesort detected on table " + table, Suggestion: "Consider adding an index that covers the ORDER BY columns.", }) } diff --git a/go.mod b/go.mod index be5bfa7..0687459 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard -go 1.26 +go 1.27 require ( github.com/mattn/go-sqlite3 v1.14.50 diff --git a/go.work b/go.work index 6169f1f..f61200c 100644 --- a/go.work +++ b/go.work @@ -16,7 +16,7 @@ // // To reproduce a consumer's build instead, set GOWORK=off. -go 1.26 +go 1.27 use ( . diff --git a/integrations/bunguard/go.mod b/integrations/bunguard/go.mod index 77fb3d4..ae245bf 100644 --- a/integrations/bunguard/go.mod +++ b/integrations/bunguard/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard/integrations/bunguard -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.1 diff --git a/integrations/entguard/go.mod b/integrations/entguard/go.mod index d9599fe..8af896b 100644 --- a/integrations/entguard/go.mod +++ b/integrations/entguard/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard/integrations/entguard -go 1.26 +go 1.27 require ( entgo.io/ent v0.14.6 diff --git a/integrations/gormguard/go.mod b/integrations/gormguard/go.mod index fced166..89a22f0 100644 --- a/integrations/gormguard/go.mod +++ b/integrations/gormguard/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard/integrations/gormguard -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.1 diff --git a/integrations/pgxguard/go.mod b/integrations/pgxguard/go.mod index a3a5625..48c01b0 100644 --- a/integrations/pgxguard/go.mod +++ b/integrations/pgxguard/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard/integrations/pgxguard -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.1 diff --git a/integrations/sqlxguard/go.mod b/integrations/sqlxguard/go.mod index bf32b8a..1d4a4e8 100644 --- a/integrations/sqlxguard/go.mod +++ b/integrations/sqlxguard/go.mod @@ -1,12 +1,11 @@ module github.com/KARTIKrocks/sqlguard/integrations/sqlxguard -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.1 github.com/jmoiron/sqlx v1.4.0 + github.com/mattn/go-sqlite3 v1.14.50 ) -require github.com/mattn/go-sqlite3 v1.14.50 - require github.com/go-sql-driver/mysql v1.10.1 // indirect diff --git a/integrations/sqlxguard/sqlxguard.go b/integrations/sqlxguard/sqlxguard.go index 6ddcdbb..e2743b0 100644 --- a/integrations/sqlxguard/sqlxguard.go +++ b/integrations/sqlxguard/sqlxguard.go @@ -97,7 +97,7 @@ func (w *WrappedDB) GetContext(ctx context.Context, dest any, query string, args // Query executes a query that returns rows. func (w *WrappedDB) Query(query string, args ...any) (*sql.Rows, error) { done := w.g.Observe(query) - rows, err := w.db.Query(query, args...) + rows, err := w.db.Query(query, args...) //nolint:noctx // deliberate passthrough of sqlx.DB's own non-context method done(err) return rows, err } @@ -121,7 +121,7 @@ func (w *WrappedDB) Queryx(query string, args ...any) (*sqlx.Rows, error) { // Exec executes a query without returning rows. func (w *WrappedDB) Exec(query string, args ...any) (sql.Result, error) { done := w.g.Observe(query) - result, err := w.db.Exec(query, args...) + result, err := w.db.Exec(query, args...) //nolint:noctx // deliberate passthrough of sqlx.DB's own non-context method done(err) return result, err } @@ -151,7 +151,7 @@ func (w *WrappedDB) NamedExecContext(ctx context.Context, query string, arg any) } // Ping verifies the database connection. -func (w *WrappedDB) Ping() error { return w.db.Ping() } +func (w *WrappedDB) Ping() error { return w.db.Ping() } //nolint:noctx // deliberate passthrough of sqlx.DB's own non-context method // Close closes the database connection. func (w *WrappedDB) Close() error { return w.db.Close() } diff --git a/integrations/xormguard/go.mod b/integrations/xormguard/go.mod index 24656e2..a80f7c8 100644 --- a/integrations/xormguard/go.mod +++ b/integrations/xormguard/go.mod @@ -1,6 +1,6 @@ module github.com/KARTIKrocks/sqlguard/integrations/xormguard -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.1 diff --git a/middleware/cache.go b/middleware/cache.go index 2389f1c..5e56d51 100644 --- a/middleware/cache.go +++ b/middleware/cache.go @@ -52,7 +52,7 @@ func (c *analysisCache) get(query string) ([]analyzer.Result, bool) { defer c.mu.Unlock() if el, ok := c.items[query]; ok { c.ll.MoveToFront(el) - return el.Value.(*cacheEntry).results, true + return el.Value.(*cacheEntry).results, true //nolint:errcheck // every element pushed by put is a *cacheEntry } return nil, false } @@ -64,7 +64,7 @@ func (c *analysisCache) put(query string, results []analyzer.Result) { defer c.mu.Unlock() if el, ok := c.items[query]; ok { c.ll.MoveToFront(el) - el.Value.(*cacheEntry).results = results + el.Value.(*cacheEntry).results = results //nolint:errcheck // every element pushed by put is a *cacheEntry return } el := c.ll.PushFront(&cacheEntry{key: query, results: results}) @@ -72,7 +72,7 @@ func (c *analysisCache) put(query string, results []analyzer.Result) { if c.ll.Len() > c.capacity { if oldest := c.ll.Back(); oldest != nil { c.ll.Remove(oldest) - delete(c.items, oldest.Value.(*cacheEntry).key) + delete(c.items, oldest.Value.(*cacheEntry).key) //nolint:errcheck // every element pushed by put is a *cacheEntry } } } diff --git a/middleware/driver.go b/middleware/driver.go index 8be10ea..363a1a0 100644 --- a/middleware/driver.go +++ b/middleware/driver.go @@ -231,7 +231,7 @@ func (c *wConn) QueryContext(ctx context.Context, query string, args []driver.Na return nil, verr } done := c.g.Observe(query) - rows, err := q.Query(query, values) //nolint:staticcheck // legacy fallback + rows, err := q.Query(query, values) done(err) return rows, err } @@ -254,7 +254,7 @@ func (c *wConn) ExecContext(ctx context.Context, query string, args []driver.Nam return nil, verr } done := c.g.Observe(query) - res, err := e.Exec(query, values) //nolint:staticcheck // legacy fallback + res, err := e.Exec(query, values) done(err) return res, err } diff --git a/parsers/mysqlparser/go.mod b/parsers/mysqlparser/go.mod index e5ab408..0e0dcba 100644 --- a/parsers/mysqlparser/go.mod +++ b/parsers/mysqlparser/go.mod @@ -1,7 +1,8 @@ module github.com/KARTIKrocks/sqlguard/parsers/mysqlparser -go 1.26 +go 1.27 -require github.com/KARTIKrocks/sqlguard v0.1.1 - -require github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 +require ( + github.com/KARTIKrocks/sqlguard v0.1.1 + github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 +) diff --git a/parsers/pgparser/go.mod b/parsers/pgparser/go.mod index 4171596..7995675 100644 --- a/parsers/pgparser/go.mod +++ b/parsers/pgparser/go.mod @@ -1,18 +1,13 @@ module github.com/KARTIKrocks/sqlguard/parsers/pgparser -go 1.26 - -require github.com/KARTIKrocks/sqlguard v0.1.1 +go 1.27 require ( - github.com/google/go-cmp v0.6.0 // indirect - github.com/rogpeppe/go-internal v1.6.1 // indirect - github.com/stretchr/testify v1.11.1 // indirect - golang.org/x/net v0.58.0 // indirect + github.com/KARTIKrocks/sqlguard v0.1.1 + github.com/auxten/postgresql-parser v1.0.1 ) require ( - github.com/auxten/postgresql-parser v1.0.1 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect github.com/cockroachdb/apd v1.1.1-0.20181017181144-bced77f817b4 // indirect github.com/cockroachdb/errors v1.8.2 // indirect @@ -23,14 +18,18 @@ require ( github.com/getsentry/raven-go v0.2.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.4.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/konsorten/go-windows-terminal-sequences v1.0.3 // indirect github.com/kr/pretty v0.3.0 // indirect github.com/kr/text v0.2.0 // indirect github.com/lib/pq v1.10.9 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/rogpeppe/go-internal v1.6.1 // indirect github.com/sirupsen/logrus v1.6.0 // indirect github.com/spf13/pflag v1.0.10 // indirect + github.com/stretchr/testify v1.11.1 // indirect + golang.org/x/net v0.58.0 // indirect golang.org/x/sync v0.22.0 // indirect golang.org/x/sys v0.47.0 // indirect golang.org/x/text v0.41.0 // indirect diff --git a/test/integration/go.mod b/test/integration/go.mod index d033018..475e4ff 100644 --- a/test/integration/go.mod +++ b/test/integration/go.mod @@ -6,7 +6,7 @@ // working tree. module github.com/KARTIKrocks/sqlguard/test/integration -go 1.26 +go 1.27 require ( github.com/KARTIKrocks/sqlguard v0.1.0