Skip to content

Fix insert exposes columns to select when used as row source#750

Open
griffio wants to merge 6 commits intosqldelight:masterfrom
griffio:fix-insert-exposes-columns-to-select
Open

Fix insert exposes columns to select when used as row source#750
griffio wants to merge 6 commits intosqldelight:masterfrom
griffio:fix-insert-exposes-columns-to-select

Conversation

@griffio
Copy link
Copy Markdown
Contributor

@griffio griffio commented Mar 26, 2026

fixes #601
fixes sqldelight/sqldelight#6194

🦺 Attempt to fix exposed columns in SELECT when used as row source for INSERT,
inherited columns from Triggers and use by CONFLICT clauses are allowed.

Removes inherited parent QueryResult from the SelectStmtMixin where the ultimate parent is SqlInsertStmt
except If the inherited parent QueryResult contains any SingleRow used with triggers and upsert statements.

Must fail with destination_id is not found

INSERT INTO destination (destination_id, t)
SELECT destination_id, t FROM source;

Must fail WHERE destination_id references invalid column

INSERT INTO destination (destination_id, t)
SELECT source_id, t FROM source
WHERE destination_id > 10;

Must fail with id is not found in SELECT, must allow ON CONFLICT(id)

INSERT INTO my_user(id)
SELECT id FROM other_user WHERE TRUE
ON CONFLICT(id) DO NOTHING;

Must succeed as the INSERT table destination is not visible from the SELECT row source.

INSERT INTO destination (name)
SELECT source.name
FROM source
LEFT JOIN destination ON source.name = destination.name
WHERE destination.name IS NULL;
  • Tested this PR branch with SqlDelight

NOTE:
When updating sql-psi dependency in SqlDelight this test will fail,
https://github.com/sqldelight/sqldelight/blob/master/dialects/postgresql/src/testFixtures/resources/fixtures_postgresql/cte-invalid-tables/failure.txt and will need to add Sample.s line 18:7 - No column found with name actor_id

Separate issue RETURNING fails with <compound operator real>, <join operator real>, GROUP, HAVING, INDEXED, LIMIT, NOT, ON, ORDER, RETURNING, WHERE or WINDOW expected, got 'destination_id']
related to sqldelight/sqldelight#4938 can be worked-around with ON CONFLICT (destination_id) DO NOTHING

INSERT INTO destination (destination_id, t)
SELECT source_id, t FROM source
RETURNING destination_id;

  • CHANGELOG.md's "Unreleased" section has been updated, if applicable.

griffio added 3 commits March 26, 2026 12:20
When the select stmt has a parent insert stmt, the insert resultQuery is omitted expect when the resultQuery contains a single row table for triggers and upserts.
keepSingleRowTables is a filter
}

private fun keepSingleRowTables(queryResults: Collection<QueryResult>): Collection<QueryResult> {
return queryResults.filter { it.table is SingleRow }
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include only inherited SingleRow tables that are trigger table rows and on conflict table rows.

griffio added 3 commits March 29, 2026 11:21
Fix WHERE clause using invalid table column
Check invalid table column in WHERE clause
@griffio griffio marked this pull request as ready for review March 30, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Runtime Crash from bogus migration INSERT INTO query Insert Statement exposes its columns in the SELECT query

1 participant