Skip to content

Commit 73be752

Browse files
committed
fix: accept identity RESTART values without WITH
Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent 60c8dc2 commit 73be752

4 files changed

Lines changed: 98 additions & 1 deletion

File tree

‎src/main/java/net/sf/jsqlparser/statement/alter/IdentityAlteration.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public void setParameters(List<Sequence.Parameter> parameters) {
6161
this.parameters = parameters == null ? null : new ArrayList<>(parameters);
6262
}
6363

64+
/** Returns the restart value, or null for a bare RESTART using the sequence start value. */
6465
public Long getRestartWith() {
6566
return restartWith;
6667
}
@@ -69,6 +70,11 @@ public void setRestartWith(Long restartWith) {
6970
this.restartWith = restartWith;
7071
}
7172

73+
public IdentityAlteration withRestartWith(Long restartWith) {
74+
setRestartWith(restartWith);
75+
return this;
76+
}
77+
7278
public boolean isIfExists() {
7379
return ifExists;
7480
}

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16306,7 +16306,7 @@ IdentityAlteration ColumnIdentityAlteration():
1630616306
}
1630716307
)
1630816308
|
16309-
<K_RESTART> [ LOOKAHEAD(2) <K_WITH> restart=SequenceParameterValue() ] {
16309+
<K_RESTART> [ LOOKAHEAD(1) [ <K_WITH> ] restart=SequenceParameterValue() ] {
1631016310
alteration = new IdentityAlteration(IdentityAlteration.Kind.RESTART);
1631116311
alteration.setRestartWith(restart);
1631216312
}

‎src/site/sphinx/usage.rst‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,13 @@ Table constraints expose ``Index.getNullsDistinct()``, ``getIncludeColumns()``,
293293
294294
Identity alterations are available as ``ColumnDataType.getIdentityAlterations()``. Sequence ownership is shared by ``CreateSequence`` and ``AlterSequence`` through ``Sequence.getOwnership()``: ``null`` means omitted, ``isNone()`` means explicit ``OWNED BY NONE``, and ``getColumn()`` identifies an owner. ``TablesNamesFinder`` includes ``LIKE`` sources and sequence owners without treating sequence or type names as tables. See `ALTER TABLE <https://www.postgresql.org/docs/18/sql-altertable.html>`_ and `ALTER SEQUENCE <https://www.postgresql.org/docs/18/sql-altersequence.html>`_.
295295

296+
For identity columns, ``RESTART 20`` and ``RESTART WITH 20`` produce the same
297+
``IdentityAlteration`` with kind ``RESTART`` and ``getRestartWith() == 20L``.
298+
The renderer consistently uses ``RESTART WITH 20``. A null restart value means
299+
bare ``RESTART``, which uses the sequence's configured start value. Call
300+
``setRestartWith`` to edit a parsed action or construct one with
301+
``new IdentityAlteration(Kind.RESTART).withRestartWith(20L)``.
302+
296303

297304
Structured column attributes
298305
============================
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2026 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement.alter;
11+
12+
import static org.junit.jupiter.api.Assertions.*;
13+
import java.util.List;
14+
import net.sf.jsqlparser.JSQLParserException;
15+
import net.sf.jsqlparser.parser.AbstractJSqlParser.Dialect;
16+
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
17+
import net.sf.jsqlparser.util.deparser.StatementDeParser;
18+
import org.junit.jupiter.api.Test;
19+
import org.junit.jupiter.params.ParameterizedTest;
20+
import org.junit.jupiter.params.provider.ValueSource;
21+
22+
class IdentityRestartValueTest {
23+
@ParameterizedTest
24+
@ValueSource(strings = {"20", "WITH 20", "+20", "-20", "WITH -20", "9223372036854775807"})
25+
void representsOptionalWithUsingTheSameValue(String value) throws JSQLParserException {
26+
for (Dialect dialect : new Dialect[] {null, Dialect.POSTGRESQL}) {
27+
Alter alter = parse("ALTER TABLE t ALTER COLUMN id RESTART " + value, dialect);
28+
IdentityAlteration restart = identity(alter).get(0);
29+
assertEquals(IdentityAlteration.Kind.RESTART, restart.getKind());
30+
assertEquals(Long.valueOf(value.replace("WITH ", "")), restart.getRestartWith());
31+
roundTrip(alter, dialect);
32+
}
33+
}
34+
35+
@Test
36+
void editsAndConstructsRestartAndPreservesBareRestart() throws JSQLParserException {
37+
Alter alter = parse("ALTER TABLE t ALTER COLUMN id RESTART", Dialect.POSTGRESQL);
38+
assertNull(identity(alter).get(0).getRestartWith());
39+
identity(alter).get(0).setRestartWith(20L);
40+
assertEquals("ALTER TABLE t ALTER COLUMN id RESTART WITH 20", alter.toString());
41+
roundTrip(alter, Dialect.POSTGRESQL);
42+
alter.getAlterExpressions().get(0).getColDataTypeList().get(0).setIdentityAlterations(
43+
List.of(new IdentityAlteration(IdentityAlteration.Kind.RESTART)
44+
.withRestartWith(40L)));
45+
assertEquals("ALTER TABLE t ALTER COLUMN id RESTART WITH 40", alter.toString());
46+
roundTrip(alter, Dialect.POSTGRESQL);
47+
identity(alter).get(0).setRestartWith(null);
48+
assertEquals("ALTER TABLE t ALTER COLUMN id RESTART", alter.toString());
49+
}
50+
51+
@Test
52+
void respectsIdentityAndAlterActionBoundaries() throws JSQLParserException {
53+
Alter alter = parse(
54+
"ALTER TABLE t ALTER COLUMN id SET CACHE 10 RESTART 20 SET NO CYCLE, ADD COLUMN extra INT",
55+
Dialect.POSTGRESQL);
56+
assertEquals(3, identity(alter).size());
57+
assertEquals(2, alter.getAlterExpressions().size());
58+
roundTrip(alter, Dialect.POSTGRESQL);
59+
roundTrip(parse("ALTER TABLE t ALTER COLUMN id RESTART SET CACHE 10", Dialect.POSTGRESQL),
60+
Dialect.POSTGRESQL);
61+
assertThrows(JSQLParserException.class,
62+
() -> parse("ALTER TABLE t ALTER COLUMN id RESTART WITH", Dialect.POSTGRESQL));
63+
}
64+
65+
private static List<IdentityAlteration> identity(Alter alter) {
66+
return alter.getAlterExpressions().get(0).getColDataTypeList().get(0)
67+
.getIdentityAlterations();
68+
}
69+
70+
private static Alter parse(String sql, Dialect dialect) throws JSQLParserException {
71+
return (Alter) CCJSqlParserUtil.parse(sql, p -> {
72+
if (dialect != null) {
73+
p.withDialect(dialect);
74+
}
75+
});
76+
}
77+
78+
private static void roundTrip(Alter alter, Dialect dialect) throws JSQLParserException {
79+
StringBuilder sql = new StringBuilder();
80+
alter.accept(new StatementDeParser(sql), null);
81+
assertEquals(alter.toString(), sql.toString());
82+
assertEquals(sql.toString(), parse(sql.toString(), dialect).toString());
83+
}
84+
}

0 commit comments

Comments
 (0)