Skip to content

Commit 8773eea

Browse files
committed
[feat] Additional support for JSON_TABLE
1 parent 0b85753 commit 8773eea

File tree

16 files changed

+947
-59
lines changed

16 files changed

+947
-59
lines changed

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,8 @@
2929
*
3030
*/
3131
public enum JsonOnEmptyType {
32-
ERROR("ERROR"),
33-
NULL("NULL"),
34-
EMPTY("EMPTY"),
35-
EMPTY_ARRAY("EMPTY ARRAY"),
36-
EMPTY_OBJECT("EMPTY OBJECT"),
37-
TRUE("TRUE"),
38-
FALSE("FALSE");
32+
ERROR("ERROR"), NULL("NULL"), EMPTY("EMPTY"), EMPTY_ARRAY("EMPTY ARRAY"), EMPTY_OBJECT(
33+
"EMPTY OBJECT"), TRUE("TRUE"), FALSE("FALSE"), DEFAULT("DEFAULT");
3934

4035
private final String value;
4136

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

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,8 @@
2929
*
3030
*/
3131
public enum JsonOnErrorType {
32-
ERROR("ERROR"),
33-
NULL("NULL"),
34-
EMPTY("EMPTY"),
35-
EMPTY_ARRAY("EMPTY ARRAY"),
36-
EMPTY_OBJECT("EMPTY OBJECT"),
37-
TRUE("TRUE"),
38-
FALSE("FALSE");
32+
ERROR("ERROR"), NULL("NULL"), EMPTY("EMPTY"), EMPTY_ARRAY("EMPTY ARRAY"), EMPTY_OBJECT(
33+
"EMPTY OBJECT"), TRUE("TRUE"), FALSE("FALSE"), DEFAULT("DEFAULT");
3934

4035
private final String value;
4136

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2021 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
/*
11+
* Copyright (C) 2021 JSQLParser.
12+
*
13+
* This library is free software; you can redistribute it and/or modify it under the terms of the
14+
* GNU Lesser General Public License as published by the Free Software Foundation; either version
15+
* 2.1 of the License, or (at your option) any later version.
16+
*
17+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
18+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License along with this library;
22+
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23+
* 02110-1301 USA
24+
*/
25+
26+
package net.sf.jsqlparser.expression;
27+
28+
/**
29+
*
30+
*/
31+
public enum JsonQueryWrapperType {
32+
WITHOUT_WRAPPER("WITHOUT WRAPPER"), WITHOUT_ARRAY_WRAPPER(
33+
"WITHOUT ARRAY WRAPPER"), WITH_WRAPPER("WITH WRAPPER"), WITH_ARRAY_WRAPPER(
34+
"WITH ARRAY WRAPPER"), WITH_UNCONDITIONAL_WRAPPER(
35+
"WITH UNCONDITIONAL WRAPPER"), WITH_UNCONDITIONAL_ARRAY_WRAPPER(
36+
"WITH UNCONDITIONAL ARRAY WRAPPER"), WITH_CONDITIONAL_WRAPPER(
37+
"WITH CONDITIONAL WRAPPER"), WITH_CONDITIONAL_ARRAY_WRAPPER(
38+
"WITH CONDITIONAL ARRAY WRAPPER");
39+
40+
private final String value;
41+
42+
JsonQueryWrapperType(String value) {
43+
this.value = value;
44+
}
45+
46+
public String getValue() {
47+
return value;
48+
}
49+
50+
public static JsonQueryWrapperType from(String type) {
51+
return Enum.valueOf(JsonQueryWrapperType.class, type.toUpperCase());
52+
}
53+
54+
public static JsonQueryWrapperType fromWithParts(boolean isArray, boolean isConditional,
55+
boolean isUnconditional) {
56+
if (isArray) {
57+
if (isConditional) {
58+
return JsonQueryWrapperType.WITH_CONDITIONAL_ARRAY_WRAPPER;
59+
} else if (isUnconditional) {
60+
return JsonQueryWrapperType.WITH_UNCONDITIONAL_ARRAY_WRAPPER;
61+
} else {
62+
return JsonQueryWrapperType.WITH_ARRAY_WRAPPER;
63+
}
64+
} else {
65+
if (isConditional) {
66+
return JsonQueryWrapperType.WITH_CONDITIONAL_WRAPPER;
67+
} else if (isUnconditional) {
68+
return JsonQueryWrapperType.WITH_UNCONDITIONAL_WRAPPER;
69+
} else {
70+
return JsonQueryWrapperType.WITH_WRAPPER;
71+
}
72+
}
73+
}
74+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package net.sf.jsqlparser.expression;
2+
3+
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
4+
5+
public class JsonReturnClause extends ASTNodeAccessImpl {
6+
7+
private JsonReturnType type;
8+
9+
private Long varcharSize;
10+
11+
public JsonReturnClause() {}
12+
13+
public JsonReturnClause(JsonReturnType type) {
14+
this.type = type;
15+
}
16+
17+
public JsonReturnType getType() {
18+
return type;
19+
}
20+
21+
public void setType(JsonReturnType type) {
22+
this.type = type;
23+
}
24+
25+
public JsonReturnClause withType(JsonReturnType type) {
26+
setType(type);
27+
return this;
28+
}
29+
30+
public Long getVarcharSize() {
31+
return varcharSize;
32+
}
33+
34+
public void setVarcharSize(Long varcharSize) {
35+
this.varcharSize = varcharSize;
36+
}
37+
38+
public JsonReturnClause withVarcharSize(Long varcharSize) {
39+
setVarcharSize(varcharSize);
40+
return this;
41+
}
42+
43+
public StringBuilder append(StringBuilder builder) {
44+
builder.append(" ");
45+
builder.append(type.getValue());
46+
switch (type) {
47+
case VARCHAR2:
48+
case VARCHAR2_BYTE:
49+
case VARCHAR2_CHAR:
50+
if (varcharSize != null) {
51+
builder.append("(");
52+
builder.append(varcharSize);
53+
switch (type) {
54+
case VARCHAR2_BYTE:
55+
builder.append(" BYTE");
56+
break;
57+
case VARCHAR2_CHAR:
58+
builder.append(" CHAR");
59+
break;
60+
}
61+
builder.append(")");
62+
}
63+
break;
64+
default:
65+
// Nothing to do
66+
break;
67+
}
68+
return builder;
69+
}
70+
71+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*-
2+
* #%L
3+
* JSQLParser library
4+
* %%
5+
* Copyright (C) 2004 - 2021 JSQLParser
6+
* %%
7+
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
8+
* #L%
9+
*/
10+
/*
11+
* Copyright (C) 2021 JSQLParser.
12+
*
13+
* This library is free software; you can redistribute it and/or modify it under the terms of the
14+
* GNU Lesser General Public License as published by the Free Software Foundation; either version
15+
* 2.1 of the License, or (at your option) any later version.
16+
*
17+
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
18+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19+
* Lesser General Public License for more details.
20+
*
21+
* You should have received a copy of the GNU Lesser General Public License along with this library;
22+
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23+
* 02110-1301 USA
24+
*/
25+
26+
package net.sf.jsqlparser.expression;
27+
28+
/**
29+
*
30+
*/
31+
public enum JsonReturnType {
32+
VARCHAR2("VARCHAR2"), CLOB("CLOB"), BLOB("BLOB"), NUMBER("NUMBER"), DATE("DATE"), TIMESTAMP(
33+
"TIMESTAMP"), TIMESTAMP_WITH_TIMEZONE(
34+
"TIMESTAMP WITH TIMEZONE"), BOOLEAN("BOOLEAN"), VECTOR("VECTOR"), JSON("JSON"),
35+
36+
// VARCHAR2( x BYTE)
37+
VARCHAR2_BYTE("VARCHAR2"),
38+
39+
// VARCHAR2( x CHAR)
40+
VARCHAR2_CHAR("VARCHAR2"),
41+
;
42+
43+
private final String value;
44+
45+
JsonReturnType(String value) {
46+
this.value = value;
47+
}
48+
49+
public String getValue() {
50+
return value;
51+
}
52+
53+
public static JsonReturnType from(String type) {
54+
return Enum.valueOf(JsonReturnType.class, type.toUpperCase());
55+
}
56+
57+
/**
58+
* @see "https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/JSON_QUERY.html#GUID-6D396EC4-D2AA-43D2-8F5D-08D646A4A2D9__CJADJIIJ"
59+
*/
60+
public boolean isValidForJsonQueryReturnType() {
61+
switch (this) {
62+
case VARCHAR2:
63+
case CLOB:
64+
case BLOB:
65+
case JSON:
66+
case VECTOR:
67+
return true;
68+
default:
69+
return false;
70+
}
71+
}
72+
73+
}

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

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package net.sf.jsqlparser.expression;
22

33
import net.sf.jsqlparser.parser.ASTNodeAccessImpl;
4+
import net.sf.jsqlparser.statement.select.AbstractFromitem;
5+
import net.sf.jsqlparser.statement.select.FromItem;
6+
import net.sf.jsqlparser.statement.select.FromItemVisitor;
47

58
import java.util.ArrayList;
69
import java.util.List;
710

8-
public class JsonTable extends ASTNodeAccessImpl implements Expression {
11+
public class JsonTable extends AbstractFromitem implements FromItem {
912

1013
private Expression expression;
1114
private boolean isFormatJson = false;
@@ -18,7 +21,6 @@ public class JsonTable extends ASTNodeAccessImpl implements Expression {
1821

1922
private List<JsonTableColumn> jsonColumns = new ArrayList<>();
2023

21-
2224
public StringBuilder append(StringBuilder builder) {
2325
builder.append("JSON_TABLE(");
2426
builder.append(expression.toString());
@@ -28,8 +30,9 @@ public StringBuilder append(StringBuilder builder) {
2830
}
2931

3032
if (pathExpression != null) {
31-
builder.append(", ");
33+
builder.append(", '");
3234
builder.append(pathExpression);
35+
builder.append("'");
3336
}
3437

3538
if (onErrorType != null) {
@@ -57,12 +60,10 @@ public StringBuilder append(StringBuilder builder) {
5760
}
5861

5962
builder.append("))");
60-
return builder;
61-
}
6263

63-
@Override
64-
public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
65-
return expressionVisitor.visit(this, context);
64+
super.appendTo(builder, getAlias(), getSampleClause(), getPivot(), getUnPivot());
65+
66+
return builder;
6667
}
6768

6869
public void setExpression(Expression expression) {
@@ -105,9 +106,25 @@ public JsonTable withFormatJson(boolean isFormatJson) {
105106
}
106107

107108
public void setOnErrorType(JsonOnErrorType onErrorType) {
109+
if (onErrorType != null) {
110+
switch (onErrorType) {
111+
case NULL:
112+
case ERROR:
113+
break;
114+
default:
115+
throw new IllegalArgumentException(
116+
"OnError type " + onErrorType + " is not allowed in JSON_TABLE");
117+
}
118+
}
119+
108120
this.onErrorType = onErrorType;
109121
}
110122

123+
/**
124+
* Returns the ON ERROR clause or NULL if none is set
125+
*
126+
* @return JsonOnErrorType or NULL
127+
*/
111128
public JsonOnErrorType getOnErrorType() {
112129
return onErrorType;
113130
}
@@ -131,9 +148,24 @@ public JsonTable withType(JsonTableType type) {
131148
}
132149

133150
public void setOnEmptyType(JsonOnEmptyType onEmptyType) {
151+
if (onEmptyType != null) {
152+
switch (onEmptyType) {
153+
case NULL:
154+
case ERROR:
155+
break;
156+
default:
157+
throw new IllegalArgumentException(
158+
"OnEmpty type " + onEmptyType + " is not allowed in JSON_TABLE");
159+
}
160+
}
134161
this.onEmptyType = onEmptyType;
135162
}
136163

164+
/**
165+
* Returns the ON EMPTY clause or NULL if none is set
166+
*
167+
* @return JsonOnEmptyType or NULL
168+
*/
137169
public JsonOnEmptyType getOnEmptyType() {
138170
return onEmptyType;
139171
}
@@ -147,8 +179,22 @@ public void addColumn(JsonTableColumn column) {
147179
this.jsonColumns.add(column);
148180
}
149181

182+
public JsonTable withColumn(JsonTableColumn column) {
183+
addColumn(column);
184+
return this;
185+
}
186+
150187
public List<JsonTableColumn> getColumns() {
151188
return jsonColumns;
152189
}
153190

191+
@Override
192+
public String toString() {
193+
return append(new StringBuilder()).toString();
194+
}
195+
196+
@Override
197+
public <T, S> T accept(FromItemVisitor<T> fromItemVisitor, S context) {
198+
return fromItemVisitor.visit(this, context);
199+
}
154200
}

0 commit comments

Comments
 (0)