Skip to content

Commit 6836c5b

Browse files
committed
Merge upstream master and resolve CREATE TABLE grammar conflict
Signed-off-by: minleejae <mmj9808@gmail.com>
2 parents 72babad + 17be330 commit 6836c5b

9 files changed

Lines changed: 573 additions & 30 deletions

File tree

‎src/main/java/net/sf/jsqlparser/schema/Sequence.java‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ public Sequence addParameters(Collection<? extends Parameter> parameters) {
187187
* The available parameters to a sequence
188188
*/
189189
public enum ParameterType {
190-
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;
190+
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;
191191

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

202202
private final ParameterType option;
203203
private Long value;
204+
private Sequence sequenceName;
204205

205206
public Parameter(ParameterType option) {
206207
this.option = option;
@@ -214,6 +215,20 @@ public ParameterType getOption() {
214215
return option;
215216
}
216217

218+
/** The sequence named by an identity declaration's SEQUENCE NAME option. */
219+
public Sequence getSequenceName() {
220+
return sequenceName;
221+
}
222+
223+
public void setSequenceName(Sequence sequenceName) {
224+
this.sequenceName = sequenceName;
225+
}
226+
227+
public Parameter withSequenceName(Sequence sequenceName) {
228+
setSequenceName(sequenceName);
229+
return this;
230+
}
231+
217232
@Override
218233
public String toString() {
219234
return formatParameter();
@@ -225,6 +240,8 @@ public void setValue(Long value) {
225240

226241
public String formatParameter() {
227242
switch (option) {
243+
case SEQUENCE_NAME:
244+
return "SEQUENCE NAME " + sequenceName.getFullyQualifiedName();
228245
case INCREMENT_BY:
229246
return prefix("INCREMENT BY");
230247
case INCREMENT:

‎src/main/java/net/sf/jsqlparser/statement/ReferentialAction.java‎

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@
1111

1212
import java.io.Serializable;
1313
import java.util.Locale;
14+
import java.util.List;
15+
import java.util.Objects;
16+
import net.sf.jsqlparser.statement.select.PlainSelect;
1417

1518
public class ReferentialAction implements Serializable {
1619

1720
private Type type;
1821
private Action action;
22+
private List<String> columnNames;
1923

2024
public ReferentialAction() {
2125
// default constructor
@@ -52,6 +56,20 @@ public ReferentialAction withAction(Action action) {
5256
return this;
5357
}
5458

59+
/** Columns affected by PostgreSQL ON DELETE SET NULL or SET DEFAULT; null means all columns. */
60+
public List<String> getColumnNames() {
61+
return columnNames;
62+
}
63+
64+
public void setColumnNames(List<String> columnNames) {
65+
this.columnNames = columnNames;
66+
}
67+
68+
public ReferentialAction withColumnNames(List<String> columnNames) {
69+
setColumnNames(columnNames);
70+
return this;
71+
}
72+
5573
@Override
5674
public int hashCode() {
5775
final int prime = 31;
@@ -64,7 +82,9 @@ public int hashCode() {
6482
@Override
6583
public String toString() {
6684
return " ON " + getType().name() + " " +
67-
getAction().getAction();
85+
getAction().getAction()
86+
+ (columnNames == null ? ""
87+
: " " + PlainSelect.getStringList(columnNames, true, true));
6888
}
6989

7090
@Override
@@ -79,12 +99,8 @@ public boolean equals(Object obj) {
7999
return false;
80100
}
81101
ReferentialAction other = (ReferentialAction) obj;
82-
// if (action != other.action) {
83-
// return false;
84-
// }
85-
// if (type != other.type) {
86-
// return false;
87-
return action == other.action && type == other.type;
102+
return action == other.action && type == other.type
103+
&& Objects.equals(columnNames, other.columnNames);
88104
}
89105

90106
public enum Type {

‎src/main/java/net/sf/jsqlparser/statement/create/table/CreateTable.java‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@ public class CreateTable implements Statement {
3535
private List<Index> indexes;
3636
private List<TableElement> tableElements;
3737
private Select select;
38+
private DuplicateHandling duplicateHandling;
3839
private Table likeTable;
3940
private Table cloneTable;
4041
private List<Table> inherits;
4142
private ColDataType ofType;
4243
private boolean selectParenthesis;
4344
private boolean useAsKeyword = true;
45+
private Boolean withData;
4446
private boolean ifNotExists = false;
4547
private boolean orReplace = false;
4648
private TablePartitioning partitioning;
@@ -51,6 +53,19 @@ public class CreateTable implements Statement {
5153

5254
private SpannerInterleaveIn interleaveIn = null;
5355

56+
public enum DuplicateHandling {
57+
IGNORE, REPLACE
58+
}
59+
60+
/** MySQL's duplicate-key handling when creating a table from a query; null if omitted. */
61+
public DuplicateHandling getDuplicateHandling() {
62+
return duplicateHandling;
63+
}
64+
65+
public void setDuplicateHandling(DuplicateHandling duplicateHandling) {
66+
this.duplicateHandling = duplicateHandling;
67+
}
68+
5469
@Override
5570
public <T, S> T accept(StatementVisitor<T> statementVisitor, S context) {
5671
return statementVisitor.visit(this, context);
@@ -205,9 +220,21 @@ public void setUseAsKeyword(boolean useAsKeyword) {
205220
this.useAsKeyword = useAsKeyword;
206221
}
207222

223+
/** Returns null for omission, true for WITH DATA, and false for WITH NO DATA. */
224+
public Boolean getWithData() {
225+
return withData;
226+
}
227+
228+
public void setWithData(Boolean withData) {
229+
this.withData = withData;
230+
}
231+
208232
public StringBuilder appendSelectTo(StringBuilder builder,
209233
java.util.function.Consumer<Select> selectRenderer) {
210234
if (select != null) {
235+
if (duplicateHandling != null) {
236+
builder.append(' ').append(duplicateHandling);
237+
}
211238
builder.append(useAsKeyword ? " AS " : " ");
212239
if (selectParenthesis) {
213240
builder.append("(");
@@ -216,6 +243,9 @@ public StringBuilder appendSelectTo(StringBuilder builder,
216243
if (selectParenthesis) {
217244
builder.append(")");
218245
}
246+
if (withData != null) {
247+
builder.append(withData ? " WITH DATA" : " WITH NO DATA");
248+
}
219249
}
220250
return builder;
221251
}

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

Lines changed: 63 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,11 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
14401440
return isKeywordAhead("MATCH_RECOGNIZE") && getToken(2).kind == OPENING_BRACKET;
14411441
}
14421442

1443+
private boolean isCreateTableQueryPrefix() {
1444+
int kind = getToken(1).kind;
1445+
return kind == K_AS || kind == K_TABLE || kind == K_IGNORE || kind == K_REPLACE;
1446+
}
1447+
14431448
private boolean isRowPatternPrimaryAhead() {
14441449
Token next = getToken(1);
14451450
return next.kind == OPENING_BRACKET || next.kind == OP_CARET
@@ -14143,8 +14148,7 @@ ColumnOption ColumnDefinitionOption(): {
1414314148
LOOKAHEAD(<K_PRIMARY> <K_KEY>) <K_PRIMARY> <K_KEY>
1414414149
{ option = ColumnOption.constraint(new NamedConstraint().withType("PRIMARY KEY")); }
1414514150
|
14146-
LOOKAHEAD([ <K_CONSTRAINT> RelObjectName() ] <K_CHECK>,
14147-
{ Dialect.POSTGRESQL.name().equals(getAsString(Feature.dialect)) })
14151+
LOOKAHEAD([ <K_CONSTRAINT> RelObjectName() ] <K_CHECK>)
1414814152
[ <K_CONSTRAINT> constraintName=RelObjectName() ]
1414914153
constraint=CheckConstraintSpec(constraintName)
1415014154
{ option = ColumnOption.constraint(constraint); }
@@ -14217,7 +14221,9 @@ IdentityDefinition IdentityDefinition():
1421714221
Token token;
1421814222
IdentityDefinition.GenerationMode mode;
1421914223
IdentityDefinition identity;
14220-
List<Sequence.Parameter> parameters;
14224+
List<Sequence.Parameter> parameters = new ArrayList<Sequence.Parameter>();
14225+
Sequence.Parameter parameter;
14226+
Sequence sequenceName;
1422114227
}
1422214228
{
1422314229
token=<S_IDENTIFIER> {
@@ -14226,8 +14232,18 @@ IdentityDefinition IdentityDefinition():
1422614232
( <K_ALWAYS> { mode = IdentityDefinition.GenerationMode.ALWAYS; }
1422714233
| <K_BY> <K_DEFAULT> { mode = IdentityDefinition.GenerationMode.BY_DEFAULT; } )
1422814234
<K_AS> <K_IDENTITY> { identity = new IdentityDefinition(mode); }
14229-
[ LOOKAHEAD(2) "(" parameters=SequenceParameters() ")" {
14230-
requireDdlSyntax(!parameters.isEmpty(), "Expected an identity sequence parameter");
14235+
[ LOOKAHEAD(1) "("
14236+
(
14237+
(
14238+
LOOKAHEAD(<K_SEQUENCE> <K_NAME>)
14239+
<K_SEQUENCE> <K_NAME> sequenceName=Sequence()
14240+
{ parameter = new Sequence.Parameter(Sequence.ParameterType.SEQUENCE_NAME)
14241+
.withSequenceName(sequenceName); }
14242+
| parameter=SequenceParameter()
14243+
)
14244+
{ parameters.add(parameter); }
14245+
)+
14246+
")" {
1423114247
identity.setParameters(parameters);
1423214248
} ]
1423314249
{ return identity; }
@@ -14970,6 +14986,7 @@ CreateTable CreateTable(boolean isUsingOrReplace):
1497014986
ColDataType ofType = null;
1497114987
Table parent;
1497214988
List<Table> parents = new ArrayList<Table>();
14989+
boolean withData;
1497314990
}
1497414991
{
1497514992
{ createTable.setOrReplace(isUsingOrReplace);}
@@ -15026,9 +15043,14 @@ CreateTable CreateTable(boolean isUsingOrReplace):
1502615043
[ rowMovement = RowMovement() { createTable.setRowMovement(rowMovement); }]
1502715044
[ LOOKAHEAD(2)
1502815045
{ createTable.setUseAsKeyword(false); }
15046+
[ ( tk=<K_IGNORE> | tk=<K_REPLACE> )
15047+
{ createTable.setDuplicateHandling(CreateTable.DuplicateHandling.valueOf(
15048+
tk.image.toUpperCase(Locale.ROOT))); } ]
1502915049
[ <K_AS> { createTable.setUseAsKeyword(true); } ]
1503015050
( LOOKAHEAD(<K_TABLE>) select=TableStatement() | select=Select() )
1503115051
{ createTable.setSelect(select, false); }
15052+
[ LOOKAHEAD(2) <K_WITH> withData=DataPopulation()
15053+
{ createTable.setWithData(withData); } ]
1503215054
]
1503315055
[
1503415056
<K_LIKE> ( LOOKAHEAD("(" Table() ")") "(" likeTable=Table() { createTable.setLikeTable(likeTable, true); } ")"
@@ -15087,10 +15109,10 @@ ColumnDefinition CreateTableColumnDefinition(boolean typed):
1508715109
void CreateTableOptions(List<TableOption> options):
1508815110
{ TableOption option; }
1508915111
{
15090-
[ LOOKAHEAD(2, { getToken(1).kind != K_AS && getToken(1).kind != K_TABLE
15112+
[ LOOKAHEAD(2, { !isCreateTableQueryPrefix()
1509115113
&& !(getToken(1).kind == K_PARTITION && getToken(2).kind == K_BY) })
1509215114
option=CreateTableOption() { options.add(option); }
15093-
( LOOKAHEAD(2, { getToken(1).kind != K_AS && getToken(1).kind != K_TABLE
15115+
( LOOKAHEAD(2, { !isCreateTableQueryPrefix()
1509415116
&& !(getToken(1).kind == K_PARTITION && getToken(2).kind == K_BY)
1509515117
&& !(getToken(1).kind == K_COMMA
1509615118
&& "INTERLEAVE".equalsIgnoreCase(getToken(2).image)) })
@@ -15619,7 +15641,7 @@ CreateView CreateView(boolean isUsingOrReplace):
1561915641
List<Index.Option> storageParameters = null;
1562015642
List<ViewOption> viewOptions = new ArrayList<ViewOption>();
1562115643
ViewOption viewOption = null;
15622-
boolean withData = true;
15644+
boolean withData;
1562315645
}
1562415646
{
1562515647
{ createView.setOrReplace(isUsingOrReplace);}
@@ -15674,7 +15696,7 @@ CreateView CreateView(boolean isUsingOrReplace):
1567415696
}
1567515697
}
1567615698
|
15677-
[ <K_NO> { withData = false; } ] <K_DATA> { createView.setWithData(withData); }
15699+
withData=DataPopulation() { createView.setWithData(withData); }
1567815700
)
1567915701
]
1568015702
{ createView.validateOptions(); return createView; }
@@ -15692,6 +15714,14 @@ ViewOption PostgreSqlViewOption():
1569215714
{ return new ViewOption(name, value, useEquals); }
1569315715
}
1569415716

15717+
/** Shared WITH [NO] DATA tail for table and materialized-view query sources. */
15718+
boolean DataPopulation():
15719+
{ boolean withData = true; }
15720+
{
15721+
[ <K_NO> { withData = false; } ] <K_DATA>
15722+
{ return withData; }
15723+
}
15724+
1569515725
List<String> CreateViewTailComment():
1569615726
{
1569715727
Token tk = null;
@@ -15739,21 +15769,32 @@ ReferentialAction.Action Action():
1573915769
* Shared between CREATE TABLE FK and ALTER TABLE FK definitions.
1574015770
*/
1574115771
void ReferentialActions(ForeignKeyReference reference):
15772+
{}
1574215773
{
15743-
Token tk;
15744-
ReferentialAction.Action action = null;
15774+
[ LOOKAHEAD(2) ReferentialActionSpec(reference) ]
15775+
[ LOOKAHEAD(2) ReferentialActionSpec(reference) ]
1574515776
}
15777+
15778+
void ReferentialActionSpec(ForeignKeyReference reference):
1574615779
{
15747-
[ LOOKAHEAD(2) (
15748-
<K_ON>
15749-
( tk=<K_DELETE> | tk=<K_UPDATE> ) action = Action()
15750-
{ reference.setReferentialAction(ReferentialAction.Type.from(tk.image), action); }
15751-
)]
15752-
[ LOOKAHEAD(2) (
15753-
<K_ON>
15754-
( tk=<K_DELETE> | tk=<K_UPDATE> ) action = Action()
15755-
{ reference.setReferentialAction(ReferentialAction.Type.from(tk.image), action); }
15756-
)]
15780+
Token token;
15781+
ReferentialAction.Type type;
15782+
ReferentialAction.Action action;
15783+
List<String> columnNames = null;
15784+
}
15785+
{
15786+
<K_ON> ( token=<K_DELETE> | token=<K_UPDATE> )
15787+
{ type = ReferentialAction.Type.from(token.image); }
15788+
action=Action()
15789+
[ LOOKAHEAD({ type == ReferentialAction.Type.DELETE
15790+
&& (action == ReferentialAction.Action.SET_NULL
15791+
|| action == ReferentialAction.Action.SET_DEFAULT)
15792+
&& "(".equals(getToken(1).image) })
15793+
columnNames=ColumnsNamesList() ]
15794+
{
15795+
reference.setReferentialAction(type, action);
15796+
reference.getReferentialAction(type).setColumnNames(columnNames);
15797+
}
1575715798
}
1575815799

1575915800
ForeignKeyReference ForeignKeyReferenceSpec():
@@ -16614,7 +16655,7 @@ TablePartitioning CreateTablePartitioning():
1661416655
]
1661516656
[ LOOKAHEAD(2) partitionDefinitions=PartitionDefinitions()
1661616657
{ partitioning.setPartitionDefinitions(partitionDefinitions); } ]
16617-
( LOOKAHEAD(2, { getToken(1).kind != K_AS })
16658+
( LOOKAHEAD(2, { !isCreateTableQueryPrefix() })
1661816659
parameter=CreateParameter() { partitionOptions.addAll(parameter); } )*
1661916660
{
1662016661
if (!partitionOptions.isEmpty()) {

0 commit comments

Comments
 (0)