Skip to content

Commit

Permalink
Fix 4501 PostgreSql sequence (#4528)
Browse files Browse the repository at this point in the history
* create sequence grammer

* test create sequence grammer

* add mixin to validate owner table

* add fixture tests with variants

* fix spotless

* add currval, nextval, lastval and setval

* add integration tests

* add function setval

add test

* Update PostgreSqlTest.kt

fix spotless whitespace

---------

Co-authored-by: griffio <griffio@users.noreply.github.com>
  • Loading branch information
griffio and griffio authored Nov 30, 2023
1 parent 40ddbe2 commit 136849f
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ class PostgreSqlTypeResolver(private val parentResolver: TypeResolver) : TypeRes
-> IntermediateType(TEXT)
"json_array_length", "jsonb_array_length" -> IntermediateType(INTEGER)
"jsonb_path_exists", "jsonb_path_match", "jsonb_path_exists_tz", "jsonb_path_match_tz" -> IntermediateType(BOOLEAN)
"currval", "lastval", "nextval", "setval" -> IntermediateType(BIG_INT)
"generate_series" -> encapsulatingType(exprList, INTEGER, BIG_INT, REAL, TIMESTAMP_TIMEZONE, TIMESTAMP)
else -> null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"static com.alecstrong.sql.psi.core.psi.SqlTypes.LIMIT"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.LP"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.MINUS"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.NO"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.NOT"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.NOTHING"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.NULL"
Expand All @@ -69,6 +70,8 @@
"static com.alecstrong.sql.psi.core.psi.SqlTypes.SELECT"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.SET"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.STRING"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.TEMP"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.TEMPORARY"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.TO"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.TRUE"
"static com.alecstrong.sql.psi.core.psi.SqlTypes.UNIQUE"
Expand Down Expand Up @@ -366,7 +369,7 @@ json_expression ::= {column_name} ( jsona_binary_operator | jsonb_binary_operato
jsona_binary_operator ::= '->' | '->>' | '#>'
jsonb_binary_operator ::= '@>' | '<@' | '?|' | '?&' | '?' | '#-'

extension_stmt ::= copy_stdin {
extension_stmt ::= create_sequence_stmt | copy_stdin {
extends = "com.alecstrong.sql.psi.core.psi.impl.SqlExtensionStmtImpl"
implements = "com.alecstrong.sql.psi.core.psi.SqlExtensionStmt"
override = true
Expand All @@ -376,6 +379,21 @@ copy_stdin ::= 'COPY' [ {database_name} DOT ] {table_name} [ AS {table_alias} ]
mixin = "app.cash.sqldelight.dialects.postgresql.grammar.mixins.CopyMixin"
}

sequence_name ::= id | string

sequence_data_type ::= ( small_int_data_type
| int_data_type
| big_int_data_type )

create_sequence_stmt ::= CREATE [ (TEMPORARY | TEMP) | 'UNLOGGED' ] 'SEQUENCE' [ IF NOT EXISTS ] sequence_name
[ AS sequence_data_type ]
[ 'INCREMENT' [ BY ] {signed_number} ]
[ 'MINVALUE' {signed_number} | NO 'MINVALUE' ] [ 'MAXVALUE' {signed_number} | NO 'MAXVALUE' ]
[ 'START' [ WITH ] {signed_number} ] [ 'CACHE' {signed_number} ] [ [ NO ] 'CYCLE' ]
[ 'OWNED' BY ( {table_name} DOT {column_name} ) | 'NONE' ] {
mixin = "app.cash.sqldelight.dialects.postgresql.grammar.mixins.CreateSequenceMixin"
}

copy_option ::= copy_option_format | copy_option_freeze | copy_option_delimiter | copy_option_null | copy_option_header | copy_option_quote | copy_option_escape | copy_option_force_not_null | copy_option_force_null | copy_option_encoding
copy_option_format ::= 'FORMAT' ('TEXT' | 'CSV' | 'BINARY')
copy_option_freeze ::= 'FREEZE' [ (boolean_literal) ]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package app.cash.sqldelight.dialects.postgresql.grammar.mixins

import app.cash.sqldelight.dialects.postgresql.grammar.psi.PostgreSqlCreateSequenceStmt
import com.alecstrong.sql.psi.core.psi.QueryElement
import com.alecstrong.sql.psi.core.psi.SqlCompositeElementImpl
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement

internal abstract class CreateSequenceMixin(node: ASTNode) :
SqlCompositeElementImpl(node),
PostgreSqlCreateSequenceStmt {
// Query any owner tableName element to allow the columnName to be resolved
override fun queryAvailable(child: PsiElement): Collection<QueryElement.QueryResult> {
return tablesAvailable(child).map { it.query }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
CREATE TABLE abc (
id INTEGER PRIMARY KEY
);

CREATE SEQUENCE integers_01;

CREATE SEQUENCE integers_02 START 31
OWNED BY abc.id;

CREATE SEQUENCE integers_03 AS INTEGER
INCREMENT 10
MINVALUE 100
MAXVALUE 250000
START 101
CACHE 1
NO CYCLE;

CREATE TEMPORARY SEQUENCE IF NOT EXISTS integers_04 AS SMALLINT
INCREMENT BY 2
NO MINVALUE
NO MAXVALUE
START WITH 3
CYCLE;

SELECT nextval('integers_01');

SELECT nextval('integers_02');

SELECT nextval('integers_03');

SELECT nextval('integers_04');
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CREATE SEQUENCE serial START 200;

CREATE TABLE sigma (
id INTEGER PRIMARY KEY
);

insertNextVal:
INSERT INTO sigma VALUES (nextval('serial'))
RETURNING id;

selectNextVal:
SELECT nextval('serial');

selectCurrentVal:
SELECT currval('serial');

selectLastVal:
SELECT lastval();

selectSetVal:
SELECT setval('serial', 200, TRUE);
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,19 @@ class PostgreSqlTest {
}
}

@Test fun sequenceFunctions() {
val nextVal = database.sequencesQueries.insertNextVal().executeAsOne()
val currVal = database.sequencesQueries.selectCurrentVal().executeAsOne()
assertThat(nextVal).isEqualTo(currVal)

val selectNextVal = database.sequencesQueries.selectNextVal().executeAsOne()
val lastVal = database.sequencesQueries.selectLastVal().executeAsOne()
assertThat(selectNextVal).isEqualTo(lastVal)

val selectSetVal = database.sequencesQueries.selectSetVal().executeAsOne()
assertThat(selectSetVal).isEqualTo(nextVal)
}

@Test
fun testGenerateSeries() {
val start = OffsetDateTime.of(2023, 9, 1, 0, 0, 0, 0, ZoneOffset.ofHours(0))
Expand Down

0 comments on commit 136849f

Please sign in to comment.