diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java index b9711d9a5..29db90fc3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterExpression.java @@ -60,6 +60,7 @@ public class AlterExpression implements Serializable { private String characterSet; private String collation; + private boolean defaultCollateSpecified; private String lockOption; private String algorithmOption; private String engineOption; @@ -432,6 +433,14 @@ public void setCollation(String collation) { this.collation = collation; } + public void setDefaultCollateSpecified(boolean value) { + this.defaultCollateSpecified = value; + } + + public boolean isDefaultCollateSpecified() { + return defaultCollateSpecified; + } + public String getLockOption() { return lockOption; } @@ -564,6 +573,17 @@ public String toString() { } b.append(getCollation()); } + } else if (operation == AlterOperation.COLLATE) { + if (isDefaultCollateSpecified()) { + b.append("DEFAULT "); + } + b.append("COLLATE "); + if (hasEqualForCollate) { + b.append("= "); + } + if (getCollation() != null) { + b.append(getCollation()); + } } else if (operation == AlterOperation.DROP_UNIQUE) { b.append("DROP UNIQUE (").append(PlainSelect.getStringList(pkColumns)).append(')'); diff --git a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java index b0f1f8924..b97ea36e3 100644 --- a/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java +++ b/src/main/java/net/sf/jsqlparser/statement/alter/AlterOperation.java @@ -10,7 +10,7 @@ package net.sf.jsqlparser.statement.alter; public enum AlterOperation { - ADD, ALTER, DROP, DROP_PRIMARY_KEY, DROP_UNIQUE, DROP_FOREIGN_KEY, MODIFY, CHANGE, CONVERT, 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; + 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; public static AlterOperation from(String operation) { return Enum.valueOf(AlterOperation.class, operation.toUpperCase()); diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 0f1fb080a..6a4416e23 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -8041,14 +8041,28 @@ AlterExpression AlterExpression(): tk= { alterExp.setCharacterSet(tk.image); } [ tk2= { alterExp.setCollation(tk2.image); }] ) - | ( { - alterExp.setOperation(AlterOperation.CONVERT); - alterExp.setConvertType(AlterExpression.ConvertType.DEFAULT_CHARACTER_SET); - } - [ "=" { alterExp.setHasEqualForCharacterSet(true); } ] - tk= { alterExp.setCharacterSet(tk.image); } - [ [ "=" { alterExp.setHasEqualForCollate(true); } ] - tk2= { alterExp.setCollation(tk2.image); }] + | + LOOKAHEAD(3) + ( + + ( + [ "=" { alterExp.setHasEqualForCharacterSet(true); } ] + tk= { + alterExp.setOperation(AlterOperation.CONVERT); + alterExp.setConvertType(AlterExpression.ConvertType.DEFAULT_CHARACTER_SET); + alterExp.setCharacterSet(tk.image); + } + [ [ "=" { alterExp.setHasEqualForCollate(true); } ] + tk2= { alterExp.setCollation(tk2.image); }] + | + + [ "=" { alterExp.setHasEqualForCollate(true); } ] + tk= { + alterExp.setOperation(AlterOperation.COLLATE); + alterExp.setCollation(tk.image); + alterExp.setDefaultCollateSpecified(true); + } + ) ) | ( [ "=" { alterExp.setHasEqualForCharacterSet(true); } ] tk= { @@ -8059,6 +8073,12 @@ AlterExpression AlterExpression(): [ [ "=" { alterExp.setHasEqualForCollate(true); } ] tk2= { alterExp.setCollation(tk2.image); }] ) + | ( { alterExp.setOperation(AlterOperation.COLLATE); } + [ "=" { alterExp.setHasEqualForCollate(true); } ] + tk= { + alterExp.setCollation(tk.image); + } + ) | ( {alterExp.setOperation(AlterOperation.COMMENT);} ["=" {alterExp.setOperation(AlterOperation.COMMENT_WITH_EQUAL_SIGN);} ] diff --git a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java index 87fcda56f..1b31004a6 100644 --- a/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java +++ b/src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java @@ -1074,6 +1074,49 @@ public void testIssue2027() throws JSQLParserException { assertSqlCanBeParsedAndDeparsed(sqlLongText); } + @Test + public void testAlterTableCollate() throws JSQLParserException { + // Case 1: Without DEFAULT and without = + String sql = "ALTER TABLE tbl_name COLLATE collation_name"; + + Alter alter = (Alter) CCJSqlParserUtil.parse(sql); + AlterExpression expression = alter.getAlterExpressions().get(0); + assertEquals(expression.getOperation(), AlterOperation.COLLATE); + assertEquals(expression.getCollation(), "collation_name"); + assertFalse(expression.isDefaultCollateSpecified()); + assertSqlCanBeParsedAndDeparsed(sql); + + // Case 2: Without DEFAULT and with = + sql = "ALTER TABLE tbl_name COLLATE = collation_name"; + + alter = (Alter) CCJSqlParserUtil.parse(sql); + expression = alter.getAlterExpressions().get(0); + assertEquals(expression.getOperation(), AlterOperation.COLLATE); + assertEquals(expression.getCollation(), "collation_name"); + assertFalse(expression.isDefaultCollateSpecified()); + assertSqlCanBeParsedAndDeparsed(sql); + + // Case 3: With DEFAULT and without = + sql = "ALTER TABLE tbl_name DEFAULT COLLATE collation_name"; + + alter = (Alter) CCJSqlParserUtil.parse(sql); + expression = alter.getAlterExpressions().get(0); + assertEquals(expression.getOperation(), AlterOperation.COLLATE); + assertEquals(expression.getCollation(), "collation_name"); + assertTrue(expression.isDefaultCollateSpecified()); + assertSqlCanBeParsedAndDeparsed(sql); + + // Case 4: With DEFAULT and with = + sql = "ALTER TABLE tbl_name DEFAULT COLLATE = collation_name"; + + alter = (Alter) CCJSqlParserUtil.parse(sql); + expression = alter.getAlterExpressions().get(0); + assertEquals(expression.getOperation(), AlterOperation.COLLATE); + assertEquals(expression.getCollation(), "collation_name"); + assertTrue(expression.isDefaultCollateSpecified()); + assertSqlCanBeParsedAndDeparsed(sql); + } + @Test public void testIssue2090LockNone() throws JSQLParserException { String sql =