Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ public enum TableRenameKeyword {

private boolean useBrackets = false;

// T-SQL/Snowflake ADD lists items comma-separated, without brackets.
private boolean bareAddList = false;

private boolean useIfNotExists = false;

private String partitionType;
Expand Down Expand Up @@ -137,6 +140,14 @@ public void useBrackets(boolean useBrackets) {
this.useBrackets = useBrackets;
}

public boolean isBareAddList() {
return bareAddList;
}

public void setBareAddList(boolean bareAddList) {
this.bareAddList = bareAddList;
}

public void hasColumn(boolean hasColumn) {
this.hasColumn = hasColumn;
}
Expand Down Expand Up @@ -1638,7 +1649,7 @@ private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPri
b.append(optionalSpecifier).append(" ");
}
b.append(columnOldName).append(" ");
} else if (colDataTypeList.size() > 1) {
} else if (colDataTypeList.size() > 1 && !bareAddList) {
b.append("(");
} else {
if (hasColumn) {
Expand All @@ -1664,9 +1675,14 @@ private void toStringGeneral(StringBuilder b, Consumer<ColumnDataType> columnPri
if (useBrackets && colDataTypeList.size() == 1) {
b.append(')');
}
if (colDataTypeList.size() > 1) {
if (colDataTypeList.size() > 1 && !bareAddList) {
b.append(")");
}
if (constraint != null && bareAddList) {
// T-SQL/Snowflake ADD lists may append a table constraint after
// the column definitions.
b.append(", ").append(constraint);
}
} else if (getColumnSetNotNullList() != null) {
b.append("COLUMN ");
b.append(PlainSelect.getStringList(columnSetNotNullList));
Expand Down
50 changes: 50 additions & 0 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -2462,6 +2462,38 @@ public class CCJSqlParser extends AbstractJSqlParser<CCJSqlParser> {
}
}

/**
* True when the item after a comma inside a T-SQL/Snowflake ADD list is
* another column definition or table constraint rather than the start of a
* new alter action, which the enclosing productions handle.
*/
private boolean isAlterAddListItemAhead() {
switch (getToken(1).kind) {
case K_CONSTRAINT:
case K_CHECK:
case K_PRIMARY:
case K_UNIQUE:
case K_FOREIGN:
return true;
case K_ADD:
case K_ALTER:
case K_CHANGE:
case K_MODIFY:
case K_DROP:
case K_FORCE:
case K_NO:
case K_ENABLE:
case K_DISABLE:
case K_ALGORITHM:
case K_LOCK:
case K_CONVERT:
case K_PARTITION:
case K_ORDER:
return false;
default:
return true; }
}

/**
* True when the pending {@code ON} opens the ON CONFLICT clause of the enclosing
* INSERT rather than another trailing join condition: after a join, the trailing
Expand Down Expand Up @@ -20568,6 +20600,24 @@ AlterExpression AlterExpressionAddAlterModify():
|
LOOKAHEAD(2) alterExpressionColumnDataType = AlterExpressionColumnDataType()
{ alterExp.addColDataType(alterExpressionColumnDataType); }
// T-SQL and Snowflake let one ADD list several columns and table
// constraints without repeating ADD.
(
LOOKAHEAD(",", { alterExp.getOperation() == AlterOperation.ADD
&& (Dialect.SQLSERVER.name().equals(getAsString(Feature.dialect))
|| Dialect.SNOWFLAKE.name().equals(getAsString(Feature.dialect)))
&& isAlterAddListItemAhead() })
"," { alterExp.setBareAddList(true); }
(
LOOKAHEAD({ getToken(1).kind == K_CONSTRAINT || getToken(1).kind == K_CHECK
|| getToken(1).kind == K_PRIMARY || getToken(1).kind == K_UNIQUE
|| getToken(1).kind == K_FOREIGN })
element=TableConstraint(false) { setAlterTableElement(alterExp, element); }
|
alterExpressionColumnDataType = AlterExpressionColumnDataType()
{ alterExp.addColDataType(alterExpressionColumnDataType); }
)
)*
)
)
|
Expand Down
43 changes: 43 additions & 0 deletions src/test/java/net/sf/jsqlparser/statement/alter/AlterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,49 @@ public void testAlterTableAddColumn_ColumnKeyWordImplicit() throws JSQLParserExc
assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString());
}

@Test
public void testAlterTableAddColumnListTSql() throws JSQLParserException {
// T-SQL and Snowflake let one ADD list several columns without repeating ADD
Alter alter = (Alter) CCJSqlParserUtil.parse(
"ALTER TABLE t ADD a int, b varchar(10) NOT NULL, c int",
parser -> parser.withDialect(Dialect.SQLSERVER));
assertEquals(1, alter.getAlterExpressions().size());
AlterExpression alterExp = alter.getAlterExpressions().get(0);
assertEquals(AlterOperation.ADD, alterExp.getOperation());
List<ColumnDataType> colDataTypes = alterExp.getColDataTypeList();
assertEquals(3, colDataTypes.size());
assertEquals("a", colDataTypes.get(0).getColumnName());
assertEquals("b", colDataTypes.get(1).getColumnName());
assertEquals("varchar (10)", colDataTypes.get(1).getColDataType().toString());
assertEquals("c", colDataTypes.get(2).getColumnName());
assertDeparse(alter, "ALTER TABLE t ADD a int, b varchar (10) NOT NULL, c int");
}

@Test
public void testAlterTableAddColumnListWithConstraintTSql() throws JSQLParserException {
// T-SQL mixes column definitions and table constraints in one ADD list
Alter alter = (Alter) CCJSqlParserUtil.parse(
"ALTER TABLE t ADD a int, CONSTRAINT ck CHECK (a > 0)",
parser -> parser.withDialect(Dialect.SQLSERVER));
assertEquals(1, alter.getAlterExpressions().size());
AlterExpression alterExp = alter.getAlterExpressions().get(0);
assertEquals(AlterOperation.ADD, alterExp.getOperation());
assertEquals(1, alterExp.getColDataTypeList().size());
assertNotNull(alterExp.getConstraint());
}

@Test
public void testAlterTableAddColumnListSnowflake() throws JSQLParserException {
Alter alter = (Alter) CCJSqlParserUtil.parse(
"ALTER TABLE t ADD COLUMN a int, b int",
parser -> parser.withDialect(Dialect.SNOWFLAKE));
assertEquals(1, alter.getAlterExpressions().size());
List<ColumnDataType> colDataTypes =
alter.getAlterExpressions().get(0).getColDataTypeList();
assertEquals(2, colDataTypes.size());
assertDeparse(alter, "ALTER TABLE t ADD COLUMN a int, b int");
}

@Test
public void testAlterTableBackBrackets() throws JSQLParserException {
String sql = "ALTER TABLE tablename add column (field string comment 'aaaaa')";
Expand Down
Loading