Skip to content

Commit 6a7094e

Browse files
authored
Merge pull request #385 from twoquarterrican/alter-table-modify-column-kw-optional
Enhance AlterExpression grammar:
2 parents 068a85b + 5a79964 commit 6a7094e

File tree

4 files changed

+132
-18
lines changed

4 files changed

+132
-18
lines changed

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

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import net.sf.jsqlparser.statement.select.PlainSelect;
2828

2929
import java.util.ArrayList;
30+
import java.util.Collections;
3031
import java.util.List;
3132

3233
/**
@@ -106,10 +107,14 @@ public List<ColumnDataType> getColDataTypeList() {
106107
}
107108

108109
public void addColDataType(String columnName, ColDataType colDataType) {
110+
addColDataType(new ColumnDataType(columnName, colDataType, null));
111+
}
112+
113+
public void addColDataType(ColumnDataType columnDataType) {
109114
if (colDataTypeList == null) {
110115
colDataTypeList = new ArrayList<ColumnDataType>();
111116
}
112-
colDataTypeList.add(new ColumnDataType(columnName, colDataType));
117+
colDataTypeList.add(columnDataType);
113118
}
114119

115120
public List<String> getFkSourceColumns() {
@@ -208,14 +213,16 @@ public String toString() {
208213
return b.toString();
209214
}
210215

211-
public class ColumnDataType {
216+
public static class ColumnDataType {
212217

213218
private final String columnName;
214219
private final ColDataType colDataType;
220+
private final List<String> columnSpecs;
215221

216-
public ColumnDataType(String columnName, ColDataType colDataType) {
222+
public ColumnDataType(String columnName, ColDataType colDataType, List<String> columnSpecs) {
217223
this.columnName = columnName;
218224
this.colDataType = colDataType;
225+
this.columnSpecs = columnSpecs;
219226
}
220227

221228
public String getColumnName() {
@@ -226,9 +233,24 @@ public ColDataType getColDataType() {
226233
return colDataType;
227234
}
228235

236+
public List<String> getColumnSpecs() {
237+
if (columnSpecs == null) {
238+
return Collections.emptyList();
239+
}
240+
return Collections.unmodifiableList(columnSpecs);
241+
}
242+
229243
@Override
230244
public String toString() {
231-
return columnName + " " + colDataType;
245+
return columnName + " " + colDataType + parametersToString();
246+
}
247+
248+
private String parametersToString()
249+
{
250+
if (columnSpecs == null || columnSpecs.isEmpty()) {
251+
return "";
252+
}
253+
return " " + PlainSelect.getStringList(columnSpecs, false, false);
232254
}
233255
}
234256

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@
4444
* @author toben
4545
*/
4646
public enum AlterOperation {
47-
ADD, DROP;
47+
ADD, DROP, MODIFY;
4848
}

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

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
204204
| <K_SIBLINGS:"SIBLINGS">
205205
| <K_ALTER:"ALTER">
206206
| <K_ADD:"ADD">
207+
| <K_MODIFY: "MODIFY">
207208
| <K_COLUMN:"COLUMN">
208209
| <K_NULLS: "NULLS">
209210
| <K_FIRST: "FIRST">
@@ -3054,6 +3055,24 @@ Truncate Truncate():
30543055
}
30553056
}
30563057

