-
Notifications
You must be signed in to change notification settings - Fork 994
Open
Labels
Description
Version
1.30.0
What happened?
Bug: sqlc does not validate column names in ON CONFLICT DO UPDATE SET clause
Description
sqlc fails to validate column names in ON CONFLICT ... DO UPDATE SET clauses against the table schema. This allows invalid queries to be generated that will only fail at runtime when executed against the database.
Steps to Reproduce
- Create a schema file (
migrations/schema.sql):
CREATE TABLE IF NOT EXISTS cart_items
(
owner_id VARCHAR(255) NOT NULL,
product_id UUID NOT NULL,
price_amount DECIMAL NOT NULL,
price_currency VARCHAR(3) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
PRIMARY KEY (owner_id, product_id)
);
CREATE INDEX idx_cart_items_owner ON cart_items (owner_id);
2. Create a query file (query.sql) with an invalid column name in the SET clause:
-- name: AddItem :exec
INSERT INTO cart_items (owner_id, product_id, price_amount, price_currency)
VALUES ($1, $2, $3, $4)
ON CONFLICT (owner_id, product_id) DO UPDATE
SET price_amount1 = EXCLUDED.price_amount1, price_currency = EXCLUDED.price_currency;
Note: The column is price_amount (exists), but the query references price_amount1 (does not exist)
3. Create sqlc.yaml:
version: "2"
sql:
- engine: "postgresql"
schema: "migrations/schema.sql"
queries: "query.sql"
gen:
go:
package: "querytest"
out: "generated"
4. Run sqlc generate
Expected Behavior
sqlc should report an error similar to:
query.sql:5:15: column "price_amount1" of relation "cart_items" does not exist
This matches the behavior when running the same query through PostgreSQL directly.
Actual Behavior
sqlc generates code successfully without any errors, embedding the invalid SQL:
const addItem = `... SET price_amount1 = EXCLUDED.price_amount1 ...`
The generated Go code compiles successfully, but the query will fail at runtime with a database error.
Root Cause
sqlc does not validate column names in ON CONFLICT ... DO UPDATE SET clauses against the table schema. The validation code path is missing:
- OnConflictClause is parsed correctly by the PostgreSQL engine
- But it's never validated in the compiler phase
- Column validation happens in internal/compiler/output_columns.go for SELECT/WHERE clauses, but not for ON CONFLICT clauses
- The validate.InsertStmt() function in internal/sql/validate/insert_stmt.go only validates column count vs value count, not SET clause columns
Files Affected
- internal/compiler/analyze.go - No validation for ON CONFLICT
- internal/sql/validate/insert_stmt.go - Missing ON CONFLICT SET column validation
- internal/compiler/output_columns.go - Missing ON CONFLICT SET clause handling
Workaround
Until this is fixed, ensure column names in ON CONFLICT DO UPDATE SET clauses are manually verified against the schema.
Environment
- sqlc version: v1.30.0 (confirmed on latest main)
- Database engine: PostgreSQL
- Go version: 1.25.0+
### Relevant log output
```shell
Database schema
SQL queries
Configuration
Playground URL
No response
What operating system are you using?
macOS
What database engines are you using?
PostgreSQL
What type of code are you generating?
Go
Reactions are currently unavailable