Skip to content

Commit d60c762

Browse files
authored
feat: support MySQL ALTER TABLE ... PARTITION BY syntax (#2210)
1 parent 30cf5d7 commit d60c762

File tree

4 files changed

+184
-6
lines changed

4 files changed

+184
-6
lines changed

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.statement.alter;
1111

12+
import net.sf.jsqlparser.expression.Expression;
1213
import net.sf.jsqlparser.statement.ReferentialAction;
1314
import net.sf.jsqlparser.statement.ReferentialAction.Action;
1415
import net.sf.jsqlparser.statement.ReferentialAction.Type;
@@ -75,6 +76,11 @@ public class AlterExpression implements Serializable {
7576

7677
private boolean useIfNotExists = false;
7778

79+
private String partitionType;
80+
private Expression partitionExpression;
81+
private List<String> partitionColumns;
82+
83+
7884
public Index getOldIndex() {
7985
return oldIndex;
8086
}
@@ -494,6 +500,30 @@ public AlterExpression withUserIfNotExists(boolean userIfNotExists) {
494500
return this;
495501
}
496502

503+
public void setPartitionType(String partitionType) {
504+
this.partitionType = partitionType;
505+
}
506+
507+
public String getPartitionType() {
508+
return partitionType;
509+
}
510+
511+
public void setPartitionExpression(Expression partitionExpression) {
512+
this.partitionExpression = partitionExpression;
513+
}
514+
515+
public Expression getPartitionExpression() {
516+
return partitionExpression;
517+
}
518+
519+
public void setPartitionColumns(List<String> partitionColumns) {
520+
this.partitionColumns = partitionColumns;
521+
}
522+
523+
public List<String> getPartitionColumns() {
524+
return partitionColumns;
525+
}
526+
497527
@Override
498528
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.NPathComplexity",
499529
"PMD.ExcessiveMethodLength", "PMD.SwitchStmtsShouldHaveDefault"})
@@ -601,6 +631,28 @@ public String toString() {
601631
} else if (operation == AlterOperation.TRUNCATE_PARTITION
602632
&& partitions != null) {
603633
b.append("TRUNCATE PARTITION ").append(PlainSelect.getStringList(partitions));
634+
} else if (operation == AlterOperation.PARTITION_BY) {
635+
b.append("PARTITION BY ").append(partitionType).append(" ");
636+
if (partitionExpression != null) {
637+
b.append("(").append(partitionExpression).append(") ");
638+
} else if (partitionColumns != null && !partitionColumns.isEmpty()) {
639+
b.append("COLUMNS(").append(String.join(", ", partitionColumns)).append(") ");
640+
}
641+
b.append("(");
642+
for (int i = 0; i < partitionDefinitions.size(); i++) {
643+
PartitionDefinition partition = partitionDefinitions.get(i);
644+
b.append("PARTITION ").append(partition.getPartitionName())
645+
.append(" ").append(partition.getPartitionOperation())
646+
.append(" (").append(PlainSelect.getStringList(partition.getValues()))
647+
.append(")");
648+
if (partition.getStorageEngine() != null) {
649+
b.append(" ENGINE = ").append(partition.getStorageEngine());
650+
}
651+
if (i < partitionDefinitions.size() - 1) {
652+
b.append(", ");
653+
}
654+
}
655+
b.append(")");
604656
} else {
605657
if (operation == AlterOperation.COMMENT_WITH_EQUAL_SIGN) {
606658
b.append("COMMENT =").append(" ");

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
package net.sf.jsqlparser.statement.alter;
1111

1212
public enum AlterOperation {
13-
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, TRUNCATE_PARTITION, SET_TABLE_OPTION, ENGINE, FORCE, LOCK, DISCARD_TABLESPACE, IMPORT_TABLESPACE, DISABLE_KEYS, ENABLE_KEYS;
13+
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, PARTITION_BY, TRUNCATE_PARTITION, SET_TABLE_OPTION, ENGINE, FORCE, LOCK, DISCARD_TABLESPACE, IMPORT_TABLESPACE, DISABLE_KEYS, ENABLE_KEYS;
1414

1515
public static AlterOperation from(String operation) {
1616
return Enum.valueOf(AlterOperation.class, operation.toUpperCase());

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7650,6 +7650,7 @@ List<PartitionDefinition> PartitionDefinitions():
76507650
String partitionName = null;
76517651
String partitionOperation = null;
76527652
String storageEngine = null;
7653+
Expression exp = null;
76537654
}
76547655
{
76557656
"("
@@ -7663,10 +7664,9 @@ List<PartitionDefinition> PartitionDefinitions():
76637664
(
76647665
<K_LESS> <K_THAN>
76657666
(
7666-
"("
7667-
( tk=<S_CHAR_LITERAL> { values.add(tk.image); }
7668-
| tk=<S_LONG> { values.add(tk.image); }
7669-
[ "," ] )* ")"
7667+
"(" exp = Expression() ")"{
7668+
values.add(exp.toString());
7669+
}
76707670
| <K_MAXVALUE> { values.add("MAXVALUE"); }
76717671
) {
76727672
partitionOperation = "VALUES LESS THAN";
@@ -7685,7 +7685,6 @@ List<PartitionDefinition> PartitionDefinitions():
76857685
}
76867686
}
76877687

7688-
76897688
List<String> PartitionNamesList() :
76907689
{
76917690
Token tk;
@@ -8146,6 +8145,28 @@ AlterExpression AlterExpression():
81468145
}
81478146
}
81488147
)
8148+
|
8149+
LOOKAHEAD(2) (
8150+
<K_PARTITION> <K_BY> {
8151+
alterExp.setOperation(AlterOperation.PARTITION_BY);
8152+
}
8153+
<K_RANGE> {
8154+
alterExp.setPartitionType("RANGE");
8155+
Expression exp = null;
8156+
}
8157+
(
8158+
"(" exp=Expression() ")" {
8159+
alterExp.setPartitionExpression(exp);
8160+
}
8161+
|
8162+
<K_COLUMNS> columnNames=ColumnsNamesList() {
8163+
alterExp.setPartitionColumns(columnNames);
8164+
}
8165+
)
8166+
partitionDefinition=PartitionDefinitions() {
8167+
alterExp.setPartitionDefinitions(partitionDefinition);
8168+
}
8169+
)
81498170
|
81508171
LOOKAHEAD(2)
81518172
(<K_RENAME> ((<K_INDEX> {alterExp.setOperation(AlterOperation.RENAME_INDEX);}

src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,4 +1500,109 @@ public void testAlterTableKeys() throws JSQLParserException {
15001500
AlterExpression alterExpEnable = alterEnable.getAlterExpressions().get(0);
15011501
assertEquals(AlterOperation.ENABLE_KEYS, alterExpEnable.getOperation());
15021502
}
1503+
1504+
@Test
1505+
public void testAlterTablePartitionByRangeColumns() throws JSQLParserException {
1506+
String sql = "ALTER TABLE `payment_lock` " +
1507+
"PARTITION BY RANGE COLUMNS(`created_at`) (" +
1508+
"PARTITION p20210217 VALUES LESS THAN ('20210218') ENGINE = InnoDB, " +
1509+
"PARTITION p20210218 VALUES LESS THAN ('20210219') ENGINE = InnoDB);";
1510+
Statement stmt = CCJSqlParserUtil.parse(sql);
1511+
assertInstanceOf(Alter.class, stmt);
1512+
Alter alter = (Alter) stmt;
1513+
assertEquals("`payment_lock`", alter.getTable().getFullyQualifiedName());
1514+
1515+
List<AlterExpression> alterExpressions = alter.getAlterExpressions();
1516+
assertNotNull(alterExpressions);
1517+
assertEquals(1, alterExpressions.size());
1518+
1519+
AlterExpression partitionExp = alterExpressions.get(0);
1520+
assertEquals(AlterOperation.PARTITION_BY, partitionExp.getOperation());
1521+
List<PartitionDefinition> partitions = partitionExp.getPartitionDefinitions();
1522+
assertNotNull(partitions);
1523+
assertEquals(2, partitions.size());
1524+
1525+
assertEquals("p20210217", partitions.get(0).getPartitionName());
1526+
assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation());
1527+
assertEquals(Collections.singletonList("'20210218'"), partitions.get(0).getValues());
1528+
1529+
assertEquals("p20210218", partitions.get(1).getPartitionName());
1530+
assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation());
1531+
assertEquals(Collections.singletonList("'20210219'"), partitions.get(1).getValues());
1532+
1533+
assertSqlCanBeParsedAndDeparsed(sql);
1534+
}
1535+
1536+
@Test
1537+
public void testAlterTablePartitionByRangeUnixTimestamp() throws JSQLParserException {
1538+
String sql = "ALTER TABLE `test`.`pipeline_service_metadata_history` " +
1539+
"PARTITION BY RANGE (FLOOR(UNIX_TIMESTAMP(requested_at))) (" +
1540+
"PARTITION p202104 VALUES LESS THAN (UNIX_TIMESTAMP('2021-05-01 00:00:00')) ENGINE = InnoDB, "
1541+
+
1542+
"PARTITION p202105 VALUES LESS THAN (UNIX_TIMESTAMP('2021-06-01 00:00:00')) ENGINE = InnoDB);";
1543+
Statement stmt = CCJSqlParserUtil.parse(sql);
1544+
assertInstanceOf(Alter.class, stmt);
1545+
Alter alter = (Alter) stmt;
1546+
assertEquals("`test`.`pipeline_service_metadata_history`",
1547+
alter.getTable().getFullyQualifiedName());
1548+
1549+
List<AlterExpression> alterExpressions = alter.getAlterExpressions();
1550+
assertNotNull(alterExpressions);
1551+
assertEquals(1, alterExpressions.size());
1552+
1553+
AlterExpression partitionExp = alterExpressions.get(0);
1554+
assertEquals(AlterOperation.PARTITION_BY, partitionExp.getOperation());
1555+
List<PartitionDefinition> partitions = partitionExp.getPartitionDefinitions();
1556+
assertNotNull(partitions);
1557+
assertEquals(2, partitions.size());
1558+
1559+
assertEquals("p202104", partitions.get(0).getPartitionName());
1560+
assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation());
1561+
assertEquals(Collections.singletonList("UNIX_TIMESTAMP('2021-05-01 00:00:00')"),
1562+
partitions.get(0).getValues());
1563+
1564+
assertEquals("p202105", partitions.get(1).getPartitionName());
1565+
assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation());
1566+
assertEquals(Collections.singletonList("UNIX_TIMESTAMP('2021-06-01 00:00:00')"),
1567+
partitions.get(1).getValues());
1568+
1569+
assertSqlCanBeParsedAndDeparsed(sql);
1570+
}
1571+
1572+
@Test
1573+
public void testAlterTablePartitionByRangeUnixTimestamp2() throws JSQLParserException {
1574+
String sql = "ALTER TABLE MP_MNEWS.PUR_MNEWS_CONTS " +
1575+
"PARTITION BY RANGE (UNIX_TIMESTAMP(REG_DATE_TS)) (" +
1576+
"PARTITION p202007 VALUES LESS THAN (1596207600) ENGINE = InnoDB, " +
1577+
"PARTITION p202008 VALUES LESS THAN (1598886000) ENGINE = InnoDB, " +
1578+
"PARTITION p202009 VALUES LESS THAN (1601478000) ENGINE = InnoDB);";
1579+
Statement stmt = CCJSqlParserUtil.parse(sql);
1580+
assertInstanceOf(Alter.class, stmt);
1581+
Alter alter = (Alter) stmt;
1582+
assertEquals("MP_MNEWS.PUR_MNEWS_CONTS", alter.getTable().getFullyQualifiedName());
1583+
1584+
List<AlterExpression> alterExpressions = alter.getAlterExpressions();
1585+
assertNotNull(alterExpressions);
1586+
assertEquals(1, alterExpressions.size());
1587+
1588+
AlterExpression partitionExp = alterExpressions.get(0);
1589+
assertEquals(AlterOperation.PARTITION_BY, partitionExp.getOperation());
1590+
List<PartitionDefinition> partitions = partitionExp.getPartitionDefinitions();
1591+
assertNotNull(partitions);
1592+
assertEquals(3, partitions.size());
1593+
1594+
assertEquals("p202007", partitions.get(0).getPartitionName());
1595+
assertEquals("VALUES LESS THAN", partitions.get(0).getPartitionOperation());
1596+
assertEquals(Collections.singletonList("1596207600"), partitions.get(0).getValues());
1597+
1598+
assertEquals("p202008", partitions.get(1).getPartitionName());
1599+
assertEquals("VALUES LESS THAN", partitions.get(1).getPartitionOperation());
1600+
assertEquals(Collections.singletonList("1598886000"), partitions.get(1).getValues());
1601+
1602+
assertEquals("p202009", partitions.get(2).getPartitionName());
1603+
assertEquals("VALUES LESS THAN", partitions.get(2).getPartitionOperation());
1604+
assertEquals(Collections.singletonList("1601478000"), partitions.get(2).getValues());
1605+
1606+
assertSqlCanBeParsedAndDeparsed(sql);
1607+
}
15031608
}

0 commit comments

Comments
 (0)