Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion src/main/java/net/sf/jsqlparser/schema/Sequence.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ public Sequence addParameters(Collection<? extends Parameter> parameters) {
* The available parameters to a sequence
*/
public enum ParameterType {
INCREMENT_BY, INCREMENT, START_WITH, START, RESTART_WITH, MAXVALUE, NOMAXVALUE, MINVALUE, NOMINVALUE, CYCLE, NOCYCLE, CACHE, NOCACHE, ORDER, NOORDER, KEEP, NOKEEP, SESSION, GLOBAL, NO_MINVALUE, NO_MAXVALUE, NO_CYCLE;
INCREMENT_BY, INCREMENT, START_WITH, START, RESTART_WITH, MAXVALUE, NOMAXVALUE, MINVALUE, NOMINVALUE, CYCLE, NOCYCLE, CACHE, NOCACHE, ORDER, NOORDER, KEEP, NOKEEP, SESSION, GLOBAL, NO_MINVALUE, NO_MAXVALUE, NO_CYCLE, SEQUENCE_NAME;

public static ParameterType from(String type) {
return Enum.valueOf(ParameterType.class, type.toUpperCase(Locale.ROOT));
Expand All @@ -201,6 +201,7 @@ public static class Parameter implements java.io.Serializable {

private final ParameterType option;
private Long value;
private Sequence sequenceName;

public Parameter(ParameterType option) {
this.option = option;
Expand All @@ -214,6 +215,20 @@ public ParameterType getOption() {
return option;
}

/** The sequence named by an identity declaration's SEQUENCE NAME option. */
public Sequence getSequenceName() {
return sequenceName;
}

public void setSequenceName(Sequence sequenceName) {
this.sequenceName = sequenceName;
}

public Parameter withSequenceName(Sequence sequenceName) {
setSequenceName(sequenceName);
return this;
}

@Override
public String toString() {
return formatParameter();
Expand All @@ -225,6 +240,8 @@ public void setValue(Long value) {

public String formatParameter() {
switch (option) {
case SEQUENCE_NAME:
return "SEQUENCE NAME " + sequenceName.getFullyQualifiedName();
case INCREMENT_BY:
return prefix("INCREMENT BY");
case INCREMENT:
Expand Down
18 changes: 15 additions & 3 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -14217,7 +14217,9 @@ IdentityDefinition IdentityDefinition():
Token token;
IdentityDefinition.GenerationMode mode;
IdentityDefinition identity;
List<Sequence.Parameter> parameters;
List<Sequence.Parameter> parameters = new ArrayList<Sequence.Parameter>();
Sequence.Parameter parameter;
Sequence sequenceName;
}
{
token=<S_IDENTIFIER> {
Expand All @@ -14226,8 +14228,18 @@ IdentityDefinition IdentityDefinition():
( <K_ALWAYS> { mode = IdentityDefinition.GenerationMode.ALWAYS; }
| <K_BY> <K_DEFAULT> { mode = IdentityDefinition.GenerationMode.BY_DEFAULT; } )
<K_AS> <K_IDENTITY> { identity = new IdentityDefinition(mode); }
[ LOOKAHEAD(2) "(" parameters=SequenceParameters() ")" {
requireDdlSyntax(!parameters.isEmpty(), "Expected an identity sequence parameter");
[ LOOKAHEAD(1) "("
(
(
LOOKAHEAD(<K_SEQUENCE> <K_NAME>)
<K_SEQUENCE> <K_NAME> sequenceName=Sequence()
{ parameter = new Sequence.Parameter(Sequence.ParameterType.SEQUENCE_NAME)
.withSequenceName(sequenceName); }
| parameter=SequenceParameter()
)
{ parameters.add(parameter); }
)+
")" {
identity.setParameters(parameters);
} ]
{ return identity; }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2026 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
package net.sf.jsqlparser.statement.create;

import static org.junit.jupiter.api.Assertions.*;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Sequence;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.alter.Alter;
import net.sf.jsqlparser.statement.create.table.CreateTable;
import net.sf.jsqlparser.statement.create.table.IdentityDefinition;
import net.sf.jsqlparser.util.deparser.StatementDeParser;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

class IdentitySequenceNameTest {
@ParameterizedTest
@ValueSource(strings = {"ids", "public.ids", "\"schema.name\".\"seq.name\""})
void sharesIdentityOptionsAcrossCreateAndAlter(String name) throws JSQLParserException {
String definition = "GENERATED BY DEFAULT AS IDENTITY (START 4 SEQUENCE NAME " + name
+ " CACHE 2 NO CYCLE)";
CreateTable create = (CreateTable) parse("CREATE TABLE t (id INT " + definition + ")");
IdentityDefinition identity = create.getColumnDefinitions().get(0).getColumnOptions().get(0)
.getIdentityDefinition();
Alter alter = (Alter) parse("ALTER TABLE t ALTER COLUMN id ADD " + definition);
IdentityDefinition altered = alter.getAlterExpressions().get(0).getColDataTypeList().get(0)
.getIdentityAlterations().get(0).getIdentityDefinition();
for (IdentityDefinition current : new IdentityDefinition[] {identity, altered}) {
assertEquals(4, current.getParameters().size());
Sequence.Parameter named = current.getParameters().get(1);
assertEquals(Sequence.ParameterType.SEQUENCE_NAME, named.getOption());
assertEquals(name, named.getSequenceName().getFullyQualifiedName());
assertNull(named.getValue());
named.getSequenceName().setName("renamed");
}
assertTrue(create.toString().contains("renamed"));
assertTrue(alter.toString().contains("renamed"));
roundTrip(create);
roundTrip(alter);
}

@Test
void preservesNameOnlyAndDoesNotExtendStandaloneSequenceOptions() throws JSQLParserException {
String sql = "CREATE TABLE t (id INT GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME ids))";
assertEquals(sql, parse(sql).toString());
roundTrip(parse(sql));
for (String invalid : new String[] {
"CREATE TABLE t (id INT GENERATED ALWAYS AS IDENTITY (SEQUENCE NAME))",
"CREATE TABLE t (id INT GENERATED ALWAYS AS IDENTITY ())",
"CREATE SEQUENCE ids SEQUENCE NAME other_ids",
"ALTER TABLE t ALTER COLUMN id SET SEQUENCE NAME other_ids"}) {
assertThrows(JSQLParserException.class, () -> parse(invalid), invalid);
}
}

private static Statement parse(String sql) throws JSQLParserException {
return CCJSqlParserUtil.parse(sql, p -> p.withDialect(Dialect.POSTGRESQL));
}

private static void roundTrip(Statement statement) throws JSQLParserException {
StringBuilder out = new StringBuilder();
statement.accept(new StatementDeParser(out));
assertEquals(statement.toString(), out.toString());
assertEquals(out.toString(), parse(out.toString()).toString());
}
}
Loading