Skip to content

Commit

Permalink
Enhance AlterExpression grammar:
Browse files Browse the repository at this point in the history
1. optional "COLUMN" keyword in ADD alter operation
2. new alter operation: MODIFY
3. add column specs to alter table column definitions
  • Loading branch information
jthomas committed Jan 19, 2017
1 parent 068a85b commit 241779b
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import net.sf.jsqlparser.statement.select.PlainSelect;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
Expand Down Expand Up @@ -106,10 +107,14 @@ public List<ColumnDataType> getColDataTypeList() {
}

public void addColDataType(String columnName, ColDataType colDataType) {
addColDataType(new ColumnDataType(columnName, colDataType, null));
}

public void addColDataType(ColumnDataType columnDataType) {
if (colDataTypeList == null) {
colDataTypeList = new ArrayList<ColumnDataType>();
}
colDataTypeList.add(new ColumnDataType(columnName, colDataType));
colDataTypeList.add(columnDataType);
}

public List<String> getFkSourceColumns() {
Expand Down Expand Up @@ -208,14 +213,16 @@ public String toString() {
return b.toString();
}

public class ColumnDataType {
public static class ColumnDataType {

private final String columnName;
private final ColDataType colDataType;
private final List<String> columnSpecs;

public ColumnDataType(String columnName, ColDataType colDataType) {
public ColumnDataType(String columnName, ColDataType colDataType, List<String> columnSpecs) {
this.columnName = columnName;
this.colDataType = colDataType;
this.columnSpecs = columnSpecs;
}

public String getColumnName() {
Expand All @@ -226,9 +233,24 @@ public ColDataType getColDataType() {
return colDataType;
}

public List<String> getColumnSpecs() {
if (columnSpecs == null) {
return Collections.emptyList();
}
return Collections.unmodifiableList(columnSpecs);
}

@Override
public String toString() {
return columnName + " " + colDataType;
return columnName + " " + colDataType + parametersToString();
}

private String parametersToString()
{
if (columnSpecs == null || columnSpecs.isEmpty()) {
return "";
}
return " " + PlainSelect.getStringList(columnSpecs, false, false);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@
* @author toben
*/
public enum AlterOperation {
ADD, DROP;
ADD, DROP, MODIFY;
}
34 changes: 25 additions & 9 deletions src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
| <K_SIBLINGS:"SIBLINGS">
| <K_ALTER:"ALTER">
| <K_ADD:"ADD">
| <K_MODIFY: "MODIFY">
| <K_COLUMN:"COLUMN">
| <K_NULLS: "NULLS">
| <K_FIRST: "FIRST">
Expand Down Expand Up @@ -3054,6 +3055,24 @@ Truncate Truncate():
}
}


AlterExpression.ColumnDataType AlterExpressionColumnDataType():
{
String columnName = null;
ColDataType dataType = null;
List<String> columnSpecs = null;
List<String> parameter = null;
}
{
columnName = RelObjectName()
dataType = ColDataType() { columnSpecs = new ArrayList(); }
( parameter = CreateParameter() { columnSpecs.addAll(parameter); } )*
{
return new AlterExpression.ColumnDataType(columnName, dataType, columnSpecs);
}
}


AlterExpression AlterExpression():
{
AlterExpression alterExp = new AlterExpression();
Expand All @@ -3065,23 +3084,20 @@ AlterExpression AlterExpression():
ForeignKeyIndex fkIndex = null;
NamedConstraint index = null;
Table fkTable = null;
AlterExpression.ColumnDataType alterExpressionColumnDataType = null;
}
{

(
(<K_ADD>
{
alterExp.setOperation(AlterOperation.ADD);
}
((<K_ADD> { alterExp.setOperation(AlterOperation.ADD); } | <K_MODIFY> { alterExp.setOperation(AlterOperation.MODIFY); })
(
( <K_COLUMN>
sk3 = RelObjectName() dataType=ColDataType()
{ alterExp.addColDataType(sk3, dataType); }
( (<K_COLUMN>)*
alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); }
)
|
(
"(" sk3 = RelObjectName() dataType = ColDataType() { alterExp.addColDataType(sk3, dataType); }
("," sk3 = RelObjectName() dataType = ColDataType() { alterExp.addColDataType(sk3, dataType); } )* ")"
"(" alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); }
("," alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } )* ")"
)
|
( <K_PRIMARY> <K_KEY> columnNames=ColumnsNamesList() { alterExp.setPkColumns(columnNames); } )
Expand Down
53 changes: 51 additions & 2 deletions src/test/java/net/sf/jsqlparser/test/alter/AlterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import net.sf.jsqlparser.statement.alter.AlterExpression;
import net.sf.jsqlparser.statement.alter.AlterExpression.ColumnDataType;
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs;

public class AlterTest extends TestCase {

Expand All @@ -28,8 +29,20 @@ public void testAlterTableAddColumn() throws JSQLParserException {
assertEquals("mycolumn", colDataTypes.get(0).getColumnName());
assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString());
}

public void testAlterTablePrimaryKey() throws JSQLParserException {

public void testAlterTableAddColumn_ColumnKeyWordImplicit() throws JSQLParserException {
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable ADD mycolumn varchar (255)");
assertTrue(stmt instanceof Alter);
Alter alter = (Alter)stmt;
assertEquals("mytable",alter.getTable().getFullyQualifiedName());
AlterExpression alterExp = alter.getAlterExpressions().get(0);
assertNotNull(alterExp);
List<ColumnDataType> colDataTypes = alterExp.getColDataTypeList();
assertEquals("mycolumn", colDataTypes.get(0).getColumnName());
assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString());
}

public void testAlterTablePrimaryKey() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals ADD PRIMARY KEY (id)");
}

Expand Down Expand Up @@ -109,6 +122,42 @@ public void testAlterTableAddColumn4() throws JSQLParserException {
assertEquals("integer", col2DataTypes.get(0).getColDataType().toString());
}

public void testAlterTableAddColumn5() throws JSQLParserException {
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable ADD col1 timestamp (3)");

// COLUMN keyword appears in deparsed statement
assertStatementCanBeDeparsedAs(stmt, "ALTER TABLE mytable ADD COLUMN col1 timestamp (3)");

Alter alter = (Alter) stmt;
List<AlterExpression> alterExps = alter.getAlterExpressions();
AlterExpression col1Exp = alterExps.get(0);
List<ColumnDataType> col1DataTypes = col1Exp.getColDataTypeList();
assertEquals("col1", col1DataTypes.get(0).getColumnName());
assertEquals("timestamp (3)", col1DataTypes.get(0).getColDataType().toString());
}

public void testAlterTableAddColumn6() throws JSQLParserException {
final String sql = "ALTER TABLE mytable ADD COLUMN col1 timestamp (3) not null";
Statement stmt = CCJSqlParserUtil.parse(sql);
assertStatementCanBeDeparsedAs(stmt, sql);
Alter alter = (Alter) stmt;
List<AlterExpression> alterExps = alter.getAlterExpressions();
AlterExpression col1Exp = alterExps.get(0);
assertEquals("not", col1Exp.getColDataTypeList().get(0).getColumnSpecs().get(0));
assertEquals("null", col1Exp.getColDataTypeList().get(0).getColumnSpecs().get(1));
}

public void testAlterTableModifyColumn1() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals MODIFY (col1 integer, col2 number (8, 2))");
}

public void testAlterTableModifyColumn2() throws JSQLParserException {
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable modify col1 timestamp (6)");

// COLUMN keyword appears in deparsed statement, modify becomes all caps
assertStatementCanBeDeparsedAs(stmt, "ALTER TABLE mytable MODIFY COLUMN col1 timestamp (6)");
}

public void testAlterTableAddColumnWithZone() throws JSQLParserException {
assertSqlCanBeParsedAndDeparsed("ALTER TABLE mytable ADD COLUMN col1 timestamp with time zone");
assertSqlCanBeParsedAndDeparsed("ALTER TABLE mytable ADD COLUMN col1 timestamp without time zone");
Expand Down

0 comments on commit 241779b

Please sign in to comment.