From 26e9a9918f177681a90a2db1f94831c3da75dc84 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: Tue, 13 Feb 2024 11:08:01 +0000 Subject: [PATCH 1/3] Add mixin to grammar to process rules in AlterTableAddConstraintMixin --- .../sqldelight/dialects/postgresql/grammar/PostgreSql.bnf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/PostgreSql.bnf b/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/PostgreSql.bnf index 6e726c86cfc..690c1fced83 100644 --- a/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/PostgreSql.bnf +++ b/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/PostgreSql.bnf @@ -314,7 +314,9 @@ alter_table_drop_column ::= DROP [ COLUMN ] {column_name} { pin = 1 } -alter_table_add_constraint ::= ADD table_constraint +alter_table_add_constraint ::= ADD table_constraint { + mixin = "app.cash.sqldelight.dialects.postgresql.grammar.mixins.AlterTableAddConstraintMixin" +} type_clause ::= 'TYPE' From 815dd9e4012934279e07c32882b08912501900b7 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: Tue, 13 Feb 2024 11:08:34 +0000 Subject: [PATCH 2/3] Add AlterTableAddConstraintMixin This takes a lazyQuery as input, checks if the table constraint is a primary key, updates any matching columns to not nullable, and returns a new lazyQuery with the transformed columns. This has the effect of propagating primary key nullability constraints to the columns when altering the table. --- .../mixins/AlterTableAddConstraintMixin.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/mixins/AlterTableAddConstraintMixin.kt diff --git a/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/mixins/AlterTableAddConstraintMixin.kt b/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/mixins/AlterTableAddConstraintMixin.kt new file mode 100644 index 00000000000..32abca5f3c6 --- /dev/null +++ b/dialects/postgresql/src/main/kotlin/app/cash/sqldelight/dialects/postgresql/grammar/mixins/AlterTableAddConstraintMixin.kt @@ -0,0 +1,27 @@ +package app.cash.sqldelight.dialects.postgresql.grammar.mixins + +import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlAlterTableAddConstraint +import com.alecstrong.sql.psi.core.psi.AlterTableApplier +import com.alecstrong.sql.psi.core.psi.LazyQuery +import com.alecstrong.sql.psi.core.psi.SqlCompositeElementImpl +import com.alecstrong.sql.psi.core.psi.SqlTypes +import com.intellij.lang.ASTNode + +abstract class AlterTableAddConstraintMixin(node: ASTNode) : + SqlCompositeElementImpl(node), + PostgreSqlAlterTableAddConstraint, + AlterTableApplier { + override fun applyTo(lazyQuery: LazyQuery): LazyQuery = + if (tableConstraint.node.findChildByType(SqlTypes.PRIMARY) != null && + tableConstraint.node.findChildByType(SqlTypes.KEY) != null + ) { + val columns = lazyQuery.query.columns.map { queryCol -> + tableConstraint.indexedColumnList.find { indexedCol -> queryCol.element.textMatches(indexedCol) }.let { + queryCol.copy(nullable = if (it != null) false else queryCol.nullable) + } + } + LazyQuery(lazyQuery.tableName, query = { lazyQuery.query.copy(columns = columns) }) + } else { + lazyQuery + } +} From f9c237d73900b405bb034f1652e6f624c8f55fc4 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: Tue, 13 Feb 2024 11:11:13 +0000 Subject: [PATCH 3/3] Add migration test fixtures New test for MigrationQueryTest for Postgresql - not relevant for Sqlite as can't alter table to add primary keys Add tests for compiler generation for single and compound primary keys --- .../core/migrations/MigrationQueryTest.kt | 4 ++ .../com/example/1.sqm | 9 ++++ .../com/example/2.sqm | 3 ++ .../com/example/Data.sq | 8 +++ .../output/com/example/DataQueries.kt | 51 +++++++++++++++++++ .../output/com/example/TestCompound.kt | 9 ++++ .../output/com/example/TestSingle.kt | 9 ++++ 7 files changed, 93 insertions(+) create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/1.sqm create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/2.sqm create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/Data.sq create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/DataQueries.kt create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestCompound.kt create mode 100644 sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestSingle.kt diff --git a/sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/migrations/MigrationQueryTest.kt b/sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/migrations/MigrationQueryTest.kt index cf36955ed70..663e7f2ac4e 100644 --- a/sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/migrations/MigrationQueryTest.kt +++ b/sqldelight-compiler/src/test/kotlin/app/cash/sqldelight/core/migrations/MigrationQueryTest.kt @@ -29,6 +29,10 @@ class MigrationQueryTest { checkFixtureCompiles("alter-table-alter-column", PostgreSqlDialect()) } + @Test fun `alter table add constraint`() { + checkFixtureCompiles("alter-table-add-constraint", PostgreSqlDialect()) + } + @Test fun `varying query migration packages`() { checkFixtureCompiles("varying-query-migration-packages", PostgreSqlDialect()) } diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/1.sqm b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/1.sqm new file mode 100644 index 00000000000..d1f3f412da4 --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/1.sqm @@ -0,0 +1,9 @@ +CREATE TABLE TestSingle( + first INTEGER, + second TEXT +); + +CREATE TABLE TestCompound ( + first INTEGER, + second TEXT +); diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/2.sqm b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/2.sqm new file mode 100644 index 00000000000..1618ef8e835 --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/2.sqm @@ -0,0 +1,3 @@ +ALTER TABLE TestSingle ADD PRIMARY KEY (first); +ALTER TABLE TestCompound ADD CONSTRAINT pk_first_second PRIMARY KEY (first, second); + diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/Data.sq b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/Data.sq new file mode 100644 index 00000000000..6bc3f66fcb5 --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/com/example/Data.sq @@ -0,0 +1,8 @@ +selectSingle: +SELECT * +FROM TestSingle; + +selectCompound: +SELECT * +FROM TestCompound; + diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/DataQueries.kt b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/DataQueries.kt new file mode 100644 index 00000000000..2efd52acdfb --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/DataQueries.kt @@ -0,0 +1,51 @@ +package com.example + +import app.cash.sqldelight.Query +import app.cash.sqldelight.TransacterImpl +import app.cash.sqldelight.db.SqlDriver +import app.cash.sqldelight.driver.jdbc.JdbcCursor +import kotlin.Any +import kotlin.Int +import kotlin.String + +public class DataQueries( + driver: SqlDriver, +) : TransacterImpl(driver) { + public fun selectSingle(mapper: (first: Int, second: String?) -> T): Query = + Query(-79_317_191, arrayOf("TestSingle"), driver, "Data.sq", "selectSingle", """ + |SELECT * + |FROM TestSingle + """.trimMargin()) { cursor -> + check(cursor is JdbcCursor) + mapper( + cursor.getInt(0)!!, + cursor.getString(1) + ) + } + + public fun selectSingle(): Query = selectSingle { first, second -> + TestSingle( + first, + second + ) + } + + public fun selectCompound(mapper: (first: Int, second: String) -> T): Query = + Query(-19_725_220, arrayOf("TestCompound"), driver, "Data.sq", "selectCompound", """ + |SELECT * + |FROM TestCompound + """.trimMargin()) { cursor -> + check(cursor is JdbcCursor) + mapper( + cursor.getInt(0)!!, + cursor.getString(1)!! + ) + } + + public fun selectCompound(): Query = selectCompound { first, second -> + TestCompound( + first, + second + ) + } +} diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestCompound.kt b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestCompound.kt new file mode 100644 index 00000000000..01f9f7dea18 --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestCompound.kt @@ -0,0 +1,9 @@ +package com.example + +import kotlin.Int +import kotlin.String + +public data class TestCompound( + public val first: Int, + public val second: String, +) diff --git a/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestSingle.kt b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestSingle.kt new file mode 100644 index 00000000000..504a227ec72 --- /dev/null +++ b/sqldelight-compiler/src/test/migration-interface-fixtures/alter-table-add-constraint/output/com/example/TestSingle.kt @@ -0,0 +1,9 @@ +package com.example + +import kotlin.Int +import kotlin.String + +public data class TestSingle( + public val first: Int, + public val second: String?, +)