Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -3364,6 +3364,40 @@ static Expression call(Method method, @Nullable Expression target,
}
}

/** Base class for the implementors of {@code JSON_VALUE} and
* {@code JSON_QUERY}. */
private abstract static class JsonImplementor extends MethodImplementor {
JsonImplementor(Method method) {
super(method, NullPolicy.ARG0, false);
}

/** Calls the runtime method with {@code operands}, followed by the
* {@link SqlTypeName}, precision and scale of {@code returningType} and
* the rounding mode that a {@code CAST} to it would use.
*
* <p>A null {@code returningType} is passed as
* {@link SqlTypeName#ANY}, meaning no conversion. */
Expression callWithReturningType(RexToLixTranslator translator,
List<Expression> operands, @Nullable RelDataType returningType) {
operands.add(
Expressions.constant(returningType == null ? SqlTypeName.ANY
: returningType.getSqlTypeName()));
operands.add(
Expressions.constant(
returningType == null ? -1 : returningType.getPrecision()));
operands.add(
Expressions.constant(
returningType == null ? -1 : returningType.getScale()));
operands.add(
Expressions.constant(
translator.typeFactory.getTypeSystem().roundingMode()));
return Expressions.call(
Expressions.new_(method.getDeclaringClass()),
method,
EnumUtils.fromInternal(method.getParameterTypes(), operands));
}
}

/**
* Implementor for JSON_VALUE function, convert to solid format
* "JSON_VALUE(json_doc, path, empty_behavior, empty_default, error_behavior, error default)"
Expand All @@ -3372,9 +3406,9 @@ static Expression call(Method method, @Nullable Expression target,
* <p>We should avoid this when we support
* variable arguments function.
*/
private static class JsonValueImplementor extends MethodImplementor {
private static class JsonValueImplementor extends JsonImplementor {
JsonValueImplementor(Method method) {
super(method, NullPolicy.ARG0, false);
super(method);
}

@Override Expression implementSafe(RexToLixTranslator translator,
Expand Down Expand Up @@ -3421,20 +3455,16 @@ private static class JsonValueImplementor extends MethodImplementor {
newOperands.add(defaultValueOnEmpty);
newOperands.add(errorBehavior);
newOperands.add(defaultValueOnError);
List<Expression> argValueList0 =
EnumUtils.fromInternal(method.getParameterTypes(), newOperands);
final Expression target =
Expressions.new_(method.getDeclaringClass());
return Expressions.call(target, method, argValueList0);
return callWithReturningType(translator, newOperands, call.getType());
}
}

/**
* Implementor for JSON_QUERY function. Passes the jsonize flag depending on the output type.
*/
private static class JsonQueryImplementor extends MethodImplementor {
private static class JsonQueryImplementor extends JsonImplementor {
JsonQueryImplementor(Method method) {
super(method, NullPolicy.ARG0, false);
super(method);
}

@Override Expression implementSafe(RexToLixTranslator translator,
Expand All @@ -3449,11 +3479,18 @@ private static class JsonQueryImplementor extends MethodImplementor {
}
newOperands.add(jsonize);

List<Expression> argValueList0 =
EnumUtils.fromInternal(method.getParameterTypes(), newOperands);
final Expression target =
Expressions.new_(method.getDeclaringClass());
return Expressions.call(target, method, argValueList0);
// How deeply an array RETURNING clause nests, and the type of its
// innermost elements. A clause that gives no array type nests zero
// deep, and its element type is passed as null, for no conversion.
RelDataType elementType = call.getType();
int arrayDepth = 0;
while (elementType.getSqlTypeName() == SqlTypeName.ARRAY) {
elementType = requireNonNull(elementType.getComponentType());
++arrayDepth;
}
newOperands.add(Expressions.constant(arrayDepth));
return callWithReturningType(translator, newOperands,
arrayDepth == 0 ? null : elementType);
}
}

Expand Down
96 changes: 82 additions & 14 deletions core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.apache.calcite.sql.SqlJsonQueryEmptyOrErrorBehavior;
import org.apache.calcite.sql.SqlJsonQueryWrapperBehavior;
import org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.Util;

import com.fasterxml.jackson.annotation.JsonValue;
Expand All @@ -43,6 +44,7 @@
import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf;
import org.checkerframework.checker.nullness.qual.Nullable;

import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
Expand Down Expand Up @@ -238,39 +240,59 @@
}
}

public @Nullable Object jsonValue(String input,

Check warning on line 243 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 10 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCl&open=AaDA3p-ozfGa7GK7HiCl&pullRequest=5276
String pathSpec,
SqlJsonValueEmptyOrErrorBehavior emptyBehavior,
Object defaultValueOnEmpty,
SqlJsonValueEmptyOrErrorBehavior errorBehavior,
Object defaultValueOnError) {
Object defaultValueOnError,
SqlTypeName returningType,
int precision,
int scale,
RoundingMode roundingMode) {
return jsonValue(
jsonApiCommonSyntaxWithCache(input, pathSpec),
emptyBehavior,
defaultValueOnEmpty,
errorBehavior,
defaultValueOnError);
defaultValueOnError,
returningType,
precision,
scale,
roundingMode);
}

