Skip to content

Commit c77bb0f

Browse files
authored
fix(parser): model PostgreSQL declarative partitions (#2535)
* fix(parser): model PostgreSQL declarative partitions * fix(ci): keep partition tests compatible with Java 11
1 parent 6413a84 commit c77bb0f

10 files changed

Lines changed: 465 additions & 8 deletions

File tree

src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,8 @@ protected boolean isPartitionOperation() {
830830
switch (operation) {
831831
case DISCARD_PARTITION:
832832
case IMPORT_PARTITION:
833+
case ATTACH_PARTITION:
834+
case DETACH_PARTITION:
833835
case TRUNCATE_PARTITION:
834836
case COALESCE_PARTITION:
835837
case REORGANIZE_PARTITION:

src/main/java/net/sf/jsqlparser/statement/alter/AlterExpressionPartition.java

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,75 @@
99
*/
1010
package net.sf.jsqlparser.statement.alter;
1111

12+
import net.sf.jsqlparser.schema.Table;
13+
import net.sf.jsqlparser.statement.create.table.PartitionBound;
14+
1215
/**
1316
* Internal subclass for partition maintenance operations within ALTER TABLE. Handles TRUNCATE,
1417
* COALESCE, REORGANIZE, EXCHANGE, ANALYZE, CHECK, OPTIMIZE, REBUILD, REPAIR PARTITION, PARTITION
1518
* BY, and REMOVE PARTITIONING.
1619
*/
1720
public class AlterExpressionPartition extends AlterExpression {
1821

22+
public enum DetachMode {
23+
CONCURRENTLY, FINALIZE
24+
}
25+
26+
private Table partitionTable;
27+
private PartitionBound partitionBound;
28+
private DetachMode detachMode;
29+
30+
public Table getPartitionTable() {
31+
return partitionTable;
32+
}
33+
34+
public void setPartitionTable(Table partitionTable) {
35+
this.partitionTable = partitionTable;
36+
}
37+
38+
public PartitionBound getPartitionBound() {
39+
return partitionBound;
40+
}
41+
42+
public void setPartitionBound(PartitionBound partitionBound) {
43+
this.partitionBound = partitionBound;
44+
}
45+
46+
public DetachMode getDetachMode() {
47+
return detachMode;
48+
}
49+
50+
public void setDetachMode(DetachMode detachMode) {
51+
this.detachMode = detachMode;
52+
}
53+
54+
public AlterExpressionPartition withPartitionTable(Table partitionTable) {
55+
setPartitionTable(partitionTable);
56+
return this;
57+
}
58+
59+
public AlterExpressionPartition withPartitionBound(PartitionBound partitionBound) {
60+
setPartitionBound(partitionBound);
61+
return this;
62+
}
63+
64+
public AlterExpressionPartition withDetachMode(DetachMode detachMode) {
65+
setDetachMode(detachMode);
66+
return this;
67+
}
68+
1969
@Override
2070
protected void appendBody(StringBuilder b) {
21-
toStringPartition(b);
71+
if (getOperation() == AlterOperation.ATTACH_PARTITION) {
72+
b.append("ATTACH PARTITION ").append(partitionTable).append(" ")
73+
.append(partitionBound);
74+
} else if (getOperation() == AlterOperation.DETACH_PARTITION) {
75+
b.append("DETACH PARTITION ").append(partitionTable);
76+
if (detachMode != null) {
77+
b.append(" ").append(detachMode);
78+
}
79+
} else {
80+
toStringPartition(b);
81+
}
2282
}
2383
}

src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import java.util.Locale;
1313

1414
public enum AlterOperation {
15-
ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, COLLATE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, DISCARD_PARTITION, IMPORT_PARTITION, TRUNCATE_PARTITION, COALESCE_PARTITION, REORGANIZE_PARTITION, EXCHANGE_PARTITION, ANALYZE_PARTITION, CHECK_PARTITION, OPTIMIZE_PARTITION, REBUILD_PARTITION, REPAIR_PARTITION, REMOVE_PARTITIONING, PARTITION_BY, SET_TABLE_OPTION, ENGINE, FORCE, KEY_BLOCK_SIZE, LOCK, DISCARD_TABLESPACE, IMPORT_TABLESPACE, DISABLE_KEYS, ENABLE_KEYS, ENABLE_ROW_LEVEL_SECURITY, DISABLE_ROW_LEVEL_SECURITY, FORCE_ROW_LEVEL_SECURITY, NO_FORCE_ROW_LEVEL_SECURITY;
15+
ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, COLLATE, ALGORITHM, RENAME, RENAME_TABLE, RENAME_INDEX, RENAME_KEY, RENAME_CONSTRAINT, COMMENT, COMMENT_WITH_EQUAL_SIGN, UNSPECIFIC, ADD_PARTITION, DROP_PARTITION, ATTACH_PARTITION, DETACH_PARTITION, DISCARD_PARTITION, IMPORT_PARTITION, TRUNCATE_PARTITION, COALESCE_PARTITION, REORGANIZE_PARTITION, EXCHANGE_PARTITION, ANALYZE_PARTITION, CHECK_PARTITION, OPTIMIZE_PARTITION, REBUILD_PARTITION, REPAIR_PARTITION, REMOVE_PARTITIONING, PARTITION_BY, SET_TABLE_OPTION, ENGINE, FORCE, KEY_BLOCK_SIZE, LOCK, DISCARD_TABLESPACE, IMPORT_TABLESPACE, DISABLE_KEYS, ENABLE_KEYS, ENABLE_ROW_LEVEL_SECURITY, DISABLE_ROW_LEVEL_SECURITY, FORCE_ROW_LEVEL_SECURITY, NO_FORCE_ROW_LEVEL_SECURITY;
1616

1717
public static AlterOperation from(String operation) {
1818
return Enum.valueOf(AlterOperation.class, operation.toUpperCase(Locale.ROOT));

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class CreateTable implements Statement {
3737
private boolean ifNotExists = false;
3838
private boolean orReplace = false;
3939
private TablePartitioning partitioning;
40+
private Table partitionOf;
41+
private PartitionBound partitionBound;
4042

4143
private RowMovement rowMovement;
4244

@@ -157,6 +159,22 @@ public void setPartitioning(TablePartitioning partitioning) {
157159
this.partitioning = partitioning;
158160
}
159161

162+
public Table getPartitionOf() {
163+
return partitionOf;
164+
}
165+
166+
public void setPartitionOf(Table partitionOf) {
167+
this.partitionOf = partitionOf;
168+
}
169+
170+
public PartitionBound getPartitionBound() {
171+
return partitionBound;
172+
}
173+
174+
public void setPartitionBound(PartitionBound partitionBound) {
175+
this.partitionBound = partitionBound;
176+
}
177+
160178
public boolean isSelectParenthesis() {
161179
return selectParenthesis;
162180
}
@@ -179,6 +197,9 @@ public String toString() {
179197
StringBuilder b = new StringBuilder();
180198
appendCreateClause(b);
181199
appendColumnDefinitions(b);
200+
if (partitionBound != null) {
201+
b.append(" ").append(partitionBound);
202+
}
182203
appendTableOptions(b);
183204
appendTableProperties(b);
184205
return b.toString();
@@ -202,6 +223,9 @@ private void appendCreateClause(StringBuilder b) {
202223
b.append("IF NOT EXISTS ");
203224
}
204225
b.append(table);
226+
if (partitionOf != null) {
227+
b.append(" PARTITION OF ").append(partitionOf);
228+
}
205229
}
206230

207231
private void appendColumnDefinitions(StringBuilder b) {
@@ -289,6 +313,16 @@ public CreateTable withPartitioning(TablePartitioning partitioning) {
289313
return this;
290314
}
291315

316+
public CreateTable withPartitionOf(Table partitionOf) {
317+
setPartitionOf(partitionOf);
318+
return this;
319+
}
320+
321+
public CreateTable withPartitionBound(PartitionBound partitionBound) {
322+
setPartitionBound(partitionBound);
323+
return this;
324+
}
325+
292326
public CreateTable withRowMovement(RowMovement rowMovement) {
293327
this.setRowMovement(rowMovement);
294328
return this;
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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.create.table;
11+
12+
import java.io.Serializable;
13+
import net.sf.jsqlparser.expression.Expression;
14+
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
15+
16+
/** A PostgreSQL declarative-partition bound. */
17+
public class PartitionBound implements Serializable {
18+
19+
public enum Type {
20+
RANGE, LIST, HASH, DEFAULT
21+
}
22+
23+
private Type type;
24+
private ExpressionList<Expression> fromExpressions;
25+
private ExpressionList<Expression> toExpressions;
26+
private ExpressionList<Expression> inExpressions;
27+
private Expression modulus;
28+
private Expression remainder;
29+
30+
public PartitionBound() {}
31+
32+
public PartitionBound(Type type) {
33+
this.type = type;
34+
}
35+
36+
public Type getType() {
37+
return type;
38+
}
39+
40+
public void setType(Type type) {
41+
this.type = type;
42+
}
43+
44+
public ExpressionList<Expression> getFromExpressions() {
45+
return fromExpressions;
46+
}
47+
48+
public void setFromExpressions(ExpressionList<Expression> fromExpressions) {
49+
this.fromExpressions = fromExpressions;
50+
}
51+
52+
public ExpressionList<Expression> getToExpressions() {
53+
return toExpressions;
54+
}
55+
56+
public void setToExpressions(ExpressionList<Expression> toExpressions) {
57+
this.toExpressions = toExpressions;
58+
}
59+
60+
public ExpressionList<Expression> getInExpressions() {
61+
return inExpressions;
62+
}
63+
64+
public void setInExpressions(ExpressionList<Expression> inExpressions) {
65+
this.inExpressions = inExpressions;
66+
}
67+
68+
public Expression getModulus() {
69+
return modulus;
70+
}
71+
72+
public void setModulus(Expression modulus) {
73+
this.modulus = modulus;
74+
}
75+
76+
public Expression getRemainder() {
77+
return remainder;
78+
}
79+
80+
public void setRemainder(Expression remainder) {
81+
this.remainder = remainder;
82+
}
83+
84+
public PartitionBound withType(Type type) {
85+
setType(type);
86+
return this;
87+
}
88+
89+
public PartitionBound withFromExpressions(ExpressionList<Expression> fromExpressions) {
90+
setFromExpressions(fromExpressions);
91+
return this;
92+
}
93+
94+
public PartitionBound withToExpressions(ExpressionList<Expression> toExpressions) {
95+
setToExpressions(toExpressions);
96+
return this;
97+
}
98+
99+
public PartitionBound withInExpressions(ExpressionList<Expression> inExpressions) {
100+
setInExpressions(inExpressions);
101+
return this;
102+
}
103+
104+
public PartitionBound withModulus(Expression modulus) {
105+
setModulus(modulus);
106+
return this;
107+
}
108+
109+
public PartitionBound withRemainder(Expression remainder) {
110+
setRemainder(remainder);
111+
return this;
112+
}
113+
114+
@Override
115+
public String toString() {
116+
switch (type) {
117+
case RANGE:
118+
return "FOR VALUES FROM (" + fromExpressions + ") TO (" + toExpressions + ")";
119+
case LIST:
120+
return "FOR VALUES IN (" + inExpressions + ")";
121+
case HASH:
122+
return "FOR VALUES WITH (MODULUS " + modulus + ", REMAINDER " + remainder + ")";
123+
case DEFAULT:
124+
return "DEFAULT";
125+
default:
126+
return "";
127+
}
128+
}
129+
}

src/main/java/net/sf/jsqlparser/statement/create/table/TablePartitioning.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public enum Type {
3333
private boolean linear;
3434
private boolean columnsSyntax;
3535
private Expression expression;
36+
private ExpressionList<Expression> expressionList;
3637
private ExpressionList<Column> columns;
3738
private Integer algorithm;
3839
private boolean algorithmUseEquals;
@@ -79,6 +80,19 @@ public void setExpression(Expression expression) {
7980
this.expression = expression;
8081
}
8182

83+
/**
84+
* Returns the ordered partition key expressions when more than one key was declared.
85+
*
86+
* @return partition key expressions, or {@code null} for the legacy single-expression form
87+
*/
88+
public ExpressionList<Expression> getExpressionList() {
89+
return expressionList;
90+
}
91+
92+
public void setExpressionList(ExpressionList<Expression> expressionList) {
93+
this.expressionList = expressionList;
94+
}
95+
8296
public ExpressionList<Column> getColumns() {
8397
return columns;
8498
}
@@ -155,6 +169,11 @@ public TablePartitioning withExpression(Expression expression) {
155169
return this;
156170
}
157171

172+
public TablePartitioning withExpressionList(ExpressionList<Expression> expressionList) {
173+
setExpressionList(expressionList);
174+
return this;
175+
}
176+
158177
public TablePartitioning withColumns(ExpressionList<Column> columns) {
159178
setColumns(columns);
160179
return this;
@@ -273,6 +292,8 @@ private void appendMethod(StringBuilder builder) {
273292
}
274293
if (expression != null) {
275294
builder.append(" (").append(expression).append(")");
295+
} else if (expressionList != null) {
296+
builder.append(" (").append(expressionList).append(")");
276297
} else if (columns != null) {
277298
builder.append(" ").append(PlainSelect.getStringList(columns, true, true));
278299
}

src/main/java/net/sf/jsqlparser/util/deparser/CreateTableDeParser.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public void deParse(CreateTable createTable) {
5252
builder.append("IF NOT EXISTS ");
5353
}
5454
builder.append(createTable.getTable().getFullyQualifiedName());
55+
if (createTable.getPartitionOf() != null) {
56+
builder.append(" PARTITION OF ")
57+
.append(createTable.getPartitionOf().getFullyQualifiedName());
58+
}
5559

5660
if (createTable.getColumns() != null && !createTable.getColumns().isEmpty()) {
5761
builder.append(" (");
@@ -92,6 +96,10 @@ public void deParse(CreateTable createTable) {
9296
builder.append(")");
9397
}
9498

99+
if (createTable.getPartitionBound() != null) {
100+
builder.append(' ').append(createTable.getPartitionBound());
101+
}
102+
95103
params = PlainSelect.getStringList(createTable.getTableOptionsStrings(), false, false);
96104
if (!"".equals(params)) {
97105
builder.append(' ').append(params);

0 commit comments

Comments
 (0)