in core/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java [5797:6496]
private boolean parseAlterSpecification(SQLAlterTableStatement stmt) {
// Specification except table options.
switch (lexer.token()) {
case IDENTIFIER:
if (lexer.identifierEquals(FnvHash.Constants.ADD)) {
alterTableAdd(stmt);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.ALGORITHM)) {
// ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
MySqlAlterTableAlgorithm item = new MySqlAlterTableAlgorithm();
item.setAlgorithmType(new SQLIdentifierExpr(lexer.stringVal()));
stmt.addItem(item);
lexer.nextToken();
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.CHANGE)) {
// CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST|AFTER col_name]
lexer.nextToken();
if (lexer.token() == Token.COLUMN) {
lexer.nextToken();
}
MySqlAlterTableChangeColumn item = new MySqlAlterTableChangeColumn();
item.setColumnName(this.exprParser.name());
item.setNewColumnDefinition(this.exprParser.parseColumn());
if (lexer.identifierEquals("AFTER")) {
lexer.nextToken();
item.setAfterColumn(this.exprParser.name());
} else if (lexer.identifierEquals("FIRST")) {
lexer.nextToken();
if (lexer.token() == Token.IDENTIFIER) {
item.setFirstColumn(this.exprParser.name());
} else {
item.setFirst(true);
}
}
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.CONVERT)) {
// CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
lexer.nextToken();
accept(Token.TO);
acceptIdentifier("CHARACTER");
accept(Token.SET);
SQLAlterTableConvertCharSet item = new SQLAlterTableConvertCharSet();
SQLExpr charset = this.exprParser.name();
item.setCharset(charset);
if (lexer.identifierEquals("COLLATE")) {
lexer.nextToken();
SQLExpr collate = this.exprParser.primary();
item.setCollate(collate);
}
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.DISCARD)) {
// DISCARD PARTITION {partition_names | ALL} TABLESPACE
// DISCARD TABLESPACE
lexer.nextToken();
if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
SQLAlterTableDiscardPartition item = new SQLAlterTableDiscardPartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
if (lexer.token() == Token.TABLESPACE) {
lexer.nextToken();
item.setTablespace(true);
}
stmt.addItem(item);
} else {
accept(Token.TABLESPACE);
MySqlAlterTableDiscardTablespace item = new MySqlAlterTableDiscardTablespace();
stmt.addItem(item);
}
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.IMPORT)) {
// IMPORT PARTITION {partition_names | ALL} TABLESPACE
// IMPORT TABLESPACE
lexer.nextToken();
if (lexer.token() == Token.PARTITION) {
lexer.nextToken();
SQLAlterTableImportPartition item = new SQLAlterTableImportPartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
if (lexer.token() == Token.TABLESPACE) {
lexer.nextToken();
item.setTablespace(true);
}
stmt.addItem(item);
} else {
accept(Token.TABLESPACE);
MySqlAlterTableImportTablespace item = new MySqlAlterTableImportTablespace();
stmt.addItem(item);
}
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.FORCE)) {
// FORCE
lexer.nextToken();
MySqlAlterTableForce item = new MySqlAlterTableForce();
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.MODIFY)) {
// MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name]
lexer.nextToken();
if (lexer.token() == Token.COLUMN) {
lexer.nextToken();
}
boolean paren = false;
if (lexer.token() == Token.LPAREN) {
paren = true;
lexer.nextToken();
}
for (; ; ) {
MySqlAlterTableModifyColumn item = new MySqlAlterTableModifyColumn();
item.setNewColumnDefinition(this.exprParser.parseColumn());
if (lexer.identifierEquals("AFTER")) {
lexer.nextToken();
item.setAfterColumn(this.exprParser.name());
} else if (lexer.identifierEquals("FIRST")) {
lexer.nextToken();
if (lexer.token() == Token.IDENTIFIER) {
item.setFirstColumn(this.exprParser.name());
} else {
item.setFirst(true);
}
}
stmt.addItem(item);
if (paren && lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
if (paren) {
accept(Token.RPAREN);
}
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.RENAME)) {
// RENAME {INDEX|KEY} old_index_name TO new_index_name
// RENAME [TO|AS] new_tbl_name
lexer.nextToken();
switch (lexer.token()) {
case INDEX:
case KEY: {
lexer.nextToken();
SQLName name = this.exprParser.name();
accept(Token.TO);
SQLName to = this.exprParser.name();
SQLAlterTableRenameIndex item = new SQLAlterTableRenameIndex(name, to);
stmt.addItem(item);
return true;
}
case COLUMN: {
lexer.nextToken();
SQLName columnName = exprParser.name();
accept(Token.TO);
SQLName toName = this.exprParser.name();
SQLAlterTableRenameColumn renameColumn = new SQLAlterTableRenameColumn();
renameColumn.setColumn(columnName);
renameColumn.setTo(toName);
stmt.addItem(renameColumn);
return true;
}
case TO:
case AS:
lexer.nextToken();
case IDENTIFIER:
SQLAlterTableRename item = new SQLAlterTableRename();
SQLName to = this.exprParser.name();
item.setTo(to);
stmt.addItem(item);
return true;
default:
break;
}
} else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {
// WITHOUT VALIDATION
lexer.nextToken();
acceptIdentifier("VALIDATION");
MySqlAlterTableValidation item = new MySqlAlterTableValidation();
item.setWithValidation(false);
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals("COALESCE")) {
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableCoalescePartition item = new SQLAlterTableCoalescePartition();
SQLIntegerExpr countExpr = this.exprParser.integerExpr();
item.setCount(countExpr);
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals("REORGANIZE")) {
// REORGANIZE PARTITION partition_names INTO (partition_definitions)
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableReOrganizePartition item = new SQLAlterTableReOrganizePartition();
this.exprParser.names(item.getNames(), item);
accept(Token.INTO);
accept(Token.LPAREN);
for (; ; ) {
MysqlPartitionSingle partition = this.getExprParser().parsePartition();
item.addPartition(partition);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
accept(Token.RPAREN);
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.EXCHANGE)) {
// EXCHANGE PARTITION partition_name WITH TABLE tbl_name [{WITH|WITHOUT} VALIDATION]
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableExchangePartition item = new SQLAlterTableExchangePartition();
SQLName partition = this.exprParser.name();
item.addPartition(partition);
accept(WITH);
accept(TABLE);
SQLName table = this.exprParser.name();
item.setTable(table);
if (lexer.token() == WITH) {
lexer.nextToken();
acceptIdentifier("VALIDATION");
item.setValidation(true);
} else if (lexer.identifierEquals(FnvHash.Constants.WITHOUT)) {
lexer.nextToken();
acceptIdentifier("VALIDATION");
item.setValidation(false);
}
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals("REBUILD")) {
// REBUILD PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableRebuildPartition item = new SQLAlterTableRebuildPartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals("REPAIR")) {
// REPAIR PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableRepairPartition item = new SQLAlterTableRepairPartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.REMOVE)) {
// REMOVE PARTITIONING
lexer.nextToken();
acceptIdentifier("PARTITIONING");
stmt.setRemovePatiting(true);
} else if (lexer.identifierEquals("UPGRADE")) {
// UPGRADE PARTITIONING
lexer.nextToken();
acceptIdentifier("PARTITIONING");
stmt.setUpgradePatiting(true);
} else if (lexer.identifierEquals("HOT_PARTITION_COUNT")) {
// UPGRADE PARTITIONING
lexer.nextToken();
accept(EQ);
try {
stmt.getTableOptions().add(new SQLAssignItem(new SQLIdentifierExpr("HOT_PARTITION_COUNT"), this.exprParser.integerExpr()));
} catch (Exception e) {
throw new ParserException("only integer number is supported for hot_partition_count");
}
}
//
// Other not in MySql documents.
//
else if (lexer.identifierEquals(FnvHash.Constants.PARTITIONS)) {
// Caution: Not in MySql documents.
SQLAlterTablePartitionCount item = new SQLAlterTablePartitionCount();
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
item.setCount((SQLIntegerExpr) exprParser.integerExpr());
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION)) {
// Caution: Not in MySql documents.
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {
lexer.nextToken();
SQLAlterTableSubpartitionLifecycle item = new SQLAlterTableSubpartitionLifecycle();
if (lexer.token() == Token.LITERAL_INT) {
for (; ; ) {
item.getPartitionIds().add(this.exprParser.integerExpr());
String pidStr = lexer.stringVal();
accept(Token.VARIANT);
String s = pidStr.replaceAll(":", "");
if (StringUtils.isEmpty(s)) {
item.getSubpartitionLifeCycle().add(exprParser.integerExpr());
} else {
item.getSubpartitionLifeCycle().add(new SQLIntegerExpr(Integer.valueOf(s)));
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
}
stmt.addItem(item);
}
return true;
} else if (lexer.identifierEquals("BLOCK_SIZE")) {
// Caution: Not in MySql documents.
SQLAlterTableBlockSize item = new SQLAlterTableBlockSize();
lexer.nextToken();
if (lexer.token() == Token.EQ) {
accept(Token.EQ);
}
item.setSize((SQLIntegerExpr) exprParser.expr());
stmt.addItem(item);
return true;
} else if (lexer.identifierEquals(INSERT_METHOD)) {
// Caution: Not in MySql documents.
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
stmt.getTableOptions().add(new SQLAssignItem(new SQLIdentifierExpr(INSERT_METHOD), this.exprParser.primary()));
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.CLUSTERED)) {
// Caution: Not in MySql documents.
SQLAlterTableModifyClusteredBy clusteredBy = new SQLAlterTableModifyClusteredBy();
acceptIdentifier("CLUSTERED");
accept(Token.BY);
accept(Token.LPAREN);
// for ads: ALTER TABLE SCHEMA1.TABLE1 CLUSTERED BY ();
if (lexer.token() != Token.RPAREN) {
for (; ; ) {
clusteredBy.addClusterColumn(this.exprParser.name());
if (lexer.token() == Token.COMMA) {
accept(Token.COMMA);
continue;
}
break;
}
}
accept(Token.RPAREN);
stmt.addItem(clusteredBy);
return true;
} else if (lexer.identifierEquals(FnvHash.Constants.SUBPARTITION_AVAILABLE_PARTITION_NUM)) {
// Caution: Not in MySql documents.
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
SQLIntegerExpr num = this.exprParser.integerExpr();
SQLAlterTableSubpartitionAvailablePartitionNum item = new SQLAlterTableSubpartitionAvailablePartitionNum();
item.setNumber(num);
stmt.addItem(item);
return true;
}
break;
case ALTER: {
lexer.nextToken();
if (lexer.token() == INDEX) {
// Caution: Not in MySql documents.
lexer.nextToken();
SQLName indexName = this.exprParser.name();
if (lexer.identifierEquals("VISIBLE") || lexer.identifierEquals("INVISIBLE")) {
SQLAlterTableAlterIndex alterIndex = new SQLAlterTableAlterIndex();
alterIndex.setName(indexName);
alterIndex.getIndexDefinition().getOptions().setVisible(lexer.identifierEquals("VISIBLE"));
alterIndex.getIndexDefinition().getOptions().setInvisible(lexer.identifierEquals("INVISIBLE"));
lexer.nextToken();
stmt.addItem(alterIndex);
break;
}
MySqlAlterTableAlterFullTextIndex alterIndex = new MySqlAlterTableAlterFullTextIndex();
alterIndex.setIndexName(indexName);
accept(Token.SET);
accept(Token.FULLTEXT);
if (lexer.token() == INDEX) {
lexer.nextToken();
alterIndex.setAnalyzerType(AnalyzerIndexType.INDEX);
} else if (lexer.identifierEquals(FnvHash.Constants.QUERY)) {
lexer.nextToken();
alterIndex.setAnalyzerType(AnalyzerIndexType.QUERY);
}
acceptIdentifier("ANALYZER");
accept(Token.EQ);
alterIndex.setAnalyzerName(this.exprParser.name());
stmt.addItem(alterIndex);
} else if (lexer.token() == Token.CHECK || lexer.token() == Token.CONSTRAINT) {
lexer.nextToken();
MysqlAlterTableAlterCheck check = new MysqlAlterTableAlterCheck();
check.setName(this.exprParser.name());
boolean enforce = true;
if (lexer.token() == Token.NOT) {
enforce = false;
lexer.nextToken();
}
if (lexer.stringVal().equalsIgnoreCase("ENFORCED")) {
check.setEnforced(enforce);
lexer.nextToken();
}
stmt.addItem(check);
} else {
// ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
if (lexer.token() == Token.COLUMN) {
lexer.nextToken();
}
MySqlAlterTableAlterColumn alterColumn = new MySqlAlterTableAlterColumn();
alterColumn.setColumn(this.exprParser.name());
if (lexer.token() == Token.SET) {
lexer.nextToken();
if (lexer.identifierEquals("VISIBLE") || lexer.identifierEquals("INVISIBLE")) {
alterColumn.setVisibleType(lexer.stringVal());
lexer.nextToken();
} else {
accept(Token.DEFAULT);
alterColumn.setDefaultExpr(this.exprParser.expr());
}
} else {
accept(Token.DROP);
accept(Token.DEFAULT);
alterColumn.setDropDefault(true);
}
stmt.addItem(alterColumn);
}
return true;
}
// [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]
// parse in table options.
case DISABLE:
lexer.nextToken();
if (lexer.token() == Token.CONSTRAINT) {
// Caution: Not in MySql documents.
lexer.nextToken();
SQLAlterTableDisableConstraint item = new SQLAlterTableDisableConstraint();
item.setConstraintName(this.exprParser.name());
stmt.addItem(item);
} else {
// DISABLE KEYS
acceptIdentifier("KEYS");
SQLAlterTableDisableKeys item = new SQLAlterTableDisableKeys();
stmt.addItem(item);
}
return true;
case ENABLE:
lexer.nextToken();
if (lexer.token() == Token.CONSTRAINT) {
// Caution: Not in MySql documents.
lexer.nextToken();
SQLAlterTableEnableConstraint item = new SQLAlterTableEnableConstraint();
item.setConstraintName(this.exprParser.name());
stmt.addItem(item);
} else {
// ENABLE KEYS
acceptIdentifier("KEYS");
SQLAlterTableEnableKeys item = new SQLAlterTableEnableKeys();
stmt.addItem(item);
}
return true;
case LOCK: {
// LOCK [=] {DEFAULT|NONE|SHARED|EXCLUSIVE}
lexer.nextToken();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
MySqlAlterTableLock item = new MySqlAlterTableLock();
item.setLockType(new SQLIdentifierExpr(lexer.stringVal()));
lexer.nextToken();
stmt.addItem(item);
return true;
}
case ORDER: {
lexer.nextToken();
accept(Token.BY);
MySqlAlterTableOrderBy item = new MySqlAlterTableOrderBy();
while (true) {
if (lexer.token() == Token.IDENTIFIER) {
SQLSelectOrderByItem column = this.exprParser.parseSelectOrderByItem();
column.setParent(item);
item.addColumn(column);
} else {
break;
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
} else {
break;
}
}
stmt.addItem(item);
return true;
}
case WITH: {
// WITH VALIDATION
lexer.nextToken();
acceptIdentifier("VALIDATION");
MySqlAlterTableValidation item = new MySqlAlterTableValidation();
item.setWithValidation(true);
stmt.addItem(item);
return true;
}
case DROP:
// DROP [COLUMN] col_name
// DROP {INDEX|KEY} index_name
// DROP PRIMARY KEY
// DROP FOREIGN KEY fk_symbol
// DROP PARTITION partition_names
// TODO: need check.
parseAlterDrop(stmt);
return true;
case TRUNCATE: {
// TRUNCATE PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableTruncatePartition item = new SQLAlterTableTruncatePartition();
if (lexer.token() == Token.ALL) {
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
lexer.nextToken();
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
}
case ANALYZE: {
// ANALYZE PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableAnalyzePartition item = new SQLAlterTableAnalyzePartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
}
case CHECK: {
// CHECK PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableCheckPartition item = new SQLAlterTableCheckPartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
}
case OPTIMIZE: {
// OPTIMIZE PARTITION {partition_names | ALL}
lexer.nextToken();
accept(Token.PARTITION);
SQLAlterTableOptimizePartition item = new SQLAlterTableOptimizePartition();
if (lexer.token() == Token.ALL) {
lexer.nextToken();
item.getPartitions().add(new SQLIdentifierExpr("ALL"));
} else {
this.exprParser.names(item.getPartitions(), item);
}
stmt.addItem(item);
return true;
}
//
// Other not in MySql documents.
//
case SET: {
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.RULE)) {
SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();
SQLAssignItem item = this.exprParser.parseAssignItem();
setOption.addOption(item);
stmt.addItem(setOption);
} else {
acceptIdentifier("TBLPROPERTIES");
SQLAlterTableSetOption setOption = new SQLAlterTableSetOption();
accept(Token.LPAREN);
for (; ; ) {
SQLAssignItem item = this.exprParser.parseAssignItem();
setOption.addOption(item);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
stmt.addItem(setOption);
if (lexer.token() == Token.ON) {
lexer.nextToken();
SQLName on = this.exprParser.name();
setOption.setOn(on);
}
}
return true;
}
case PARTITION: {
Lexer.SavePoint mark = lexer.mark();
lexer.nextToken();
if (lexer.identifierEquals(FnvHash.Constants.LIFECYCLE)) {
lexer.nextToken();
SQLAlterTablePartitionLifecycle item = new SQLAlterTablePartitionLifecycle();
if (lexer.token() == Token.EQ) {
lexer.nextToken();
}
item.setLifecycle((SQLIntegerExpr) exprParser.integerExpr());
stmt.addItem(item);
return true;
} else {
lexer.reset(mark);
}
}
}
return false;
}