Skip to content

Commit 9caed41

Browse files
authored
fix: share expression-aware table constraint rendering (#2609)
1 parent fec4ec4 commit 9caed41

8 files changed

Lines changed: 211 additions & 105 deletions

File tree

src/main/java/net/sf/jsqlparser/statement/create/table/CheckConstraint.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import java.util.Collection;
1313
import java.util.List;
14+
import java.util.function.Consumer;
1415

1516
import net.sf.jsqlparser.expression.Expression;
1617
import net.sf.jsqlparser.schema.Table;
@@ -52,16 +53,20 @@ public void setEnforced(Boolean enforced) {
5253
}
5354

5455
@Override
55-
public String toString() {
56-
StringBuilder b = new StringBuilder();
56+
public void appendTo(StringBuilder b, Consumer<Expression> expressionPrinter) {
5757
appendConstraintPrefixTo(b);
58-
b.append("CHECK (").append(expression).append(")");
58+
b.append("CHECK (");
59+
if (expression == null) {
60+
b.append("null");
61+
} else {
62+
expressionPrinter.accept(expression);
63+
}
64+
b.append(')');
5965
if (enforced != null) {
6066
b.append(enforced ? " ENFORCED" : " NOT ENFORCED");
6167
}
6268
appendConstraintSuffixTo(b);
6369
appendConstraintAttributesTo(b);
64-
return b.toString();
6570
}
6671

6772
public CheckConstraint withTable(Table table) {

src/main/java/net/sf/jsqlparser/statement/create/table/ExcludeConstraint.java

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111

1212
import java.util.Collection;
1313
import java.util.List;
14+
import java.util.function.Consumer;
1415

1516
import net.sf.jsqlparser.expression.Expression;
16-
import net.sf.jsqlparser.statement.select.PlainSelect;
1717

1818
public class ExcludeConstraint extends Index {
1919

@@ -33,8 +33,7 @@ public void setExpression(Expression expression) {
3333
}
3434

3535
@Override
36-
public String toString() {
37-
StringBuilder exclusionStatement = new StringBuilder();
36+
public void appendTo(StringBuilder exclusionStatement, Consumer<Expression> expressionPrinter) {
3837
if (getName() != null) {
3938
exclusionStatement.append("CONSTRAINT ").append(getName()).append(' ');
4039
}
@@ -43,15 +42,16 @@ public String toString() {
4342
exclusionStatement.append(" USING ").append(getUsing());
4443
}
4544
if (getColumns() != null) {
46-
exclusionStatement.append(' ')
47-
.append(PlainSelect.getStringList(getColumns(), true, true));
45+
exclusionStatement.append(' ');
46+
appendColumnsTo(exclusionStatement, expressionPrinter);
4847
}
49-
appendConstraintOptionsTo(exclusionStatement);
48+
appendConstraintOptionsTo(exclusionStatement, expressionPrinter);
5049
if (expression != null) {
51-
exclusionStatement.append(" WHERE (").append(expression).append(')');
50+
exclusionStatement.append(" WHERE (");
51+
expressionPrinter.accept(expression);
52+
exclusionStatement.append(')');
5253
}
5354
appendConstraintAttributesTo(exclusionStatement);
54-
return exclusionStatement.toString();
5555
}
5656

5757
public ExcludeConstraint withExpression(Expression expression) {

src/main/java/net/sf/jsqlparser/statement/create/table/ForeignKeyIndex.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import java.util.Collections;
2121
import java.util.LinkedHashSet;
2222
import java.util.List;
23+
import java.util.function.Consumer;
24+
import net.sf.jsqlparser.expression.Expression;
2325
import java.util.Optional;
2426
import java.util.Set;
2527

@@ -165,8 +167,9 @@ public void setOnUpdateReferenceOption(String onUpdateReferenceOption) {
165167
}
166168

167169
@Override
168-
public String toString() {
169-
StringBuilder b = new StringBuilder(super.toString()).append(" ");
170+
public void appendTo(StringBuilder b, Consumer<Expression> expressionPrinter) {
171+
super.appendTo(b, expressionPrinter);
172+
b.append(' ');
170173
if (reference != null) {
171174
b.append(reference);
172175
} else {
@@ -176,7 +179,6 @@ public String toString() {
176179
}
177180
appendConstraintSuffixTo(b);
178181
appendConstraintAttributesTo(b);
179-
return b.toString();
180182
}
181183

182184
public ForeignKeyIndex withTable(Table table) {

src/main/java/net/sf/jsqlparser/statement/create/table/Index.java

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -111,11 +111,17 @@ public String nullsDistinctClause() {
111111
}
112112

113113
public void appendConstraintOptionsTo(StringBuilder sql) {
114+
appendConstraintOptionsTo(sql, sql::append);
115+
}
116+
117+
public void appendConstraintOptionsTo(StringBuilder sql,
118+
Consumer<Expression> expressionPrinter) {
114119
if (includeColumns != null) {
115120
sql.append(" INCLUDE ").append(PlainSelect.getStringList(includeColumns, true, true));
116121
}
117122
if (storageParameters != null) {
118-
sql.append(" WITH ").append(PlainSelect.getStringList(storageParameters, true, true));
123+
sql.append(" WITH ");
124+
Option.appendListTo(sql, storageParameters, expressionPrinter);
119125
}
120126
if (tableSpace != null) {
121127
sql.append(" USING INDEX TABLESPACE ").append(tableSpace);
@@ -283,31 +289,49 @@ public Index withIndexKeyword(String indexKeyword) {
283289

284290
@Override
285291
public String toString() {
292+
StringBuilder sql = new StringBuilder();
293+
appendTo(sql, sql::append);
294+
return sql.toString();
295+
}
296+
297+
/** Renders index definitions through the supplied expression writer. */
298+
public void appendTo(StringBuilder sql, Consumer<Expression> expressionPrinter) {
286299
String idxSpecText = PlainSelect.getStringList(idxSpec, false, false);
287300
String keyword = indexKeyword != null
288301
&& (type == null || !type.toUpperCase(java.util.Locale.ROOT)
289302
.endsWith(indexKeyword.toUpperCase(java.util.Locale.ROOT)))
290303
? " " + indexKeyword
291304
: "";
292-
String head =
293-
(type != null ? type : "") +
294-
keyword +
295-
(!name.isEmpty() ? " " + getName() : "") +
296-
(using != null ? " USING " + using : "");
297-
298-
String tail = (columns != null && !columns.isEmpty()
299-
? PlainSelect.getStringList(columns, true, true)
300-
: "")
301-
+ (!idxSpecText.isEmpty() ? " " + idxSpecText : "");
302-
303-
StringBuilder sql = new StringBuilder(head).append(nullsDistinctClause())
304-
.append(clusteringClause());
305-
if (!tail.isEmpty()) {
306-
sql.append(' ').append(tail);
307-
}
308-
appendConstraintOptionsTo(sql);
305+
sql.append(type != null ? type : "").append(keyword);
306+
if (!name.isEmpty()) {
307+
sql.append(' ').append(getName());
308+
}
309+
if (using != null) {
310+
sql.append(" USING ").append(using);
311+
}
312+
sql.append(nullsDistinctClause()).append(clusteringClause());
313+
boolean hasColumns = columns != null && !columns.isEmpty();
314+
if (hasColumns) {
315+
sql.append(' ');
316+
appendColumnsTo(sql, expressionPrinter);
317+
}
318+
if (!idxSpecText.isEmpty()) {
319+
sql.append(hasColumns ? " " : " ").append(idxSpecText);
320+
}
321+
appendConstraintOptionsTo(sql, expressionPrinter);
309322
appendConstraintAttributesTo(sql);
310-
return sql.toString();
323+
}
324+
325+
/** Appends a parenthesized list of keys, including expression keys and operator options. */
326+
protected void appendColumnsTo(StringBuilder sql, Consumer<Expression> expressionPrinter) {
327+
sql.append('(');
328+
for (int i = 0; i < columns.size(); i++) {
329+
if (i > 0) {
330+
sql.append(", ");
331+
}
332+
columns.get(i).appendTo(sql, expressionPrinter);
333+
}
334+
sql.append(')');
311335
}
312336

313337
public Index withType(String type) {

src/main/java/net/sf/jsqlparser/statement/create/table/NamedConstraint.java

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
import java.util.Collection;
1313
import java.util.List;
14+
import java.util.function.Consumer;
15+
import net.sf.jsqlparser.expression.Expression;
1416

1517
import net.sf.jsqlparser.statement.select.PlainSelect;
1618

@@ -81,32 +83,34 @@ public void setUseConstraintKeyword(boolean useConstraintKeyword) {
8183
}
8284

8385
@Override
84-
public String toString() {
86+
public void appendTo(StringBuilder sql, Consumer<Expression> expressionPrinter) {
8587
String idxSpecText = PlainSelect.getStringList(getIndexSpec(), false, false);
8688
String keyword = getIndexKeyword() != null
8789
&& !getType().toUpperCase(java.util.Locale.ROOT)
8890
.endsWith(getIndexKeyword().toUpperCase(java.util.Locale.ROOT))
8991
? " " + getIndexKeyword()
9092
: "";
91-
String tail = getType()
92-
+ nullsDistinctClause()
93-
+ keyword
94-
+ clusteringClause()
95-
+ (indexName != null ? " " + indexName : "")
96-
+ (getUsing() != null ? " USING " + getUsing() : "")
97-
+ (getColumns() == null ? ""
98-
: " " + PlainSelect.getStringList(getColumnsNames(), true, true))
99-
+
100-
(!"".equals(idxSpecText) ? " " + idxSpecText : "");
101-
StringBuilder sql = new StringBuilder();
10293
appendConstraintPrefixTo(sql);
103-
sql.append(tail);
104-
appendConstraintOptionsTo(sql);
94+
sql.append(getType()).append(nullsDistinctClause()).append(keyword)
95+
.append(clusteringClause());
96+
if (indexName != null) {
97+
sql.append(' ').append(indexName);
98+
}
99+
if (getUsing() != null) {
100+
sql.append(" USING ").append(getUsing());
101+
}
102+
if (getColumns() != null) {
103+
sql.append(' ');
104+
appendColumnsTo(sql, expressionPrinter);
105+
}
106+
if (!idxSpecText.isEmpty()) {
107+
sql.append(' ').append(idxSpecText);
108+
}
109+
appendConstraintOptionsTo(sql, expressionPrinter);
105110
if (getKind() != Kind.FOREIGN_KEY) {
106111
appendConstraintSuffixTo(sql);
107112
appendConstraintAttributesTo(sql);
108113
}
109-
return sql.toString();
110114
}
111115

112116
public NamedConstraint withIndexName(String indexName) {

src/main/java/net/sf/jsqlparser/util/deparser/AlterDeParser.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import net.sf.jsqlparser.expression.ExpressionVisitor;
1414
import net.sf.jsqlparser.statement.alter.AlterExpression;
1515
import net.sf.jsqlparser.statement.alter.AlterExpressionPrimaryKey;
16-
import net.sf.jsqlparser.statement.create.table.DefaultConstraint;
16+
import net.sf.jsqlparser.statement.alter.AlterOperation;
1717
import net.sf.jsqlparser.statement.select.PlainSelect;
1818
import java.util.Iterator;
1919

@@ -54,9 +54,17 @@ private void deParseAction(AlterExpression action) {
5454
expression -> expression.accept(expressionVisitor, null));
5555
return;
5656
}
57-
if (action.getIndex() instanceof DefaultConstraint) {
57+
if (action.getOperation() == AlterOperation.ADD && action.getIndex() != null
58+
&& action.getConstraintType() == null) {
5859
builder.append(action.getOperation()).append(' ');
5960
new TableElementDeParser(builder, expressionVisitor).deParse(action.getIndex());
61+
if (action.getConstraints() != null && !action.getConstraints().isEmpty()) {
62+
builder.append(' ')
63+
.append(PlainSelect.getStringList(action.getConstraints(), false, false));
64+
}
65+
if (action.getUseEqual()) {
66+
builder.append('=');
67+
}
6068
deParseTail(action);
6169
return;
6270
}

src/main/java/net/sf/jsqlparser/util/deparser/TableElementDeParser.java

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@
99
*/
1010
package net.sf.jsqlparser.util.deparser;
1111

12-
import java.util.Iterator;
1312
import net.sf.jsqlparser.expression.ExpressionVisitor;
14-
import net.sf.jsqlparser.statement.create.table.CheckConstraint;
1513
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
1614
import net.sf.jsqlparser.statement.create.table.ColumnOption;
17-
import net.sf.jsqlparser.statement.create.table.DefaultConstraint;
18-
import net.sf.jsqlparser.statement.create.table.ExcludeConstraint;
1915
import net.sf.jsqlparser.statement.create.table.Index;
2016
import net.sf.jsqlparser.statement.create.table.TableElement;
2117

@@ -31,13 +27,9 @@ public TableElementDeParser(StringBuilder builder,
3127

3228
@Override
3329
public void deParse(TableElement element) {
34-
if (element instanceof DefaultConstraint) {
35-
((DefaultConstraint) element).appendTo(builder,
30+
if (element instanceof Index) {
31+
((Index) element).appendTo(builder,
3632
expression -> expression.accept(expressionVisitor, null));
37-
} else if (element instanceof ExcludeConstraint) {
38-
deParseExclude((ExcludeConstraint) element);
39-
} else if (element instanceof CheckConstraint) {
40-
deParseCheck((CheckConstraint) element);
4133
} else if (element instanceof ColumnDefinition
4234
&& ((ColumnDefinition) element).getColumnOptions() != null) {
4335
deParseColumn((ColumnDefinition) element);
@@ -64,48 +56,4 @@ private void deParseColumn(ColumnDefinition column) {
6456
}
6557
}
6658

67-
private void deParseExclude(ExcludeConstraint constraint) {
68-
if (constraint.getName() != null) {
69-
builder.append("CONSTRAINT ").append(constraint.getName()).append(' ');
70-
}
71-
builder.append("EXCLUDE");
72-
if (constraint.getUsing() != null) {
73-
builder.append(" USING ").append(constraint.getUsing());
74-
}
75-
if (constraint.getColumns() != null) {
76-
builder.append(" (");
77-
for (Iterator<Index.ColumnParams> iterator =
78-
constraint.getColumns().iterator(); iterator.hasNext();) {
79-
iterator.next().appendTo(builder,
80-
expression -> expression.accept(expressionVisitor, null));
81-
if (iterator.hasNext()) {
82-
builder.append(", ");
83-
}
84-
}
85-
builder.append(')');
86-
}
87-
constraint.appendConstraintOptionsTo(builder);
88-
if (constraint.getExpression() != null) {
89-
builder.append(" WHERE (");
90-
constraint.getExpression().accept(expressionVisitor, null);
91-
builder.append(')');
92-
}
93-
constraint.appendConstraintAttributesTo(builder);
94-
}
95-
96-
private void deParseCheck(CheckConstraint constraint) {
97-
constraint.appendConstraintPrefixTo(builder);
98-
builder.append("CHECK (");
99-
if (constraint.getExpression() != null) {
100-
constraint.getExpression().accept(expressionVisitor, null);
101-
} else {
102-
builder.append("null");
103-
}
104-
builder.append(')');
105-
if (constraint.getEnforced() != null) {
106-
builder.append(constraint.getEnforced() ? " ENFORCED" : " NOT ENFORCED");
107-
}
108-
constraint.appendConstraintSuffixTo(builder);
109-
constraint.appendConstraintAttributesTo(builder);
110-
}
11159
}

0 commit comments

Comments
 (0)