Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@
exports net.sf.jsqlparser.util.validation.feature;
exports net.sf.jsqlparser.util.validation.metadata;
exports net.sf.jsqlparser.util.validation.validator;
exports net.sf.jsqlparser.expression.json;
exports net.sf.jsqlparser.statement.from;
}
19 changes: 18 additions & 1 deletion src/main/java/net/sf/jsqlparser/expression/JsonFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
*/
public class JsonFunction extends ASTNodeAccessImpl implements Expression {
public enum JsonOnResponseBehaviorType {
ERROR, NULL, DEFAULT, EMPTY_ARRAY, EMPTY_OBJECT, TRUE, FALSE, UNKNOWN
ERROR, NULL, DEFAULT, EMPTY, EMPTY_ARRAY, EMPTY_OBJECT, TRUE, FALSE, UNKNOWN
}

public enum JsonWrapperType {
Expand All @@ -42,6 +42,10 @@ public enum JsonQuotesType {
KEEP, OMIT
}

public enum ScalarsType {
ALLOW, DISALLOW
}

public static class JsonOnResponseBehavior {
private JsonOnResponseBehaviorType type;
private Expression expression;
Expand Down Expand Up @@ -82,6 +86,9 @@ public StringBuilder append(StringBuilder builder) {
case DEFAULT:
builder.append("DEFAULT ").append(expression);
break;
case EMPTY:
builder.append("EMPTY ");
break;
case EMPTY_ARRAY:
builder.append("EMPTY ARRAY");
break;
Expand All @@ -98,6 +105,7 @@ public StringBuilder append(StringBuilder builder) {
builder.append("UNKNOWN");
break;
default:
throw new IllegalStateException("Unhandled JsonOnResponseBehavior: " + type );
// this should never happen
}
return builder;
Expand Down Expand Up @@ -130,6 +138,7 @@ public String toString() {
private boolean wrapperArray;
private JsonQuotesType quotesType;
private boolean quotesOnScalarString;
private ScalarsType scalarsType;

public JsonFunction() {}

Expand Down Expand Up @@ -294,6 +303,14 @@ public void setQuotesOnScalarString(boolean quotesOnScalarString) {
this.quotesOnScalarString = quotesOnScalarString;
}

public ScalarsType getScalarsType() {
return scalarsType;
}

public void setScalarsType(ScalarsType type) {
this.scalarsType = type;
}

public boolean isEmpty() {
return keyValuePairs.isEmpty();
}
Expand Down
152 changes: 146 additions & 6 deletions src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,15 @@ public String getDisplay() {
}

public enum JsonTableOnErrorType {
ERROR, EMPTY
ERROR, NULL, EMPTY
}

public enum JsonTableOnEmptyType {
ERROR, NULL, EMPTY
}

public enum JsonTableParsingType {
STRICT, LAX
}

public static class JsonTablePassingClause extends ASTNodeAccessImpl implements Serializable {
Expand Down Expand Up @@ -78,10 +86,28 @@ public String toString() {
}

public static class JsonTableWrapperClause extends ASTNodeAccessImpl implements Serializable {
private boolean beforePathExpression;
private JsonFunction.JsonWrapperType wrapperType;
private JsonFunction.JsonWrapperMode wrapperMode;
private boolean array;

/**
* Creates a wrapper clause. Depending on the dialect, this clause can come before or after the PATH expression.
* <ul>
* <li>Trino: after PATH</li>
* <li>Oracle: before PATH</li>
* </ul>
*
* @param beforePathExpression A flag to determine wether the clause is rendered before or after the PATH expression
*/
public JsonTableWrapperClause(boolean beforePathExpression) {
this.beforePathExpression = beforePathExpression;
}

public boolean isBeforePathExpression() {
return beforePathExpression;
}

public JsonFunction.JsonWrapperType getWrapperType() {
return wrapperType;
}
Expand Down Expand Up @@ -159,6 +185,15 @@ public String toString() {

public static class JsonTableOnErrorClause extends ASTNodeAccessImpl implements Serializable {
private JsonTableOnErrorType type;
private boolean beforeColumns = true;

public JsonTableOnErrorClause(boolean beforeColumns) {
this.beforeColumns = beforeColumns;
}

public boolean isBeforeColumns() {
return beforeColumns;
}

public JsonTableOnErrorType getType() {
return type;
Expand All @@ -175,6 +210,48 @@ public String toString() {
}
}

public static class JsonTableOnEmptyClause extends ASTNodeAccessImpl implements Serializable {
private JsonTableOnEmptyType type;

public JsonTableOnEmptyClause() {
}

public JsonTableOnEmptyType getType() {
return type;
}

public JsonTableOnEmptyClause setType(JsonTableOnEmptyType type) {
this.type = type;
return this;
}

@Override
public String toString() {
return type + " ON EMPTY";
}
}

public static class JsonTableParsingTypeClause extends ASTNodeAccessImpl implements Serializable {
private JsonTableParsingType type;

public JsonTableParsingTypeClause() {
}

public JsonTableParsingType getType() {
return type;
}

public JsonTableParsingTypeClause setType(JsonTableParsingType type) {
this.type = type;
return this;
}

@Override
public String toString() {
return "TYPE(" + type + ")";
}
}

public static class JsonTablePlanTerm extends ASTNodeAccessImpl implements Serializable {
private JsonTablePlanExpression nestedPlanExpression;
private String name;
Expand Down Expand Up @@ -395,6 +472,7 @@ public static class JsonTableValueColumnDefinition extends JsonTableColumnDefini
private JsonTableQuotesClause quotesClause;
private JsonFunction.JsonOnResponseBehavior onEmptyBehavior;
private JsonFunction.JsonOnResponseBehavior onErrorBehavior;
private JsonFunction.ScalarsType scalarsType;

public String getColumnName() {
return columnName;
Expand Down Expand Up @@ -489,6 +567,14 @@ public JsonTableValueColumnDefinition setOnErrorBehavior(
return this;
}

public void setScalarsType(JsonFunction.ScalarsType scalarsType) {
this.scalarsType = scalarsType;
}

public JsonFunction.ScalarsType getScalarsType() {
return scalarsType;
}

@Override
public void collectExpressions(List<Expression> expressions) {
if (pathExpression != null) {
Expand All @@ -509,18 +595,27 @@ public String toString() {
builder.append(" FOR ORDINALITY");
return builder.toString();
}

builder.append(" ").append(dataType);
if (dataType != null) {
builder.append(" ").append(dataType);
}
if (formatJson) {
builder.append(" FORMAT JSON");
if (encoding != null) {
builder.append(" ENCODING ").append(encoding);
}
}
if (scalarsType != null) {
builder.append(" ");
builder.append(scalarsType);
builder.append(" SCALARS");
}
if (wrapperClause != null && wrapperClause.isBeforePathExpression()) {
builder.append(" ").append(wrapperClause);
}
if (pathExpression != null) {
builder.append(" PATH ").append(pathExpression);
}
if (wrapperClause != null) {
if (wrapperClause != null && !wrapperClause.isBeforePathExpression()) {
builder.append(" ").append(wrapperClause);
}
if (quotesClause != null) {
Expand Down Expand Up @@ -580,11 +675,23 @@ public String toString() {
private JsonTableColumnsClause columnsClause;
private JsonTablePlanClause planClause;
private JsonTableOnErrorClause onErrorClause;
private JsonTableParsingTypeClause parsingTypeClause;
private JsonTableOnEmptyClause onEmptyClause;
private boolean formatJson;

public JsonTableFunction() {
setName("JSON_TABLE");
}

public boolean getFormatJson() {
return formatJson;
}

public JsonTableFunction setFormatJson(boolean formatJson) {
this.formatJson = formatJson;
return this;
}

public Expression getJsonInputExpression() {
return jsonInputExpression;
}
Expand Down Expand Up @@ -648,6 +755,24 @@ public JsonTableFunction setOnErrorClause(JsonTableOnErrorClause onErrorClause)
return this;
}

public JsonTableParsingTypeClause getParsingTypeClause() {
return parsingTypeClause;
}

public JsonTableFunction setParsingTypeClause(JsonTableParsingTypeClause parsingTypeClause) {
this.parsingTypeClause = parsingTypeClause;
return this;
}

public JsonTableOnEmptyClause getOnEmptyClause() {
return onEmptyClause;
}

public JsonTableFunction setOnEmptyClause(JsonTableOnEmptyClause onEmptyClause) {
this.onEmptyClause = onEmptyClause;
return this;
}

public List<Expression> getAllExpressions() {
List<Expression> expressions = new ArrayList<>();
if (jsonInputExpression != null) {
Expand Down Expand Up @@ -676,7 +801,13 @@ public <T, S> T accept(ExpressionVisitor<T> expressionVisitor, S context) {
@Override
public String toString() {
StringBuilder builder = new StringBuilder("JSON_TABLE(");
builder.append(jsonInputExpression).append(", ").append(jsonPathExpression);
builder.append(jsonInputExpression);
if (formatJson) {
builder.append(" FORMAT JSON");
}
if (jsonPathExpression != null) {
builder.append(", ").append(jsonPathExpression);
}
if (pathName != null) {
builder.append(" AS ").append(pathName);
}
Expand All @@ -691,11 +822,20 @@ public String toString() {
first = false;
}
}
if (onErrorClause != null && onErrorClause.isBeforeColumns()) {
builder.append(" ").append(onErrorClause);
}
if (parsingTypeClause != null) {
builder.append(" ").append(parsingTypeClause);
}
if (onEmptyClause != null) {
builder.append(" ").append(onEmptyClause);
}
builder.append(" ").append(columnsClause);
if (planClause != null) {
builder.append(" ").append(planClause);
}
if (onErrorClause != null) {
if (onErrorClause != null && !onErrorClause.isBeforeColumns()) {
builder.append(" ").append(onErrorClause);
}
builder.append(")");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*-
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2021 JSQLParser
* %%
* Dual licensed under GNU LGPL 2.1 or Apache License 2.0
* #L%
*/
/*
* Copyright (C) 2021 JSQLParser.
*
* This library is free software; you can redistribute it and/or modify it under the terms of the
* GNU Lesser General Public License as published by the Free Software Foundation; either version
* 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this library;
* if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/

package net.sf.jsqlparser.expression.json;

/**
*
*/
public enum JsonOnEmptyType {
ERROR("ERROR"), NULL("NULL"), EMPTY("EMPTY"), EMPTY_ARRAY("EMPTY ARRAY"), EMPTY_OBJECT(
"EMPTY OBJECT"), TRUE("TRUE"), FALSE("FALSE"), DEFAULT("DEFAULT");

private final String value;

JsonOnEmptyType(String value) {
this.value = value;
}

public String getValue() {
return value;
}

public static JsonOnEmptyType from(String type) {
return Enum.valueOf(JsonOnEmptyType.class, type.toUpperCase());
}
}
Loading
Loading