public @Nullable Object jsonValue(JsonValueContext input,

Check warning on line 265 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 10 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCm&open=AaDA3p-ozfGa7GK7HiCm&pullRequest=5276
String pathSpec,
SqlJsonValueEmptyOrErrorBehavior emptyBehavior,
Object defaultValueOnEmpty,
SqlJsonValueEmptyOrErrorBehavior errorBehavior,
Object defaultValueOnError) {
Object defaultValueOnError,
SqlTypeName returningType,
int precision,
int scale,
RoundingMode roundingMode) {
return jsonValue(
jsonApiCommonSyntax(input, pathSpec),
emptyBehavior,
defaultValueOnEmpty,
errorBehavior,
defaultValueOnError);
defaultValueOnError,
returningType,
precision,
scale,
roundingMode);
}

public @Nullable Object jsonValue(JsonPathContext context,

Check failure on line 287 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCr&open=AaDA3p-ozfGa7GK7HiCr&pullRequest=5276

Check warning on line 287 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 9 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCn&open=AaDA3p-ozfGa7GK7HiCn&pullRequest=5276
SqlJsonValueEmptyOrErrorBehavior emptyBehavior,
Object defaultValueOnEmpty,
SqlJsonValueEmptyOrErrorBehavior errorBehavior,
Object defaultValueOnError) {
Object defaultValueOnError,
SqlTypeName returningType,
int precision,
int scale,
RoundingMode roundingMode) {
final Exception exc;
if (context.hasException()) {
exc = context.exc;
Expand All @@ -284,7 +306,8 @@
case NULL:
return null;
case DEFAULT:
return defaultValueOnEmpty;
return convertDefaultValue(defaultValueOnEmpty, returningType,
precision, scale, roundingMode);
default:
throw RESOURCE.illegalEmptyBehaviorInJsonValueFunc(
emptyBehavior.toString()).ex();
Expand All @@ -295,7 +318,13 @@
RESOURCE.scalarValueRequiredInStrictModeOfJsonValueFunc(
value.toString()).ex();
} else {
return value;
try {
return SqlFunctions.cast(value, returningType, precision, scale,
roundingMode);
} catch (Exception e) {
// A failed conversion is an error, so ON ERROR applies.
exc = e;
}
}
}
switch (errorBehavior) {
Expand All @@ -304,42 +333,60 @@
case NULL:
return null;
case DEFAULT:
return defaultValueOnError;
return convertDefaultValue(defaultValueOnError, returningType,
precision, scale, roundingMode);
default:
throw RESOURCE.illegalErrorBehaviorInJsonValueFunc(
errorBehavior.toString()).ex();
}
}

