From 9e35edc857589f78a309b8d674843e81d21a015b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:20:55 +0000 Subject: [PATCH 1/6] Update SelectStmtMixin.kt 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. --- .../psi/core/psi/mixins/SelectStmtMixin.kt | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt index e0a0d5708..53dfc1999 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt @@ -11,6 +11,7 @@ import com.alecstrong.sql.psi.core.psi.SqlColumnExpr import com.alecstrong.sql.psi.core.psi.SqlColumnName import com.alecstrong.sql.psi.core.psi.SqlCompositeElementImpl import com.alecstrong.sql.psi.core.psi.SqlExpr +import com.alecstrong.sql.psi.core.psi.SqlInsertStmt import com.alecstrong.sql.psi.core.psi.SqlIsExpr import com.alecstrong.sql.psi.core.psi.SqlLiteralExpr import com.alecstrong.sql.psi.core.psi.SqlParenExpr @@ -21,6 +22,7 @@ import com.alecstrong.sql.psi.core.psi.asColumns import com.intellij.lang.ASTNode import com.intellij.psi.PsiElement import com.intellij.psi.PsiNamedElement +import com.intellij.psi.util.PsiTreeUtil internal abstract class SelectStmtMixin(node: ASTNode) : SqlCompositeElementImpl(node), SqlSelectStmt, FromQuery { @@ -81,9 +83,14 @@ internal abstract class SelectStmtMixin(node: ASTNode) : } if (child in resultColumnList) { return fromQuery().map { it.copy(adjacent = true) } + - super.queryAvailable(this).map { it.copy(adjacent = false) } + (if (this.isInsertSelect() && !hasSingleRowTable(super.queryAvailable(this))) emptyList() + else super.queryAvailable(this).map { it.copy(adjacent = false) }) } - if (child == joinClause) return super.queryAvailable(child) + + if (child == joinClause) + return (if (this.isInsertSelect() && !hasSingleRowTable(super.queryAvailable(this))) + emptyList() + else super.queryAvailable(child)) return super.queryAvailable(child) } @@ -96,6 +103,14 @@ internal abstract class SelectStmtMixin(node: ASTNode) : return emptyList() } + private fun PsiElement.isInsertSelect(): Boolean { + return PsiTreeUtil.getParentOfType(this, SqlInsertStmt::class.java) != null + } + + private fun hasSingleRowTable(queryResults: Collection): Boolean { + return queryResults.any() { it.table is SingleRow } + } + private fun PsiElement.nonNullIn(whereExpr: SqlExpr): Boolean { if (this is SqlColumnAlias) return source().nonNullIn(whereExpr) if (this is SqlResultColumn) return expr?.nonNullIn(whereExpr) ?: false From 427cf14a0bff856d7e0ea599a9353c3d3a27e99c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:21:10 +0000 Subject: [PATCH 2/6] Fixture tests --- .../fixtures/insert-select-invalid-column/Test.s | 12 ++++++++++++ .../insert-select-invalid-column/failure.txt | 1 + .../resources/fixtures/insert-select-join/Test.s | 14 ++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s create mode 100644 core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt create mode 100644 core/src/testFixtures/resources/fixtures/insert-select-join/Test.s diff --git a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s new file mode 100644 index 000000000..68a6301d3 --- /dev/null +++ b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s @@ -0,0 +1,12 @@ +CREATE TABLE destination ( + destination_id INTEGER PRIMARY KEY, + t TEXT NOT NULL +); + +CREATE TABLE source ( + source_id INTEGER PRIMARY KEY, + t TEXT NOT NULL +); + +INSERT INTO destination (destination_id, t) +SELECT destination_id, t FROM source; diff --git a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt new file mode 100644 index 000000000..26070ffc9 --- /dev/null +++ b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt @@ -0,0 +1 @@ +Test.s line 12:7 - No column found with name destination_id diff --git a/core/src/testFixtures/resources/fixtures/insert-select-join/Test.s b/core/src/testFixtures/resources/fixtures/insert-select-join/Test.s new file mode 100644 index 000000000..4169bca36 --- /dev/null +++ b/core/src/testFixtures/resources/fixtures/insert-select-join/Test.s @@ -0,0 +1,14 @@ +CREATE TABLE destination ( + name TEXT +); + +CREATE TABLE source ( + name TEXT NOT NULL +); + +INSERT INTO destination (name) +SELECT source.name +FROM source +LEFT JOIN destination ON source.name = destination.name +WHERE destination.name IS NULL; + From b1c66e4bd4e9b7133abad21617a18ce07c5a1e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Thu, 26 Mar 2026 16:00:39 +0000 Subject: [PATCH 3/6] Update SelectStmtMixin.kt keepSingleRowTables is a filter --- .../sql/psi/core/psi/mixins/SelectStmtMixin.kt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt index 53dfc1999..8bbaffe22 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt @@ -83,15 +83,13 @@ internal abstract class SelectStmtMixin(node: ASTNode) : } if (child in resultColumnList) { return fromQuery().map { it.copy(adjacent = true) } + - (if (this.isInsertSelect() && !hasSingleRowTable(super.queryAvailable(this))) emptyList() + (if (this.isInsertSelect()) keepSingleRowTables(super.queryAvailable(this)) else super.queryAvailable(this).map { it.copy(adjacent = false) }) } - if (child == joinClause) - return (if (this.isInsertSelect() && !hasSingleRowTable(super.queryAvailable(this))) - emptyList() - else super.queryAvailable(child)) - return super.queryAvailable(child) + return if (child == joinClause && this.isInsertSelect()) + keepSingleRowTables(super.queryAvailable(child)) + else super.queryAvailable(child) } override fun queryExposed() = queryExposed.forFile(containingFile) @@ -107,8 +105,8 @@ internal abstract class SelectStmtMixin(node: ASTNode) : return PsiTreeUtil.getParentOfType(this, SqlInsertStmt::class.java) != null } - private fun hasSingleRowTable(queryResults: Collection): Boolean { - return queryResults.any() { it.table is SingleRow } + private fun keepSingleRowTables(queryResults: Collection): Collection { + return queryResults.filter { it.table is SingleRow } } private fun PsiElement.nonNullIn(whereExpr: SqlExpr): Boolean { From 09cf8a24a61ba29cc29822f388c6e213cf0b8595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Sun, 29 Mar 2026 11:21:03 +0100 Subject: [PATCH 4/6] Update SelectStmtMixin.kt Fix WHERE clause using invalid table column --- .../sql/psi/core/psi/mixins/SelectStmtMixin.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt index 8bbaffe22..addae8118 100644 --- a/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt +++ b/core/src/main/kotlin/com/alecstrong/sql/psi/core/psi/mixins/SelectStmtMixin.kt @@ -59,9 +59,7 @@ internal abstract class SelectStmtMixin(node: ASTNode) : override fun queryAvailable(child: PsiElement): Collection { if (child in exprList || child in (groupBy?.exprList ?: emptyList())) { - val available = - fromQuery().map { it.copy(adjacent = true) } + - super.queryAvailable(this).map { it.copy(adjacent = false) } + val available = fromQuery().map { it.copy(adjacent = true) } + availableFromParent(this) if (ignoreParentProjection) return available val projection = @@ -82,9 +80,7 @@ internal abstract class SelectStmtMixin(node: ASTNode) : return available + projection } if (child in resultColumnList) { - return fromQuery().map { it.copy(adjacent = true) } + - (if (this.isInsertSelect()) keepSingleRowTables(super.queryAvailable(this)) - else super.queryAvailable(this).map { it.copy(adjacent = false) }) + return fromQuery().map { it.copy(adjacent = true) } + availableFromParent(this) } return if (child == joinClause && this.isInsertSelect()) @@ -101,6 +97,11 @@ internal abstract class SelectStmtMixin(node: ASTNode) : return emptyList() } + private fun availableFromParent(child: PsiElement): Collection { + val available = super.queryAvailable(child).map { it.copy(adjacent = false) } + return if (isInsertSelect()) keepSingleRowTables(available) else available + } + private fun PsiElement.isInsertSelect(): Boolean { return PsiTreeUtil.getParentOfType(this, SqlInsertStmt::class.java) != null } From 08d1e9272e80be72a4677329aec66787ad84c313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Sun, 29 Mar 2026 11:21:44 +0100 Subject: [PATCH 5/6] Fixture tests Check invalid table column in WHERE clause --- .../resources/fixtures/insert-select-invalid-column/Test.s | 4 ++++ .../fixtures/insert-select-invalid-column/failure.txt | 1 + 2 files changed, 5 insertions(+) diff --git a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s index 68a6301d3..7b8c07fa2 100644 --- a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s +++ b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/Test.s @@ -10,3 +10,7 @@ CREATE TABLE source ( INSERT INTO destination (destination_id, t) SELECT destination_id, t FROM source; + +INSERT INTO destination (destination_id, t) +SELECT source_id, t FROM source +WHERE destination_id > 0; diff --git a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt index 26070ffc9..043178304 100644 --- a/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt +++ b/core/src/testFixtures/resources/fixtures/insert-select-invalid-column/failure.txt @@ -1 +1,2 @@ Test.s line 12:7 - No column found with name destination_id +Test.s line 16:6 - No column found with name destination_id From 2fe5382cb7b21e69698f8ea8be67dde2c0b69882 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?griff=20=D1=96=E2=8A=99?= <346896+griffio@users.noreply.github.com> Date: Mon, 30 Mar 2026 09:11:37 +0100 Subject: [PATCH 6/6] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c490b946..5b761e1ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased - Fix a compilation error with migration files when CREATE UNIQUE INDEX referenced by FOREIGN KEY (https://github.com/sqldelight/sql-psi/pull/732) +- Fix insert statement exposes columns to a select statement when used as the row source (https://github.com/sqldelight/sql-psi/pull/750) ## [0.7.3] - 2026-03-13 [0.7.3]: https://github.com/sqldelight/sql-psi/releases/tag/0.7.3