Skip to content

Commit 1e88dd5

Browse files
authored
Support Foreign Key ON UPDATE CASCADE (#1025)
* #985 * add 2 unit-tests for given statements #985 * fix formating (line width) #985 * * fix nullpointerexceptions * add more unittest-assertions #985 * change order to match the same order as in ForeignKeyIndex * byAction should not throw an exception (is used by deprecated string-setters) * add unit-tests for ReferentialAction within AlterExpression * fix toString (added bug on refactoring) * javadoc * test set from get on null-values too * refactoring: add and use ReferentialAction() to evaluate enum #985 * refactoring: fix parser that order of referential actions does not matter #985 * add empty constructor
1 parent 685f6fe commit 1e88dd5

File tree

5 files changed

+564
-76
lines changed

5 files changed

+564
-76
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2020 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
package net.sf.jsqlparser.statement;
11+
12+
public class ReferentialAction {
13+
14+
private Type type;
15+
private Action action;
16+
17+
public ReferentialAction() {
18+
// default constructor
19+
}
20+
21+
public ReferentialAction(Type type, Action action) {
22+
this.type = type;
23+
this.action = action;
24+
}
25+
26+
public Type getType() {
27+
return type;
28+
}
29+
30+
public void setType(Type type) {
31+
this.type = type;
32+
}
33+
34+
public Action getAction() {
35+
return action;
36+
}
37+
38+
public void setAction(Action action) {
39+
this.action = action;
40+
}
41+
42+
@Override
43+
public int hashCode() {
44+
final int prime = 31;
45+
int result = 1;
46+
result = prime * result + ((action == null) ? 0 : action.hashCode());
47+
result = prime * result + ((type == null) ? 0 : type.hashCode());
48+
return result;
49+
}
50+
51+
@Override
52+
public String toString() {
53+
return new StringBuilder(" ON ").append(getType().name()).append(" ").append(getAction().getAction())
54+
.toString();
55+
}
56+
57+
@Override
58+
public boolean equals(Object obj) {
59+
if (this == obj) {
60+
return true;
61+
}
62+
if (obj == null) {
63+
return false;
64+
}
65+
if (getClass() != obj.getClass()) {
66+
return false;
67+
}
68+
ReferentialAction other = (ReferentialAction) obj;
69+
if (action != other.action) {
70+
return false;
71+
}
72+
if (type != other.type) {
73+
return false;
74+
}
75+
return true;
76+
}
77+
78+
public enum Type {
79+
DELETE,
80+
UPDATE
81+
}
82+
83+
public enum Action {
84+
CASCADE("CASCADE"),
85+
RESTRICT("RESTRICT"),
86+
NO_ACTION("NO ACTION"),
87+
SET_DEFAULT("SET DEFAULT"),
88+
SET_NULL("SET NULL");
89+
90+
private Action(String action) {
91+
this.action = action;
92+
}
93+
94+
private String action;
95+
96+
/**
97+
* @param action
98+
* @return the {@link Action}, if found, otherwise <code>null</code>
99+
*/
100+
public static Action byAction(String action) {
101+
for (Action a : values()) {
102+
if (a.getAction().equals(action)) {
103+
return a;
104+
}
105+
}
106+
return null;
107+
}
108+
109+
public String getAction() {
110+
return action;
111+
}
112+
113+
@Override
114+
public String toString() {
115+
return action;
116+
}
117+
}
118+
119+
}

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

Lines changed: 92 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111

1212
import java.util.ArrayList;
1313
import java.util.Arrays;
14+
import java.util.LinkedHashSet;
1415
import java.util.List;
16+
import java.util.Set;
17+
18+
import net.sf.jsqlparser.statement.ReferentialAction;
19+
import net.sf.jsqlparser.statement.ReferentialAction.Action;
20+
import net.sf.jsqlparser.statement.ReferentialAction.Type;
1521
import net.sf.jsqlparser.statement.create.table.ColDataType;
1622
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
1723
import net.sf.jsqlparser.statement.create.table.Index;
@@ -23,7 +29,7 @@ public class AlterExpression {
2329
private String optionalSpecifier;
2430
private String columnName;
2531
private String columnOldName;
26-
//private ColDataType dataType;
32+
// private ColDataType dataType;
2733

2834
private List<ColumnDataType> colDataTypeList;
2935
private List<ColumnDropNotNull> columnDropNotNullList;
@@ -34,9 +40,9 @@ public class AlterExpression {
3440
private Index index = null;
3541
private String constraintName;
3642
private boolean constraintIfExists;
37-
private boolean onDeleteRestrict;
38-
private boolean onDeleteSetNull;
39-
private boolean onDeleteCascade;
43+
44+
private Set<ReferentialAction> referentialActions = new LinkedHashSet<>(2);
45+
4046
private List<String> fkColumns;
4147
private String fkSourceTable;
4248
private List<String> fkSourceColumns;
@@ -71,28 +77,96 @@ public void setOptionalSpecifier(String optionalSpecifier) {
7177
this.optionalSpecifier = optionalSpecifier;
7278
}
7379

80+
/**
81+
* @param type
82+
* @param action
83+
*/
84+
public void setReferentialAction(Type type, Action action) {
85+
setReferentialAction(type, action, true);
86+
}
87+
88+
/**
89+
* @param type
90+
*/
91+
public void removeReferentialAction(Type type) {
92+
setReferentialAction(type, null, false);
93+
}
94+
95+
/**
96+
* @param type
97+
* @return
98+
*/
99+
public ReferentialAction getReferentialAction(Type type) {
100+
return referentialActions.stream().filter(ra -> type.equals(ra.getType())).findFirst().orElse(null);
101+
}
102+
103+
private void setReferentialAction(Type type, Action action, boolean set) {
104+
ReferentialAction found = getReferentialAction(type);
105+
if (set) {
106+
if (found == null) {
107+
referentialActions.add(new ReferentialAction(type, action));
108+
} else {
109+
found.setAction(action);
110+
}
111+
} else if (found != null) {
112+
referentialActions.remove(found);
113+
}
114+
}
115+
/**
116+
* @return
117+
* @deprecated use {@link #getOnDeleteReferentialAction()}
118+
*/
119+
@Deprecated
74120
public boolean isOnDeleteCascade() {
75-
return onDeleteCascade;
121+
ReferentialAction found = getReferentialAction(Type.DELETE);
122+
return found != null && Action.CASCADE.equals(found.getAction());
76123
}
77124

125+
/**
126+
* @return
127+
* @deprecated use {@link #setOnDeleteReferentialAction(Action)
128+
*/
129+
@Deprecated
78130
public void setOnDeleteCascade(boolean onDeleteCascade) {
79-
this.onDeleteCascade = onDeleteCascade;
131+
setReferentialAction(Type.DELETE, Action.CASCADE, onDeleteCascade);
80132
}
81133

134+
/**
135+
* @return
136+
* @deprecated use {@link #getOnDeleteReferentialAction()}
137+
*/
138+
@Deprecated
82139
public boolean isOnDeleteRestrict() {
83-
return onDeleteRestrict;
140+
ReferentialAction found = getReferentialAction(Type.DELETE);
141+
return found != null && Action.RESTRICT.equals(found.getAction());
84142
}
85143

144+
/**
145+
* @return
146+
* @deprecated use {@link #setOnDeleteReferentialAction(Action)
147+
*/
148+
@Deprecated
86149
public void setOnDeleteRestrict(boolean onDeleteRestrict) {
87-
this.onDeleteRestrict = onDeleteRestrict;
150+
setReferentialAction(Type.DELETE, Action.RESTRICT, onDeleteRestrict);
88151
}
89152

153+
/**
154+
* @return
155+
* @deprecated use {@link #getOnDeleteReferentialAction()}
156+
*/
157+
@Deprecated
90158
public boolean isOnDeleteSetNull() {
91-
return onDeleteSetNull;
159+
ReferentialAction found = getReferentialAction(Type.DELETE);
160+
return found != null && Action.SET_NULL.equals(found.getAction());
92161
}
93162

163+
/**
164+
* @return
165+
* @deprecated use {@link #setOnDeleteReferentialAction(Action)
166+
*/
167+
@Deprecated
94168
public void setOnDeleteSetNull(boolean onDeleteSetNull) {
95-
this.onDeleteSetNull = onDeleteSetNull;
169+
setReferentialAction(Type.DELETE, Action.SET_NULL, onDeleteSetNull);
96170
}
97171

98172
public List<String> getFkColumns() {
@@ -121,14 +195,14 @@ public void addColDataType(String columnName, ColDataType colDataType) {
121195

122196
public void addColDataType(ColumnDataType columnDataType) {
123197
if (colDataTypeList == null) {
124-
colDataTypeList = new ArrayList<ColumnDataType>();
198+
colDataTypeList = new ArrayList<>();
125199
}
126200
colDataTypeList.add(columnDataType);
127201
}
128202

129203
public void addColDropNotNull(ColumnDropNotNull columnDropNotNull) {
130204
if (columnDropNotNullList == null) {
131-
columnDropNotNullList = new ArrayList<ColumnDropNotNull>();
205+
columnDropNotNullList = new ArrayList<>();
132206
}
133207
columnDropNotNullList.add(columnDropNotNull);
134208
}
@@ -219,7 +293,7 @@ public List<ColumnDropNotNull> getColumnDropNotNullList() {
219293

220294
public void addParameters(String... params) {
221295
if (parameters == null) {
222-
parameters = new ArrayList<String>();
296+
parameters = new ArrayList<>();
223297
}
224298
parameters.addAll(Arrays.asList(params));
225299
}
@@ -312,16 +386,11 @@ public String toString() {
312386
}
313387
b.append(" (").append(PlainSelect.getStringList(ukColumns)).append(")");
314388
} else if (fkColumns != null) {
315-
b.append("FOREIGN KEY (").append(PlainSelect.getStringList(fkColumns)).
316-
append(") REFERENCES ").append(fkSourceTable).append(" (").append(
317-
PlainSelect.getStringList(fkSourceColumns)).append(")");
318-
if (isOnDeleteCascade()) {
319-
b.append(" ON DELETE CASCADE");
320-
} else if (isOnDeleteRestrict()) {
321-
b.append(" ON DELETE RESTRICT");
322-
} else if (isOnDeleteSetNull()) {
323-
b.append(" ON DELETE SET NULL");
324-
}
389+
b.append("FOREIGN KEY (").append(PlainSelect.getStringList(fkColumns)).append(") REFERENCES ")
390+
.append(fkSourceTable).append(" (").append(
391+
PlainSelect.getStringList(fkSourceColumns))
392+
.append(")");
393+
referentialActions.forEach(b::append);
325394
} else if (index != null) {
326395
b.append(index);
327396
}

0 commit comments

Comments
 (0)