public @Nullable Object jsonQuery(

Check warning on line 344 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 11 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCo&open=AaDA3p-ozfGa7GK7HiCo&pullRequest=5276
String input,
String pathSpec,
SqlJsonQueryWrapperBehavior wrapperBehavior,
SqlJsonQueryEmptyOrErrorBehavior emptyBehavior,
SqlJsonQueryEmptyOrErrorBehavior errorBehavior,
boolean jsonize) {
boolean jsonize,
int arrayDepth,
SqlTypeName elementType,
int precision,
int scale,
RoundingMode roundingMode) {
return jsonQuery(
jsonApiCommonSyntaxWithCache(input, pathSpec),
wrapperBehavior, emptyBehavior, errorBehavior, jsonize);
wrapperBehavior, emptyBehavior, errorBehavior, jsonize, arrayDepth,
elementType, precision, scale, roundingMode);
}

public @Nullable Object jsonQuery(JsonValueContext input,

Check warning on line 362 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 11 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCp&open=AaDA3p-ozfGa7GK7HiCp&pullRequest=5276
String pathSpec,
SqlJsonQueryWrapperBehavior wrapperBehavior,
SqlJsonQueryEmptyOrErrorBehavior emptyBehavior,
SqlJsonQueryEmptyOrErrorBehavior errorBehavior,
boolean jsonize) {
boolean jsonize,
int arrayDepth,
SqlTypeName elementType,
int precision,
int scale,
RoundingMode roundingMode) {
return jsonQuery(
jsonApiCommonSyntax(input, pathSpec),
wrapperBehavior, emptyBehavior, errorBehavior, jsonize);
wrapperBehavior, emptyBehavior, errorBehavior, jsonize, arrayDepth,
elementType, precision, scale, roundingMode);
}

public @Nullable Object jsonQuery(

Check warning on line 379 in core/src/main/java/org/apache/calcite/runtime/JsonFunctions.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Method has 10 parameters, which is greater than 7 authorized.

See more on https://sonarcloud.io/project/issues?id=apache_calcite&issues=AaDA3p-ozfGa7GK7HiCq&open=AaDA3p-ozfGa7GK7HiCq&pullRequest=5276
JsonPathContext context,
SqlJsonQueryWrapperBehavior wrapperBehavior,
SqlJsonQueryEmptyOrErrorBehavior emptyBehavior,
SqlJsonQueryEmptyOrErrorBehavior errorBehavior,
boolean jsonize) {
boolean jsonize,
int arrayDepth,
SqlTypeName elementType,
int precision,
int scale,
RoundingMode roundingMode) {
final Exception exc;
if (context.hasException()) {
exc = context.exc;
Expand Down Expand Up @@ -394,7 +441,13 @@
exc = e;
}
} else {
return value;
try {
return SqlFunctions.castArray(value, elementType, precision,
scale, roundingMode, arrayDepth);
} catch (Exception e) {
// A failed conversion is an error, so ON ERROR applies.
exc = e;
}
}
}
}
Expand All @@ -413,6 +466,21 @@
}
}

/** Converts the value of a {@code DEFAULT} clause to the type of the
* {@code RETURNING} clause.
*
* <p>The value is a SQL value of the type it was written as, not a
* value read from a JSON document, so the only conversion it can need is
* between numeric types, as in
* {@code RETURNING DOUBLE DEFAULT 1 ON EMPTY}. */
private static @Nullable Object convertDefaultValue(@Nullable Object value,
SqlTypeName typeName, int precision, int scale,
RoundingMode roundingMode) {
return SqlTypeName.NUMERIC_TYPES.contains(typeName)
? SqlFunctions.cast(value, typeName, precision, scale, roundingMode)
: value;
}

private static Object jsonQueryEmptyArray(boolean jsonize) {
return jsonize ? "[]" : Collections.emptyList();
}
Expand Down
Loading
Loading