diff --git a/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java b/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java index b2d42026b..556977680 100644 --- a/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java +++ b/src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java @@ -32,6 +32,8 @@ public class ForeignKeyIndex extends NamedConstraint { private Table table; private List referencedColumnNames; + private String onDeleteReferenceOption; + private String onUpdateReferenceOption; public Table getTable() { return table; @@ -49,9 +51,33 @@ public void setReferencedColumnNames(List referencedColumnNames) { this.referencedColumnNames = referencedColumnNames; } + public String getOnDeleteReferenceOption() { + return onDeleteReferenceOption; + } + + public void setOnDeleteReferenceOption(String onDeleteReferenceOption) { + this.onDeleteReferenceOption = onDeleteReferenceOption; + } + + public String getOnUpdateReferenceOption() { + return onUpdateReferenceOption; + } + + public void setOnUpdateReferenceOption(String onUpdateReferenceOption) { + this.onUpdateReferenceOption = onUpdateReferenceOption; + } + @Override public String toString() { + String referenceOptions = ""; + if(onDeleteReferenceOption != null) { + referenceOptions += " ON DELETE " + onDeleteReferenceOption; + } + if(onUpdateReferenceOption != null) { + referenceOptions += " ON UPDATE " + onUpdateReferenceOption; + } return super.toString() - + " REFERENCES " + table + PlainSelect.getStringList(getReferencedColumnNames(), true, true); + + " REFERENCES " + table + PlainSelect.getStringList(getReferencedColumnNames(), true, true) + + referenceOptions; } } diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index a8a03dbb3..0c41622dc 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -166,6 +166,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -199,13 +200,13 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | -| +| | | | -| -| -| +| +| +| | | | @@ -227,6 +228,7 @@ TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */ | | | +| | | | @@ -263,14 +265,14 @@ TOKEN: | < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])+ "\"" | ("`" (~["\n","\r","`"])+ "`") | ( "[" ~["0"-"9","]"] (~["\n","\r","]"])* "]" ) > } -Statement Statement() #Statement: -{ Statement stm; } +Statement Statement() #Statement: +{ Statement stm; } { stm = SingleStatement() [";"] - { - return stm; + { + return stm; } } @@ -312,7 +314,7 @@ Statement SingleStatement() : { return stm; } } -Statements Statements() #Statements : +Statements Statements() #Statements : { Statements stmts = new Statements(); List list = new ArrayList(); Statement stm; } @@ -358,9 +360,9 @@ Update Update(): boolean useColumnsBrackets = false; } { - table=TableWithAlias() { tables.add(table); } + table=TableWithAlias() { tables.add(table); } ("," table=TableWithAlias() { tables.add(table); } )* - + ( LOOKAHEAD(3) tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); } ("," tableColumn=Column() "=" value=SimpleExpression() { columns.add(tableColumn); expList.add(value); } )* @@ -579,19 +581,19 @@ Statement Merge() : { } { table=TableWithAlias() { merge.setTable(table); } - "(" - ( table=Table() { merge.setUsingTable(table); } + "(" + ( table=Table() { merge.setUsingTable(table); } | select=SubSelect() { merge.setUsingSelect(select); } ) - ")" [ alias = Alias() { merge.setUsingAlias(alias); } ] + ")" [ alias = Alias() { merge.setUsingAlias(alias); } ] "(" condition = Condition() { merge.setOnCondition(condition); } ")" [ LOOKAHEAD(2) update = MergeUpdateClause() { merge.setMergeUpdate(update); } ] - + [ insert = MergeInsertClause() { merge.setMergeInsert(insert); } ] - + { return merge; } } - + MergeUpdate MergeUpdateClause() : { MergeUpdate mu = new MergeUpdate(); List columns = new ArrayList(); @@ -601,11 +603,11 @@ MergeUpdate MergeUpdateClause() : { Expression condition; } { - - - col = Column() "=" exp = SimpleExpression() - { columns.add(col); expList.add(exp); } - ("," col = Column() "=" exp = SimpleExpression() { columns.add(col); expList.add(exp); } )* + + + col = Column() "=" exp = SimpleExpression() + { columns.add(col); expList.add(exp); } + ("," col = Column() "=" exp = SimpleExpression() { columns.add(col); expList.add(exp); } )* { mu.setColumns(columns); mu.setValues(expList); } @@ -623,9 +625,9 @@ MergeInsert MergeInsertClause() : { Expression exp; } { - - "(" col=Column() { columns.add(col); } ("," col=Column() { columns.add(col); } )* ")" - "(" exp=SimpleExpression() { expList.add(exp); } ("," exp=SimpleExpression() { expList.add(exp); } )* ")" + + "(" col=Column() { columns.add(col); } ("," col=Column() { columns.add(col); } )* ")" + "(" exp=SimpleExpression() { expList.add(exp); } ("," exp=SimpleExpression() { expList.add(exp); } )* ")" { mi.setColumns(columns); mi.setValues(expList); @@ -659,8 +661,8 @@ String RelObjectName() : { Token tk = null; } { (tk= | tk= - | tk= | tk= | tk= | tk= | tk= - | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= + | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= | tk= @@ -675,7 +677,7 @@ Extended usage of object names. String RelObjectNameExt(): { Token tk = null; String result=null; -} +} { ( result=RelObjectName() | tk= | tk= | tk= ) { @@ -801,7 +803,7 @@ PlainSelect PlainSelect(): [LOOKAHEAD() offset = Offset() { plainSelect.setOffset(offset); } ] [LOOKAHEAD() fetch = Fetch() { plainSelect.setFetch(fetch); } ] - [ { plainSelect.setForUpdate(true); } + [ { plainSelect.setForUpdate(true); } [ updateTable = Table() { plainSelect.setForUpdateTable(updateTable); } ] ] { @@ -908,7 +910,7 @@ SelectItem SelectItem(): | LOOKAHEAD(AllTableColumns()) selectItem=AllTableColumns() | - LOOKAHEAD(SelectExpressionItem()) selectItem=SelectExpressionItem() + LOOKAHEAD(SelectExpressionItem()) selectItem=SelectExpressionItem() ) { return selectItem; @@ -1207,22 +1209,22 @@ Join JoinerExpression(): List columns = null; } { - [ + [ ( { join.setLeft(true); } | { join.setRight(true); } - | { join.setFull(true); } + | { join.setFull(true); } ) [ { join.setOuter(true); } ] | { join.setInner(true); } | { join.setNatural(true); } - | { join.setCross(true); } + | { join.setCross(true); } ] - ( | "," { join.setSimple(true); } ) + ( | "," { join.setSimple(true); } ) right=FromItem() - [ + [ LOOKAHEAD(2) (( onExpression=Expression() { join.setOnExpression(onExpression); } ) | ( "(" tableColumn=Column() { columns = new ArrayList(); columns.add(tableColumn); } @@ -1231,7 +1233,7 @@ Join JoinerExpression(): ] { join.setRightItem(right); - return join; + return join; } } @@ -1256,8 +1258,8 @@ OracleHierarchicalExpression OracleHierarchicalQueryClause(): { result.setConnectExpression(expr); } | [ { result.setNoCycle(true); } ] expr=AndExpression() - { - result.setConnectExpression(expr); + { + result.setConnectExpression(expr); result.setConnectFirst(true); } [ expr=AndExpression() {result.setStartExpression(expr);} ] @@ -1312,9 +1314,9 @@ OrderByElement OrderByElement(): { columnReference = SimpleExpression() [ ( | ( { orderByElement.setAsc(false); } )) { orderByElement.setAscDescPresent(true); } ] - [ ( - { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_FIRST); } | - { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_LAST); } + [ ( + { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_FIRST); } | + { orderByElement.setNullOrdering(OrderByElement.NullOrdering.NULLS_LAST); } )? ] { @@ -1408,7 +1410,7 @@ Fetch Fetch(): ( { fetch.setFetchParamFirst(true); } | ) (token= { fetch.setRowCount(Long.parseLong(token.image)); } | "?" { fetch.setFetchJdbcParameter(true); } ) - ( { fetch.setFetchParam("ROWS"); } | ) + ( { fetch.setFetchParam("ROWS"); } | ) ) @@ -1435,7 +1437,7 @@ Top Top(): | "?" { top.setRowCountJdbcParameter(true);} ) { top.setParenthesis(true);} ")" - ) [ LOOKAHEAD(2) { top.setPercentage(true); } ] + ) [ LOOKAHEAD(2) { top.setPercentage(true); } ] { return top; } @@ -1613,7 +1615,7 @@ Expression RegularCondition(): | "!~*" { result = new RegExpMatchOperator(RegExpMatchOperatorType.NOT_MATCH_CASEINSENSITIVE); } ) - ( LOOKAHEAD(2) rightExpression=ComparisonItem() { oraclePrior = EqualsTo.ORACLE_PRIOR_END; } + ( LOOKAHEAD(2) rightExpression=ComparisonItem() { oraclePrior = EqualsTo.ORACLE_PRIOR_END; } | rightExpression=ComparisonItem() ) [ "(" "+" ")" { oracleJoin=EqualsTo.ORACLE_JOIN_LEFT; } ] @@ -1822,7 +1824,7 @@ Expression AnyComparisonExpression() : SubSelect subselect = null; } { - ( { anyType = AnyType.ANY; } | { anyType = AnyType.SOME; } ) + ( { anyType = AnyType.ANY; } | { anyType = AnyType.SOME; } ) "(" subselect=SubSelect() ")" { retval = new AnyComparisonExpression(anyType, subselect); } { return retval; @@ -2076,10 +2078,10 @@ UserVariable UserVariable() : { } { ("@" | "@@" { var.setDoubleAdd(true);} ) - token= - { - var.setName(token.image); - return var; + token= + { + var.setName(token.image); + return var; } } @@ -2088,10 +2090,10 @@ NumericBind NumericBind() : { Token token; } { - ":" token= - { - var.setBindId(Integer.valueOf(token.image)); - return var; + ":" token= + { + var.setBindId(Integer.valueOf(token.image)); + return var; } } @@ -2102,9 +2104,9 @@ JsonExpression JsonExpression() : { } { column=Column() ("->" token= {result.addIdent(token.image);} )+ - { + { result.setColumn(column); - return result; + return result; } } @@ -2113,7 +2115,7 @@ IntervalExpression IntervalExpression() : { Token token; } { - (token= | token= | token=) + (token= | token= | token=) { interval.setParameter(token.image); } [ LOOKAHEAD(2) token = { interval.setIntervalType(token.image); } ] { @@ -2129,15 +2131,15 @@ WithinGroupExpression WithinGroupExpression() : ExpressionList exprList; } { - token = "(" exprList = SimpleExpressionList() ")" + token = "(" exprList = SimpleExpressionList() ")" "(" orderByElements = OrderByElements() ")" - { + { result.setName(token.image); result.setExprList(exprList); result.setOrderByElements(orderByElements); - return result; + return result; } } @@ -2171,14 +2173,14 @@ AnalyticExpression AnalyticExpression() : } { token= { retval.setName(token.image); } - "(" [ expr=SimpleExpression() ["," offset=SimpleExpression() ["," defaultValue=SimpleExpression() ]] | "*" { retval.setAllColumns(true); } ] ")" + "(" [ expr=SimpleExpression() ["," offset=SimpleExpression() ["," defaultValue=SimpleExpression() ]] | "*" { retval.setAllColumns(true); } ] ")" [ keep=KeepExpression() ] "(" [ expressionList=SimpleExpressionList() ] [olist=OrderByElements() [windowElement = WindowElement() ] ] - + { retval.setExpression(expr); retval.setOffset(offset); @@ -2203,14 +2205,14 @@ WindowElement WindowElement(): { ( { windowElement.setType(WindowElement.Type.ROWS); } | { windowElement.setType(WindowElement.Type.RANGE); } ) ( ( - { windowElement.setRange(range); } - offset = WindowOffset() { range.setStart(offset); } + { windowElement.setRange(range); } + offset = WindowOffset() { range.setStart(offset); } offset = WindowOffset() { range.setEnd(offset); } ) - | - offset = WindowOffset() { windowElement.setOffset(offset); } + | + offset = WindowOffset() { windowElement.setOffset(offset); } ) - + { return windowElement; } @@ -2223,24 +2225,24 @@ WindowOffset WindowOffset(): } { ( - + ( { offset.setType(WindowOffset.Type.PRECEDING); return offset; } | { offset.setType(WindowOffset.Type.FOLLOWING); return offset; } ) - ) + ) | - ( { offset.setType(WindowOffset.Type.CURRENT); return offset;} ) + ( { offset.setType(WindowOffset.Type.CURRENT); return offset;} ) | ( expr = SimpleExpression() { - offset.setType(WindowOffset.Type.EXPR); - offset.setExpression(expr); - } + offset.setType(WindowOffset.Type.EXPR); + offset.setExpression(expr); + } ( { offset.setType(WindowOffset.Type.PRECEDING); } | { offset.setType(WindowOffset.Type.FOLLOWING); } ) ) - + { return offset; } -} +} ExtractExpression ExtractExpression() : { @@ -2363,9 +2365,9 @@ Execute Execute(): { [ expressionList=SimpleExpressionList() ] - { + { execute.setExprList(expressionList); - return execute; + return execute; } } @@ -2405,15 +2407,15 @@ MySQLGroupConcat MySQLGroupConcat():{ Token t; } { - "(" - [ { retval.setDistinct(true); } ] - expressionList = SimpleExpressionList() + "(" + [ { retval.setDistinct(true); } ] + expressionList = SimpleExpressionList() [ orderByList = OrderByElements() { retval.setOrderByElements(orderByList); } ] [ t= { retval.setSeparator(t.image); } ] ")" - { + { retval.setExpressionList(expressionList); - return retval; + return retval; } } @@ -2531,7 +2533,7 @@ CreateTable CreateTable(): [ { createTable.setUnlogged(true); } ] (parameter = CreateParameter() { createOptions.add(parameter); })* - + [ { createTable.setIfNotExists(true); }] table=Table() [ @@ -2576,20 +2578,20 @@ CreateTable CreateTable(): index = new NamedConstraint(); } [ sk3=RelObjectName() {index.setName(sk3);} ] - + (tk= tk2= {index.setType(tk.image + " " + tk2.image);} | tk= [ tk2= ] {index.setType(tk.image + (tk2!=null?" " + tk2.image:""));} ) colNames=ColumnsNamesList() { - + index.setColumnsNames(colNames); indexes.add(index); } ) | LOOKAHEAD(3) ( {tk=null;} - [ tk= ] tk2= + [ tk= ] [ tk= ] tk2= sk3=RelObjectName() colNames=ColumnsNamesList() { @@ -2618,6 +2620,8 @@ CreateTable CreateTable(): fkIndex.setReferencedColumnNames(colNames); indexes.add(fkIndex); } + [LOOKAHEAD(2) ( ( {fkIndex.setOnDeleteReferenceOption("CASCADE");}| {fkIndex.setOnDeleteReferenceOption("NO ACTION");}))] + [LOOKAHEAD(2) ( ( {fkIndex.setOnUpdateReferenceOption("CASCADE");}| {fkIndex.setOnUpdateReferenceOption("NO ACTION");}))] ) | ( @@ -2741,17 +2745,17 @@ String CreateParameter(): tk= { retval += tk.image; } ) | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | - tk= { retval = tk.image; } + tk= { retval = tk.image; } | tk= { retval = tk.image; } | @@ -2853,7 +2857,7 @@ Alter Alter(): Token alterDrop = null; } { - table=Table() { alter.setTable(table); } + table=Table() { alter.setTable(table); } ( (alterDrop = { @@ -2874,7 +2878,7 @@ Alter Alter(): | //following two choices regarding foreign keys should be merged ( columnNames=ColumnsNamesList() { alter.setFkColumns(columnNames); } - tk= columnNames=ColumnsNamesList() + tk= columnNames=ColumnsNamesList() { alter.setFkSourceTable(tk.image); alter.setFkSourceColumns(columnNames); } [ ( { alter.setOnDeleteCascade(true); } diff --git a/src/test/java/net/sf/jsqlparser/test/create/CreateTableTest.java b/src/test/java/net/sf/jsqlparser/test/create/CreateTableTest.java index b88f663f5..3f6863d34 100644 --- a/src/test/java/net/sf/jsqlparser/test/create/CreateTableTest.java +++ b/src/test/java/net/sf/jsqlparser/test/create/CreateTableTest.java @@ -169,16 +169,28 @@ public void testCreateTableColumnValue() throws JSQLParserException { } public void testCreateTableForeignKey5() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY AUTO_INCREMENT, aid INTEGER REFERENCES accounts ON aid ON DELETE CASCADE, name STRING, lastname STRING)"); - } - - public void testCreateTableForeignKey6() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE test (id long, fkey long references another_table (id))"); - } + assertSqlCanBeParsedAndDeparsed("CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY AUTO_INCREMENT, aid INTEGER REFERENCES accounts ON aid ON DELETE CASCADE, name STRING, lastname STRING)"); + } - public void testCreateTableMySqlOnUpdateCurrentTimestamp() throws JSQLParserException { - assertSqlCanBeParsedAndDeparsed("CREATE TABLE test (applied timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)"); - } + public void testCreateTableForeignKey6() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE TABLE test (id long, fkey long references another_table (id))"); + } + + public void testMySqlCreateTableOnUpdateCurrentTimestamp() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE TABLE test (applied timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)"); + } + + public void testMySqlCreateTableWithConstraintWithCascade() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE TABLE table1 (id INT (10) UNSIGNED NOT NULL AUTO_INCREMENT, t2_id INT (10) UNSIGNED DEFAULT NULL, t3_id INT (10) UNSIGNED DEFAULT NULL, t4_id INT (10) UNSIGNED NOT NULL, PRIMARY KEY (id), KEY fkc_table1_t4 (t4_id), KEY fkc_table1_t2 (t2_id), KEY fkc_table1_t3 (t3_id), CONSTRAINT fkc_table1_t2 FOREIGN KEY (t2_id) REFERENCES table_two(t2o_id) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fkc_table1_t3 FOREIGN KEY (t3_id) REFERENCES table_three(t3o_id) ON UPDATE CASCADE, CONSTRAINT fkc_table1_t4 FOREIGN KEY (t4_id) REFERENCES table_four(t4o_id) ON DELETE CASCADE) ENGINE = InnoDB AUTO_INCREMENT = 8761 DEFAULT CHARSET = utf8"); + } + + public void testMySqlCreateTableWithConstraintWithNoAction() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE TABLE table1 (id INT (10) UNSIGNED NOT NULL AUTO_INCREMENT, t2_id INT (10) UNSIGNED DEFAULT NULL, t3_id INT (10) UNSIGNED DEFAULT NULL, t4_id INT (10) UNSIGNED NOT NULL, PRIMARY KEY (id), KEY fkc_table1_t4 (t4_id), KEY fkc_table1_t2 (t2_id), KEY fkc_table1_t3 (t3_id), CONSTRAINT fkc_table1_t2 FOREIGN KEY (t2_id) REFERENCES table_two(t2o_id) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT fkc_table1_t3 FOREIGN KEY (t3_id) REFERENCES table_three(t3o_id) ON UPDATE NO ACTION, CONSTRAINT fkc_table1_t4 FOREIGN KEY (t4_id) REFERENCES table_four(t4o_id) ON DELETE NO ACTION) ENGINE = InnoDB AUTO_INCREMENT = 8761 DEFAULT CHARSET = utf8"); + } + + public void testMySqlCreateTableWithTextIndexes() throws JSQLParserException { + assertSqlCanBeParsedAndDeparsed("CREATE TABLE table2 (id INT (10) UNSIGNED NOT NULL AUTO_INCREMENT, name TEXT, url TEXT, created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), FULLTEXT KEY idx_table2_name (name)) ENGINE = InnoDB AUTO_INCREMENT = 7334 DEFAULT CHARSET = utf8"); + } public void testRUBiSCreateList() throws Exception { BufferedReader in = new BufferedReader(new InputStreamReader(CreateTableTest.class.getResourceAsStream("/RUBiS-create-requests.txt")));