Skip to content

Commit 20793d4

Browse files
committed
Adapt wildcard exclusion tests to column transformers
Signed-off-by: Jake Wang <jake.wang@argonlabs.tech>
2 parents 5f929d2 + 60c8dc2 commit 20793d4

83 files changed

Lines changed: 5535 additions & 570 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎src/main/java/net/sf/jsqlparser/expression/AnalyticExpression.java‎

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*/
1010
package net.sf.jsqlparser.expression;
1111

12+
import java.util.function.Consumer;
1213
import java.util.Locale;
1314
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
1415
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
@@ -338,10 +339,8 @@ public String toString() {
338339
b.append(keep).append(" ");
339340
}
340341

341-
if (filterExpression != null) {
342-
b.append("FILTER (WHERE ");
343-
b.append(filterExpression);
344-
b.append(")");
342+
if (filterExpression != null && type != AnalyticType.WITHIN_GROUP) {
343+
appendFilterTo(b, b::append);
345344
if (type != AnalyticType.FILTER_ONLY) {
346345
b.append(" ");
347346
}
@@ -382,9 +381,22 @@ public String toString() {
382381
b.append(windowDef.toString());
383382
}
384383

384+
if (filterExpression != null && type == AnalyticType.WITHIN_GROUP) {
385+
b.append(' ');
386+
appendFilterTo(b, b::append);
387+
}
385388
return b.toString();
386389
}
387390

391+
/** Renders the filter using the caller's expression writer. */
392+
public void appendFilterTo(StringBuilder builder, Consumer<Expression> expressionPrinter) {
393+
if (filterExpression != null) {
394+
builder.append("FILTER (WHERE ");
395+
expressionPrinter.accept(filterExpression);
396+
builder.append(')');
397+
}
398+
}
399+
388400
public boolean isAllColumns() {
389401
return allColumns;
390402
}

‎src/main/java/net/sf/jsqlparser/expression/ColumnsTransformer.java‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
import net.sf.jsqlparser.statement.select.SelectItem;
1818

1919
/**
20-
* A ClickHouse transformer following a {@code COLUMNS(...)} matcher, for example the
20+
* A ClickHouse transformer following a {@code COLUMNS(...)} matcher or a {@code *}, for example the
2121
* {@code APPLY(x -> round(x, 2))} in {@code SELECT COLUMNS('^m') APPLY(x -> round(x, 2))}.
2222
*
2323
* ClickHouse parses its transformers in a loop, so they may repeat and combine in any order.
2424
*/
2525
public class ColumnsTransformer extends ASTNodeAccessImpl {
2626

2727
public enum ColumnsTransformerType {
28-
APPLY, EXCEPT, REPLACE
28+
APPLY, EXCEPT, EXCLUDE, REPLACE
2929
}
3030

3131
private ColumnsTransformerType type;
@@ -81,6 +81,7 @@ void collectExpressions(List<Expression> expressions) {
8181
}
8282
break;
8383
case EXCEPT:
84+
case EXCLUDE:
8485
if (exceptColumns != null) {
8586
expressions.addAll(exceptColumns);
8687
}
@@ -105,6 +106,9 @@ public StringBuilder appendTo(StringBuilder builder) {
105106
case EXCEPT:
106107
builder.append("EXCEPT ").append(exceptColumns);
107108
break;
109+
case EXCLUDE:
110+
builder.append("EXCLUDE ").append(exceptColumns);
111+
break;
108112
case REPLACE:
109113
builder.append("REPLACE(").append(Select.getStringList(replaceItems)).append(")");
110114
break;

‎src/main/java/net/sf/jsqlparser/expression/ExpressionVisitor.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import net.sf.jsqlparser.expression.operators.relational.IsDistinctExpression;
4747
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
4848
import net.sf.jsqlparser.expression.operators.relational.IsUnknownExpression;
49+
import net.sf.jsqlparser.expression.operators.relational.IsJsonExpression;
4950
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
5051
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
5152
import net.sf.jsqlparser.expression.operators.relational.Matches;
@@ -370,6 +371,14 @@ default void visit(IsBooleanExpression isBooleanExpression) {
370371
this.visit(isBooleanExpression, null);
371372
}
372373

374+
default <S> T visit(IsJsonExpression expression, S context) {
375+
return expression.getLeftExpression().accept(this, context);
376+
}
377+
378+
default void visit(IsJsonExpression expression) {
379+
visit(expression, null);
380+
}
381+
373382
<S> T visit(IsUnknownExpression isUnknownExpression, S context);
374383

375384
default void visit(IsUnknownExpression isUnknownExpression) {

‎src/main/java/net/sf/jsqlparser/expression/Function.java‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
import net.sf.jsqlparser.statement.select.Limit;
1818
import net.sf.jsqlparser.statement.select.OrderByElement;
1919

20+
import net.sf.jsqlparser.statement.create.table.ColumnDefinition;
21+
import net.sf.jsqlparser.statement.select.PlainSelect;
22+
2023
import java.io.Serializable;
2124
import java.util.ArrayList;
2225
import java.util.Arrays;
@@ -46,6 +49,7 @@ public class Function extends ASTNodeAccessImpl implements Expression {
4649
private KeepExpression keep = null;
4750
private String onOverflowTruncate = null;
4851
private String extraKeyword = null;
52+
private List<ColumnDefinition> resultColumnDefinitions;
4953

5054
/**
5155
* Generic keyword arguments captured inside function parentheses, e.g.
@@ -55,6 +59,23 @@ public class Function extends ASTNodeAccessImpl implements Expression {
5559
*/
5660
private List<KeywordArgument> keywordArguments = null;
5761

62+
/** Column definitions supplied for a record-returning function inside ROWS FROM. */
63+
public List<ColumnDefinition> getResultColumnDefinitions() {
64+
return resultColumnDefinitions;
65+
}
66+
67+
public void setResultColumnDefinitions(List<ColumnDefinition> resultColumnDefinitions) {
68+
this.resultColumnDefinitions = resultColumnDefinitions;
69+
}
70+
71+
public StringBuilder appendResultColumnDefinitionsTo(StringBuilder builder) {
72+
if (resultColumnDefinitions != null) {
73+
builder.append(" AS ")
74+
.append(PlainSelect.getStringList(resultColumnDefinitions, true, true));
75+
}
76+
return builder;
77+
}
78+
5879
public Function() {}
5980

6081
public Function(String name, Expression... parameters) {
@@ -446,7 +467,8 @@ public String toString() {
446467
ans = "{fn " + ans + "}";
447468
}
448469

449-
return ans;
470+
return resultColumnDefinitions == null ? ans
471+
: appendResultColumnDefinitionsTo(new StringBuilder(ans)).toString();
450472
}
451473

452474
public Function withAttribute(Expression attribute) {

‎src/main/java/net/sf/jsqlparser/expression/LambdaExpression.java‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,18 @@
1010
package net.sf.jsqlparser.expression;
1111

1212
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
13+
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
1314
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
1415

1516
import java.util.ArrayList;
1617
import java.util.Collections;
1718
import java.util.List;
19+
import java.util.function.Consumer;
1820

1921
public class LambdaExpression extends ASTNodeAccessImpl implements Expression {
2022
private List<String> identifiers;
2123
private Expression expression;
24+
private boolean parenthesized;
2225

2326
public LambdaExpression(String identifier, Expression expression) {
2427
this.identifiers = Collections.singletonList(identifier);
@@ -36,7 +39,18 @@ public static LambdaExpression from(ExpressionList<? extends Expression> express
3639
for (Expression variable : expressionList) {
3740
identifiers.add(variable.toString());
3841
}
39-
return new LambdaExpression(identifiers, expression);
42+
return new LambdaExpression(identifiers, expression)
43+
.setParenthesized(expressionList instanceof ParenthesedExpressionList);
44+
}
45+
46+
/** Whether the parameter list was explicitly parenthesized, including a single parameter. */
47+
public boolean isParenthesized() {
48+
return parenthesized;
49+
}
50+
51+
public LambdaExpression setParenthesized(boolean parenthesized) {
52+
this.parenthesized = parenthesized;
53+
return this;
4054
}
4155

4256
public List<String> getIdentifiers() {
@@ -58,7 +72,11 @@ public LambdaExpression setExpression(Expression expression) {
5872
}
5973

6074
public StringBuilder appendTo(StringBuilder builder) {
61-
if (identifiers.size() == 1) {
75+
return appendTo(builder, builder::append);
76+
}
77+
78+
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionPrinter) {
79+
if (identifiers.size() == 1 && !parenthesized) {
6280
builder.append(identifiers.get(0));
6381
} else {
6482
int i = 0;
@@ -68,7 +86,9 @@ public StringBuilder appendTo(StringBuilder builder) {
6886
}
6987
builder.append(" )");
7088
}
71-
return builder.append(" -> ").append(expression);
89+
builder.append(" -> ");
90+
expressionPrinter.accept(expression);
91+
return builder;
7292
}
7393

7494
@Override

‎src/main/java/net/sf/jsqlparser/expression/SQLServerHints.java‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,18 @@ public class SQLServerHints implements Serializable {
1717

1818
private Boolean noLock;
1919
private String indexName;
20+
private final List<LockHint> lockHints = new ArrayList<>();
21+
22+
/** Additional argument-free locking hints; NOLOCK retains its existing accessors. */
23+
public enum LockHint {
24+
HOLDLOCK, NOWAIT, PAGLOCK, READCOMMITTED, READCOMMITTEDLOCK, READPAST, READUNCOMMITTED, REPEATABLEREAD, ROWLOCK, SERIALIZABLE, SNAPSHOT, TABLOCK, TABLOCKX, UPDLOCK, XLOCK
25+
}
26+
27+
/** Returns the mutable list of locking hints, in their original order. */
28+
public List<LockHint> getLockHints() {
29+
return lockHints;
30+
}
31+
2032

2133
public SQLServerHints() {}
2234

@@ -50,6 +62,9 @@ public String toString() {
5062
if (Boolean.TRUE.equals(noLock)) {
5163
hints.add("NOLOCK");
5264
}
65+
for (LockHint hint : lockHints) {
66+
hints.add(hint.name());
67+
}
5368
return " WITH ("
5469
+ String.join(", ", hints)
5570
+ ")";

‎src/main/java/net/sf/jsqlparser/expression/TranscodingFunction.java‎

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,16 @@
1414
import net.sf.jsqlparser.statement.create.table.ColDataType;
1515

1616
import java.util.Objects;
17+
import java.util.function.Consumer;
1718

1819
public class TranscodingFunction extends ASTNodeAccessImpl implements Expression {
1920
private String keyword = "CONVERT";
20-
private boolean isTranscodeStyle = true;
21+
22+
public enum Syntax {
23+
USING, TYPE_FIRST, TYPE_LAST
24+
}
25+
26+
private Syntax syntax = Syntax.USING;
2127
private ColDataType colDataType;
2228
private Expression expression;
2329
private String transcodingName;
@@ -39,15 +45,15 @@ public TranscodingFunction(String keyword, ColDataType colDataType, Expression e
3945
this.colDataType = colDataType;
4046
this.expression = expression;
4147
this.transcodingName = transcodingName;
42-
this.isTranscodeStyle = false;
48+
this.syntax = Syntax.TYPE_FIRST;
4349
}
4450

4551
public TranscodingFunction(ColDataType colDataType, Expression expression,
4652
String transcodingName) {
4753
this.colDataType = colDataType;
4854
this.expression = expression;
4955
this.transcodingName = transcodingName;
50-
this.isTranscodeStyle = false;
56+
this.syntax = Syntax.TYPE_FIRST;
5157
}
5258

5359
public TranscodingFunction() {
@@ -100,39 +106,45 @@ public TranscodingFunction setColDataType(ColDataType colDataType) {
100106
}
101107

102108
public boolean isTranscodeStyle() {
103-
return isTranscodeStyle;
109+
return syntax == Syntax.USING;
104110
}
105111

106112
public TranscodingFunction setTranscodeStyle(boolean transcodeStyle) {
107-
isTranscodeStyle = transcodeStyle;
113+
syntax = transcodeStyle ? Syntax.USING : Syntax.TYPE_FIRST;
108114
return this;
109115
}
110116

111117
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
112118
return expressionVisitor.visit(this, context);
113119
}
114120

121+
public Syntax getSyntax() {
122+
return syntax;
123+
}
124+
125+
public TranscodingFunction setSyntax(Syntax syntax) {
126+
this.syntax = Objects.requireNonNull(syntax);
127+
return this;
128+
}
129+
115130
public StringBuilder appendTo(StringBuilder builder) {
116-
if (isTranscodeStyle) {
117-
return builder
118-
.append(keyword)
119-
.append("( ")
120-
.append(expression)
121-
.append(" USING ")
122-
.append(transcodingName)
123-
.append(" )");
124-
} else {
125-
return builder
126-
.append(keyword)
127-
.append("( ")
128-
.append(colDataType)
129-
.append(", ")
130-
.append(expression)
131-
.append(transcodingName != null && !transcodingName.isEmpty()
132-
? ", " + transcodingName
133-
: "")
134-
.append(" )");
131+
return appendTo(builder, builder::append);
132+
}
133+
134+
public StringBuilder appendTo(StringBuilder builder, Consumer<Expression> expressionRenderer) {
135+
builder.append(keyword).append("( ");
136+
if (syntax == Syntax.TYPE_FIRST) {
137+
builder.append(colDataType).append(", ");
138+
}
139+
expressionRenderer.accept(expression);
140+
if (syntax == Syntax.USING) {
141+
builder.append(" USING ").append(transcodingName);
142+
} else if (syntax == Syntax.TYPE_LAST) {
143+
builder.append(", ").append(colDataType);
144+
} else if (transcodingName != null && !transcodingName.isEmpty()) {
145+
builder.append(", ").append(transcodingName);
135146
}
147+
return builder.append(" )");
136148
}
137149

138150
@Override

0 commit comments

Comments
 (0)