Skip to content
Merged
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
21 changes: 19 additions & 2 deletions 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,7 +105,8 @@ public StringBuilder append(StringBuilder builder) {
builder.append("UNKNOWN");
break;
default:
// this should never happen
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
190 changes: 175 additions & 15 deletions src/main/java/net/sf/jsqlparser/expression/JsonTableFunction.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@
import net.sf.jsqlparser.statement.create.table.ColDataType;

public class JsonTableFunction extends Function {

private Expression jsonInputExpression;
private Expression jsonPathExpression;
private String pathName;
private final List<JsonTablePassingClause> passingClauses = new ArrayList<>();
private JsonTableColumnsClause columnsClause;
private JsonTablePlanClause planClause;
private JsonTableOnErrorClause onErrorClause;
private JsonTableParsingTypeClause parsingTypeClause;
private JsonTableOnEmptyClause onEmptyClause;
private boolean formatJson;

public enum JsonTablePlanOperator {
COMMA(", "), INNER(" INNER "), OUTER(" OUTER "), CROSS(" CROSS "), UNION(" UNION ");

Expand All @@ -33,7 +45,15 @@ public String getDisplay() {
}

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

public enum JsonTableOnEmptyType {
ERROR, NULL, EMPTY, TRUE, FALSE
}

public enum JsonTableParsingType {
STRICT, LAX
}

public static class JsonTablePassingClause extends ASTNodeAccessImpl implements Serializable {
Expand Down Expand Up @@ -78,10 +98,30 @@ 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 +199,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 +224,43 @@ public String toString() {
}
}

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

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 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 @@ -389,12 +475,15 @@ public static class JsonTableValueColumnDefinition extends JsonTableColumnDefini
private boolean forOrdinality;
private ColDataType dataType;
private boolean formatJson;
private boolean exists;
private boolean onEmptyAfterOnError;
private String encoding;
private Expression pathExpression;
private JsonTableWrapperClause wrapperClause;
private JsonTableQuotesClause quotesClause;
private JsonFunction.JsonOnResponseBehavior onEmptyBehavior;
private JsonFunction.JsonOnResponseBehavior onErrorBehavior;
private JsonFunction.ScalarsType scalarsType;

public String getColumnName() {
return columnName;
Expand All @@ -405,6 +494,20 @@ public JsonTableValueColumnDefinition setColumnName(String columnName) {
return this;
}

public boolean isExists() {
return exists;
}

public JsonTableValueColumnDefinition setExistsKeyword(boolean exists) {
this.exists = exists;
return this;
}

public JsonTableValueColumnDefinition setOnEmptyAfterOnError(boolean b) {
this.onEmptyAfterOnError = b;
return this;
}

public boolean isForOrdinality() {
return forOrdinality;
}
Expand Down Expand Up @@ -489,6 +592,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,29 +620,44 @@ public String toString() {
builder.append(" FOR ORDINALITY");
return builder.toString();
}

builder.append(" ").append(dataType);
if (exists) {
builder.append(" EXISTS");
}
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) {
builder.append(" ").append(quotesClause);
}
if (onEmptyBehavior != null) {
if (onEmptyBehavior != null && !onEmptyAfterOnError) {
builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
}
if (onErrorBehavior != null) {
builder.append(" ").append(onErrorBehavior).append(" ON ERROR");
}
if (onEmptyBehavior != null && onEmptyAfterOnError) {
builder.append(" ").append(onEmptyBehavior).append(" ON EMPTY");
}
return builder.toString();
}
}
Expand Down Expand Up @@ -573,18 +699,19 @@ public String toString() {
}
}

private Expression jsonInputExpression;
private Expression jsonPathExpression;
private String pathName;
private final List<JsonTablePassingClause> passingClauses = new ArrayList<>();
private JsonTableColumnsClause columnsClause;
private JsonTablePlanClause planClause;
private JsonTableOnErrorClause onErrorClause;

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 +775,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 +821,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 +842,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
Loading
Loading