1818import net .sf .jsqlparser .statement .create .table .ColDataType ;
1919
2020public 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