Skip to content

Commit ea2f431

Browse files
Merge branch 'master' into manticore
2 parents 4dad36d + cae3e0d commit ea2f431

File tree

11 files changed

+42724
-74
lines changed

11 files changed

+42724
-74
lines changed

src/main/java/net/sf/jsqlparser/expression/JsonFunction.java

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
*/
2828
public class JsonFunction extends ASTNodeAccessImpl implements Expression {
2929
public enum JsonOnResponseBehaviorType {
30-
ERROR, NULL, DEFAULT, EMPTY_ARRAY, EMPTY_OBJECT, TRUE, FALSE, UNKNOWN
30+
ERROR, NULL, DEFAULT, EMPTY, EMPTY_ARRAY, EMPTY_OBJECT, TRUE, FALSE, UNKNOWN
3131
}
3232

3333
public enum JsonWrapperType {
@@ -42,6 +42,10 @@ public enum JsonQuotesType {
4242
KEEP, OMIT
4343
}
4444

45+
public enum ScalarsType {
46+
ALLOW, DISALLOW
47+
}
48+
4549
public static class JsonOnResponseBehavior {
4650
private JsonOnResponseBehaviorType type;
4751
private Expression expression;
@@ -82,6 +86,9 @@ public StringBuilder append(StringBuilder builder) {
8286
case DEFAULT:
8387
builder.append("DEFAULT ").append(expression);
8488
break;
89+
case EMPTY:
90+
builder.append("EMPTY ");
91+
break;
8592
case EMPTY_ARRAY:
8693
builder.append("EMPTY ARRAY");
8794
break;
@@ -98,7 +105,8 @@ public StringBuilder append(StringBuilder builder) {
98105
builder.append("UNKNOWN");
99106
break;
100107
default:
101-
// this should never happen
108+
throw new IllegalStateException("Unhandled JsonOnResponseBehavior: " + type);
109+
// this should never happen
102110
}
103111
return builder;
104112
}
@@ -130,6 +138,7 @@ public String toString() {
130138
private boolean wrapperArray;
131139
private JsonQuotesType quotesType;
132140
private boolean quotesOnScalarString;
141+
private ScalarsType scalarsType;
133142

134143
public JsonFunction() {}
135144

@@ -294,6 +303,14 @@ public void setQuotesOnScalarString(boolean quotesOnScalarString) {
294303
this.quotesOnScalarString = quotesOnScalarString;
295304
}
296305

306+
public ScalarsType getScalarsType() {
307+
return scalarsType;
308+
}
309+
310+
public void setScalarsType(ScalarsType type) {
311+
this.scalarsType = type;
312+
}
313+
297314
public boolean isEmpty() {
298315
return keyValuePairs.isEmpty();
299316
}

src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java

Lines changed: 175 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@
1818
import net.sf.jsqlparser.statement.create.table.ColDataType;
1919

2020
public class JsonTableFunction extends Function {
21+
22+
private Expression jsonInputExpression;
23+
private Expression jsonPathExpression;
24+
private String pathName;
25+
private final List<JsonTablePassingClause> passingClauses = new ArrayList<>();
26+
private JsonTableColumnsClause columnsClause;
27+
private JsonTablePlanClause planClause;
28+
private JsonTableOnErrorClause onErrorClause;
29+
private JsonTableParsingTypeClause parsingTypeClause;
30+
private JsonTableOnEmptyClause onEmptyClause;
31+
private boolean formatJson;
32+
2133
public enum JsonTablePlanOperator {
2234
COMMA(", "), INNER(" INNER "), OUTER(" OUTER "), CROSS(" CROSS "), UNION(" UNION ");
2335

@@ -33,7 +45,15 @@ public String getDisplay() {
3345
}
3446

3547
public enum JsonTableOnErrorType {
36-
ERROR, EMPTY
48+
ERROR, NULL, EMPTY, TRUE, FALSE
49+
}
50+
51+
public enum JsonTableOnEmptyType {
52+
ERROR, NULL, EMPTY, TRUE, FALSE
53+
}
54+
55+
public enum JsonTableParsingType {
56+
STRICT, LAX
3757
}
3858

3959
public static class JsonTablePassingClause extends ASTNodeAccessImpl implements Serializable {
@@ -78,10 +98,30 @@ public String toString() {
7898
}
7999

80100
public static class JsonTableWrapperClause extends ASTNodeAccessImpl implements Serializable {
101+
private boolean beforePathExpression;
81102
private JsonFunction.JsonWrapperType wrapperType;
82103
private JsonFunction.JsonWrapperMode wrapperMode;
83104
private boolean array;
84105

106+
/**
107+
* Creates a wrapper clause. Depending on the dialect, this clause can come before or after
108+
* the PATH expression.
109+
* <ul>
110+
* <li>Trino: after PATH</li>
111+
* <li>Oracle: before PATH</li>
112+
* </ul>
113+
*
114+
* @param beforePathExpression A flag to determine wether the clause is rendered before or
115+
* after the PATH expression
116+
*/
117+
public JsonTableWrapperClause(boolean beforePathExpression) {
118+
this.beforePathExpression = beforePathExpression;
119+
}
120+
121+
public boolean isBeforePathExpression() {
122+
return beforePathExpression;
123+
}
124+
85125
public JsonFunction.JsonWrapperType getWrapperType() {
86126
return wrapperType;
87127
}
@@ -159,6 +199,15 @@ public String toString() {
159199

160200
public static class JsonTableOnErrorClause extends ASTNodeAccessImpl implements Serializable {
161201
private JsonTableOnErrorType type;
202+
private boolean beforeColumns = true;
203+
204+
public JsonTableOnErrorClause(boolean beforeColumns) {
205+
this.beforeColumns = beforeColumns;
206+
}
207+
208+
public boolean isBeforeColumns() {
209+
return beforeColumns;
210+
}
162211

163212
public JsonTableOnErrorType getType() {
164213
return type;
@@ -175,6 +224,43 @@ public String toString() {
175224
}
176225
}
177226

227+
public static class JsonTableOnEmptyClause extends ASTNodeAccessImpl implements Serializable {
228+
private JsonTableOnEmptyType type;
229+
230+
public JsonTableOnEmptyType getType() {
231+
return type;
232+
}
233+
234+
public JsonTableOnEmptyClause setType(JsonTableOnEmptyType type) {
235+
this.type = type;
236+
return this;
237+
}
238+
239+
@Override
240+
public String toString() {
241+
return type + " ON EMPTY";
242+
}
243+
}
244+
245+
public static class JsonTableParsingTypeClause extends ASTNodeAccessImpl
246+
implements Serializable {
247+
private JsonTableParsingType type;
248+
249+
public JsonTableParsingType getType() {
250+
return type;
251+
}
252+
253+
public JsonTableParsingTypeClause setType(JsonTableParsingType type) {
254+
this.type = type;
255+
return this;
256+
}
257+
258+
@Override
259+
public String toString() {
260+
return "TYPE(" + type + ")";
261+
}
262+
}
263+
178264
public static class JsonTablePlanTerm extends ASTNodeAccessImpl implements Serializable {
179265
private JsonTablePlanExpression nestedPlanExpression;
180266
private String name;
@@ -389,12 +475,15 @@ public static class JsonTableValueColumnDefinition extends JsonTableColumnDefini
389475
private boolean forOrdinality;
390476
private ColDataType dataType;
391477
private boolean formatJson;
478+
private boolean exists;
479+
private boolean onEmptyAfterOnError;
392480
private String encoding;
393481
private Expression pathExpression;
394482
private JsonTableWrapperClause wrapperClause;
395483
private JsonTableQuotesClause quotesClause;
396484
private JsonFunction.JsonOnResponseBehavior onEmptyBehavior;
397485
private JsonFunction.JsonOnResponseBehavior onErrorBehavior;
486+
private JsonFunction.ScalarsType scalarsType;
398487

399488
public String getColumnName() {
400489
return columnName;
@@ -405,6 +494,20 @@ public JsonTableValueColumnDefinition setColumnName(String columnName) {
405494
return this;
406495
}
407496

497+
public boolean isExists() {
498+
return exists;
499+
}
500+
501+
public JsonTableValueColumnDefinition setExistsKeyword(boolean exists) {
502+
this.exists = exists;
503+
return this;
504+
}
505+
506+
public JsonTableValueColumnDefinition setOnEmptyAfterOnError(boolean b) {
507+
this.onEmptyAfterOnError = b;
508+
return this;
509+
}
510+
408511
public boolean isForOrdinality() {
409512
return forOrdinality;
410513
}
@@ -489,6 +592,14 @@ public JsonTableValueColumnDefinition setOnErrorBehavior(
489592
return this;
490593
}
491594

595+
public void setScalarsType(JsonFunction.ScalarsType scalarsType) {
596+
this.scalarsType = scalarsType;
597+
}
598+
599+
public JsonFunction.ScalarsType getScalarsType() {
600+
return scalarsType;
601+
}
602+
492603
@Override
493604
public void collectExpressions(List<Expression> expressions) {
494605
if (pathExpression != null) {
@@ -509,29 +620,44 @@ public String toString() {
509620
builder.append(" FOR ORDINALITY");
510621
return builder.toString();
511622
}
512-
513-
builder.append(" ").append(dataType);
623+
if (exists) {
624+
builder.append(" EXISTS");
625+
}
626+
if (dataType != null) {
627+
builder.append(" ").append(dataType);
628+
}
514629
if (formatJson) {
515630
builder.append(" FORMAT JSON");
516631
if (encoding != null) {
517632
builder.append(" ENCODING ").append(encoding);
518633
}
519634
}
635+
if (scalarsType != null) {
636+
builder.append(" ");
637+
builder.append(scalarsType);
638+
builder.append(" SCALARS");
639+
}
640+
if (wrapperClause != null && wrapperClause.isBeforePathExpression()) {
641+
builder.append(" ").append(wrapperClause);
642+
}
520643
if (pathExpression != null) {
521644
builder.append(" PATH ").append(pathExpression);
522645
}
523-
if (wrapperClause != null) {
646+
if (wrapperClause != null && !wrapperClause.isBeforePathExpression()) {
524647
builder.append(" ").append(wrapperClause);
525648
}
526649
if (quotesClause != null) {
527650
builder.append(" ").append(quotesClause);
528651
}
529-
if (onEmptyBehavior != null) {
652+
if (onEmptyBehavior != null && !onEmptyAfterOnError) {
530653
builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
531654
}
532655
if (onErrorBehavior != null) {
533656
builder.append(" ").append(onErrorBehavior).append(" ON ERROR");
534657
}
658+
if (onEmptyBehavior != null && onEmptyAfterOnError) {
659+
builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
660+
}
535661
return builder.toString();
536662
}
537663
}
@@ -573,18 +699,19 @@ public String toString() {
573699
}
574700
}
575701

576-
private Expression jsonInputExpression;
577-
private Expression jsonPathExpression;
578-
private String pathName;
579-
private final List<JsonTablePassingClause> passingClauses = new ArrayList<>();
580-
private JsonTableColumnsClause columnsClause;
581-
private JsonTablePlanClause planClause;
582-
private JsonTableOnErrorClause onErrorClause;
583-
584702
public JsonTableFunction() {
585703
setName("JSON_TABLE");
586704
}
587705

706+
public boolean getFormatJson() {
707+
return formatJson;
708+
}
709+
710+
public JsonTableFunction setFormatJson(boolean formatJson) {
711+
this.formatJson = formatJson;
712+
return this;
713+
}
714+
588715
public Expression getJsonInputExpression() {
589716
return jsonInputExpression;
590717
}
@@ -648,6 +775,24 @@ public JsonTableFunction setOnErrorClause(JsonTableOnErrorClause onErrorClause)
648775
return this;
649776
}
650777

778+
public JsonTableParsingTypeClause getParsingTypeClause() {
779+
return parsingTypeClause;
780+
}
781+
782+
public JsonTableFunction setParsingTypeClause(JsonTableParsingTypeClause parsingTypeClause) {
783+
this.parsingTypeClause = parsingTypeClause;
784+
return this;
785+
}
786+
787+
public JsonTableOnEmptyClause getOnEmptyClause() {
788+
return onEmptyClause;
789+
}
790+
791+
public JsonTableFunction setOnEmptyClause(JsonTableOnEmptyClause onEmptyClause) {
792+
this.onEmptyClause = onEmptyClause;
793+
return this;
794+
}
795+
651796
public List<Expression> getAllExpressions() {
652797
List<Expression> expressions = new ArrayList<>();
653798
if (jsonInputExpression != null) {
@@ -676,7 +821,13 @@ public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
676821
@Override
677822
public String toString() {
678823
StringBuilder builder = new StringBuilder("JSON_TABLE(");
679-
builder.append(jsonInputExpression).append(", ").append(jsonPathExpression);
824+
builder.append(jsonInputExpression);
825+
if (formatJson) {
826+
builder.append(" FORMAT JSON");
827+
}
828+
if (jsonPathExpression != null) {
829+
builder.append(", ").append(jsonPathExpression);
830+
}
680831
if (pathName != null) {
681832
builder.append(" AS ").append(pathName);
682833
}
@@ -691,11 +842,20 @@ public String toString() {
691842
first = false;
692843
}
693844
}
845+
if (onErrorClause != null && onErrorClause.isBeforeColumns()) {
846+
builder.append(" ").append(onErrorClause);
847+
}
848+
if (parsingTypeClause != null) {
849+
builder.append(" ").append(parsingTypeClause);
850+
}
851+
if (onEmptyClause != null) {
852+
builder.append(" ").append(onEmptyClause);
853+
}
694854
builder.append(" ").append(columnsClause);
695855
if (planClause != null) {
696856
builder.append(" ").append(planClause);
697857
}
698-
if (onErrorClause != null) {
858+
if (onErrorClause != null && !onErrorClause.isBeforeColumns()) {
699859
builder.append(" ").append(onErrorClause);
700860
}
701861
builder.append(")");

0 commit comments

Comments
 (0)