3058+
3059+
AlterExpression.ColumnDataType AlterExpressionColumnDataType():
3060+
{
3061+
String columnName = null;
3062+
ColDataType dataType = null;
3063+
List<String> columnSpecs = null;
3064+
List<String> parameter = null;
3065+
}
3066+
{
3067+
columnName = RelObjectName()
3068+
dataType = ColDataType() { columnSpecs = new ArrayList(); }
3069+
( parameter = CreateParameter() { columnSpecs.addAll(parameter); } )*
3070+
{
3071+
return new AlterExpression.ColumnDataType(columnName, dataType, columnSpecs);
3072+
}
3073+
}
3074+
3075+
30573076
AlterExpression AlterExpression():
30583077
{
30593078
AlterExpression alterExp = new AlterExpression();
@@ -3065,23 +3084,20 @@ AlterExpression AlterExpression():
30653084
ForeignKeyIndex fkIndex = null;
30663085
NamedConstraint index = null;
30673086
Table fkTable = null;
3087+
AlterExpression.ColumnDataType alterExpressionColumnDataType = null;
30683088
}
30693089
{
30703090

30713091
(
3072-
(<K_ADD>
3073-
{
3074-
alterExp.setOperation(AlterOperation.ADD);
3075-
}
3092+
((<K_ADD> { alterExp.setOperation(AlterOperation.ADD); } | <K_MODIFY> { alterExp.setOperation(AlterOperation.MODIFY); })
30763093
(
3077-
( <K_COLUMN>
3078-
sk3 = RelObjectName() dataType=ColDataType()
3079-
{ alterExp.addColDataType(sk3, dataType); }
3094+
( (<K_COLUMN>)?
3095+
alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); }
30803096
)
30813097
|
30823098
(
3083-
"(" sk3 = RelObjectName() dataType = ColDataType() { alterExp.addColDataType(sk3, dataType); }
3084-
("," sk3 = RelObjectName() dataType = ColDataType() { alterExp.addColDataType(sk3, dataType); } )* ")"
3099+
"(" alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); }
3100+
("," alterExpressionColumnDataType = AlterExpressionColumnDataType() { alterExp.addColDataType(alterExpressionColumnDataType); } )* ")"
30853101
)
30863102
|
30873103
( <K_PRIMARY> <K_KEY> columnNames=ColumnsNamesList() { alterExp.setPkColumns(columnNames); } )

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

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import java.util.List;
55
import junit.framework.TestCase;
66
import net.sf.jsqlparser.JSQLParserException;
7+
import net.sf.jsqlparser.parser.CCJSqlParser;
78
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
89
import net.sf.jsqlparser.statement.Statement;
910
import net.sf.jsqlparser.statement.alter.Alter;
1011
import net.sf.jsqlparser.statement.alter.AlterExpression;
1112
import net.sf.jsqlparser.statement.alter.AlterExpression.ColumnDataType;
13+
import net.sf.jsqlparser.statement.alter.AlterOperation;
14+
1215
import static net.sf.jsqlparser.test.TestUtils.assertSqlCanBeParsedAndDeparsed;
16+
import static net.sf.jsqlparser.test.TestUtils.assertStatementCanBeDeparsedAs;
1317

1418
public class AlterTest extends TestCase {
1519

@@ -28,8 +32,20 @@ public void testAlterTableAddColumn() throws JSQLParserException {
2832
assertEquals("mycolumn", colDataTypes.get(0).getColumnName());
2933
assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString());
3034
}
31-
32-
public void testAlterTablePrimaryKey() throws JSQLParserException {
35+
36+
public void testAlterTableAddColumn_ColumnKeyWordImplicit() throws JSQLParserException {
37+
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable ADD mycolumn varchar (255)");
38+
assertTrue(stmt instanceof Alter);
39+
Alter alter = (Alter)stmt;
40+
assertEquals("mytable",alter.getTable().getFullyQualifiedName());
41+
AlterExpression alterExp = alter.getAlterExpressions().get(0);
42+
assertNotNull(alterExp);
43+
List<ColumnDataType> colDataTypes = alterExp.getColDataTypeList();
44+
assertEquals("mycolumn", colDataTypes.get(0).getColumnName());
45+
assertEquals("varchar (255)", colDataTypes.get(0).getColDataType().toString());
46+
}
47+
48+
public void testAlterTablePrimaryKey() throws JSQLParserException {
3349
assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals ADD PRIMARY KEY (id)");
3450
}
3551

@@ -74,13 +90,35 @@ public void testAlterTableDropColumn2() throws JSQLParserException {
7490
}
7591

7692
public void testAlterTableDropConstraint() throws JSQLParserException {
77-
assertSqlCanBeParsedAndDeparsed("ALTER TABLE test DROP CONSTRAINT YYY");
93+
final String sql = "ALTER TABLE test DROP CONSTRAINT YYY";
94+
Statement stmt = CCJSqlParserUtil.parse(sql);
95+
assertStatementCanBeDeparsedAs(stmt, sql);
96+
AlterExpression alterExpression = ((Alter) stmt).getAlterExpressions().get(0);
97+
assertEquals(alterExpression.getConstraintName(), "YYY");
7898
}
7999

80100
public void testAlterTablePK() throws JSQLParserException {
81-
assertSqlCanBeParsedAndDeparsed("ALTER TABLE `Author` ADD CONSTRAINT `AuthorPK` PRIMARY KEY (`ID`)");
101+
final String sql = "ALTER TABLE `Author` ADD CONSTRAINT `AuthorPK` PRIMARY KEY (`ID`)";
102+
Statement stmt = CCJSqlParserUtil.parse(sql);
103+
assertStatementCanBeDeparsedAs(stmt, sql);
104+
AlterExpression alterExpression = ((Alter) stmt).getAlterExpressions().get(0);
105+
assertNull(alterExpression.getConstraintName());
106+
// TODO: should this pass? ==> assertEquals(alterExpression.getPkColumns().get(0), "ID");
107+
assertEquals(alterExpression.getIndex().getColumnsNames().get(0), "`ID`");
82108
}
83109

110+
public void testAlterTableFK() throws JSQLParserException {
111+
String sql = "ALTER TABLE `Novels` ADD FOREIGN KEY (AuthorID) REFERENCES Author (ID)";
112+
Statement stmt = CCJSqlParserUtil.parse(sql);
113+
assertStatementCanBeDeparsedAs(stmt, sql);
114+
AlterExpression alterExpression = ((Alter) stmt).getAlterExpressions().get(0);
115+
assertEquals(alterExpression.getFkColumns().size(), 1);
116+
assertEquals(alterExpression.getFkColumns().get(0), "AuthorID");
117+
assertEquals(alterExpression.getFkSourceTable(), "Author");
118+
assertEquals(alterExpression.getFkSourceColumns().size(), 1);
119+
assertEquals(alterExpression.getFkSourceColumns().get(0), "ID");
120+
}
121+
84122
public void testAlterTableCheckConstraint() throws JSQLParserException {
85123
assertSqlCanBeParsedAndDeparsed("ALTER TABLE `Author` ADD CONSTRAINT name_not_empty CHECK (`NAME` <> '')");
86124
}
@@ -109,6 +147,44 @@ public void testAlterTableAddColumn4() throws JSQLParserException {
109147
assertEquals("integer", col2DataTypes.get(0).getColDataType().toString());
110148
}
111149

150+
public void testAlterTableAddColumn5() throws JSQLParserException {
151+
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable ADD col1 timestamp (3)");
152+
153+
// COLUMN keyword appears in deparsed statement
154+
assertStatementCanBeDeparsedAs(stmt, "ALTER TABLE mytable ADD COLUMN col1 timestamp (3)");
155+
156+
Alter alter = (Alter) stmt;
157+
List<AlterExpression> alterExps = alter.getAlterExpressions();
158+
AlterExpression col1Exp = alterExps.get(0);
159+
List<ColumnDataType> col1DataTypes = col1Exp.getColDataTypeList();
160+
assertEquals("col1", col1DataTypes.get(0).getColumnName());
161+
assertEquals("timestamp (3)", col1DataTypes.get(0).getColDataType().toString());
162+
}
163+
164+
public void testAlterTableAddColumn6() throws JSQLParserException {
165+
final String sql = "ALTER TABLE mytable ADD COLUMN col1 timestamp (3) not null";
166+
Statement stmt = CCJSqlParserUtil.parse(sql);
167+
assertStatementCanBeDeparsedAs(stmt, sql);
168+
Alter alter = (Alter) stmt;
169+
List<AlterExpression> alterExps = alter.getAlterExpressions();
170+
AlterExpression col1Exp = alterExps.get(0);
171+
assertEquals("not", col1Exp.getColDataTypeList().get(0).getColumnSpecs().get(0));
172+
assertEquals("null", col1Exp.getColDataTypeList().get(0).getColumnSpecs().get(1));
173+
}
174+
175+
public void testAlterTableModifyColumn1() throws JSQLParserException {
176+
assertSqlCanBeParsedAndDeparsed("ALTER TABLE animals MODIFY (col1 integer, col2 number (8, 2))");
177+
}
178+
179+
public void testAlterTableModifyColumn2() throws JSQLParserException {
180+
Statement stmt = CCJSqlParserUtil.parse("ALTER TABLE mytable modify col1 timestamp (6)");
181+
182+
// COLUMN keyword appears in deparsed statement, modify becomes all caps
183+
assertStatementCanBeDeparsedAs(stmt, "ALTER TABLE mytable MODIFY COLUMN col1 timestamp (6)");
184+
185+
assertEquals(AlterOperation.MODIFY, ((Alter) stmt).getAlterExpressions().get(0).getOperation());
186+
}
187+
112188
public void testAlterTableAddColumnWithZone() throws JSQLParserException {
113189
assertSqlCanBeParsedAndDeparsed("ALTER TABLE mytable ADD COLUMN col1 timestamp with time zone");
114190
assertSqlCanBeParsedAndDeparsed("ALTER TABLE mytable ADD COLUMN col1 timestamp without time zone");

0 commit comments

Comments
 (0)