Search in sources :

Example 1 with SqlJsonValueEmptyOrErrorBehavior

use of org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior in project flink by apache.

the class JsonValueConverter method getBehaviorOperands.

private List<RexNode> getBehaviorOperands(CallExpression call, CallExpressionConvertRule.ConvertContext context, SqlJsonEmptyOrError mode) {
    final int idx = getArgumentIndexForBehavior(mode);
    final SqlJsonValueEmptyOrErrorBehavior behavior = getBehavior(call, idx);
    final Expression defaultExpression = call.getChildren().get(idx + 1);
    final List<RexNode> operands = new ArrayList<>();
    operands.add(context.getRelBuilder().getRexBuilder().makeFlag(behavior));
    if (behavior == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
        operands.add(context.toRexNode(defaultExpression));
    }
    operands.add(context.getRelBuilder().getRexBuilder().makeFlag(mode));
    return operands;
}
Also used : CallExpression(org.apache.flink.table.expressions.CallExpression) Expression(org.apache.flink.table.expressions.Expression) ValueLiteralExpression(org.apache.flink.table.expressions.ValueLiteralExpression) ArrayList(java.util.ArrayList) SqlJsonValueEmptyOrErrorBehavior(org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior) RexNode(org.apache.calcite.rex.RexNode)

Example 2 with SqlJsonValueEmptyOrErrorBehavior

use of org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior in project hazelcast by hazelcast.

the class HazelcastSqlToRelConverter method convertJsonValueCall.

/**
 * Converts JSON_VALUE calls with extended syntax, with RETURNING clause among other things.
 * Because there is no RexNode for type reference in Calcite (see CAST implementation),
 * the type has to be instead set as the type of the parent (JSON_VALUE's RexCall), which is
 * then interpreted as the desired type of the expression.
 * <p>
 * Supported syntax:
 * JSON_VALUE(jsonArg, jsonPathArg [returning] [onEmpty|onError])
 * returning: RETURNING dataType
 * onEmpty: (DEFAULT value | NULL | ERROR) ON EMPTY
 * onError: (DEFAULT value | NULL | ERROR) ON ERROR
 */
private RexNode convertJsonValueCall(SqlCall call, Blackboard bb) {
    RexNode target = bb.convertExpression(call.operand(0));
    RexNode path = bb.convertExpression(call.operand(1));
    SqlJsonValueEmptyOrErrorBehavior onError = SqlJsonValueEmptyOrErrorBehavior.NULL;
    SqlJsonValueEmptyOrErrorBehavior onEmpty = SqlJsonValueEmptyOrErrorBehavior.NULL;
    RelDataType returning = validator.getTypeFactory().createSqlType(SqlTypeName.VARCHAR);
    RexNode defaultValueOnError = getRexBuilder().makeNullLiteral(typeFactory.createSqlType(SqlTypeName.ANY));
    RexNode defaultValueOnEmpty = getRexBuilder().makeNullLiteral(typeFactory.createSqlType(SqlTypeName.ANY));
    // Start at 3rd Arg
    int tokenIndex = 2;
    // RETURNING can only be placed at the beginning, never in the middle or the end of the list of tokens.
    if (call.operandCount() > 2 && isJsonValueReturningClause(call.operand(tokenIndex))) {
        returning = validator.getValidatedNodeType(call.operand(tokenIndex + 1));
        tokenIndex += 2;
    }
    boolean onEmptyDefined = false;
    boolean onErrorDefined = false;
    while (tokenIndex < call.operandCount()) {
        if (!(call.operand(tokenIndex) instanceof SqlLiteral)) {
            throw QueryException.error(SqlErrorCode.PARSING, "Unsupported JSON_VALUE extended syntax");
        }
        final SqlJsonValueEmptyOrErrorBehavior behavior = (SqlJsonValueEmptyOrErrorBehavior) ((SqlLiteral) call.operand(tokenIndex)).getValue();
        RexNode defaultExpr = getRexBuilder().makeNullLiteral(typeFactory.createSqlType(SqlTypeName.ANY));
        if (behavior == null) {
            throw QueryException.error(SqlErrorCode.PARSING, "Failed to extract ON behavior for JSON_VALUE call");
        }
        switch(behavior) {
            case DEFAULT:
                defaultExpr = bb.convertExpression(call.operand(tokenIndex + 1));
                tokenIndex += 2;
                break;
            case NULL:
            case ERROR:
                tokenIndex++;
                break;
            default:
                // guard against possible unsupported updates to syntax, should never be thrown.
                throw QueryException.error(SqlErrorCode.PARSING, "Unsupported JSON_VALUE OnEmptyOrErrorBehavior");
        }
        final SqlJsonEmptyOrError onTarget = (SqlJsonEmptyOrError) ((SqlLiteral) call.operand(tokenIndex)).getValue();
        if (onTarget == null) {
            throw QueryException.error(SqlErrorCode.PARSING, "Failed to extract ON-behavior target for JSON_VALUE call");
        }
        switch(onTarget) {
            case EMPTY:
                if (onEmptyDefined) {
                    throw QueryException.error(SqlErrorCode.PARSING, "Duplicate ON EMPTY clause in JSON_VALUE call");
                }
                if (behavior == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
                    defaultValueOnEmpty = defaultExpr;
                }
                onEmpty = behavior;
                onEmptyDefined = true;
                break;
            case ERROR:
                if (onErrorDefined) {
                    throw QueryException.error(SqlErrorCode.PARSING, "Duplicate ON ERROR clause in JSON_VALUE call");
                }
                if (behavior == SqlJsonValueEmptyOrErrorBehavior.DEFAULT) {
                    defaultValueOnError = defaultExpr;
                }
                onError = behavior;
                onErrorDefined = true;
                break;
            default:
                // guard against possible unsupported updates to syntax, should never be thrown.
                throw QueryException.error(SqlErrorCode.PARSING, "Unsupported JSON_VALUE EmptyOrErrorBehavior target");
        }
        tokenIndex++;
    }
    return getRexBuilder().makeCall(returning, HazelcastJsonValueFunction.INSTANCE, asList(target, path, defaultValueOnEmpty, defaultValueOnError, bb.convertLiteral(onEmpty.symbol(SqlParserPos.ZERO)), bb.convertLiteral(onError.symbol(SqlParserPos.ZERO))));
}
Also used : SqlJsonEmptyOrError(org.apache.calcite.sql.SqlJsonEmptyOrError) RelDataType(org.apache.calcite.rel.type.RelDataType) SqlJsonValueEmptyOrErrorBehavior(org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior) SqlLiteral(org.apache.calcite.sql.SqlLiteral) RexNode(org.apache.calcite.rex.RexNode)

Example 3 with SqlJsonValueEmptyOrErrorBehavior

use of org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior in project hazelcast by hazelcast.

the class RexToExpression method convertCall.

/**
 * Converts a {@link RexCall} to {@link Expression}.
 *
 * @param call the call to convert.
 * @return the resulting expression.
 * @throws QueryException if the given {@link RexCall} can't be
 *                        converted.
 */
@SuppressWarnings({ "checkstyle:CyclomaticComplexity", "checkstyle:MethodLength", "checkstyle:ReturnCount", "checkstyle:NPathComplexity", "checkstyle:MagicNumber" })
public static Expression<?> convertCall(RexCall call, Expression<?>[] operands) {
    SqlOperator operator = call.getOperator();
    QueryDataType resultType = HazelcastTypeUtils.toHazelcastType(call.getType());
    switch(operator.getKind()) {
        case DEFAULT:
            return ConstantExpression.create(null, resultType);
        case CAST:
            if (operands[0].getType().equals(resultType)) {
                // nullable ones after the conversion.
                return operands[0];
            }
            return CastExpression.create(operands[0], resultType);
        case AND:
            return AndPredicate.create(operands);
        case OR:
            return OrPredicate.create(operands);
        case NOT:
            return NotPredicate.create(operands[0]);
        case PLUS:
            return PlusFunction.create(operands[0], operands[1], resultType);
        case MINUS:
            return MinusFunction.create(operands[0], operands[1], resultType);
        case TIMES:
            return MultiplyFunction.create(operands[0], operands[1], resultType);
        case DIVIDE:
            return DivideFunction.create(operands[0], operands[1], resultType);
        case MOD:
            return RemainderFunction.create(operands[0], operands[1], resultType);
        case MINUS_PREFIX:
            return UnaryMinusFunction.create(operands[0], resultType);
        case PLUS_PREFIX:
            return operands[0];
        case FLOOR:
            return FloorCeilFunction.create(operands[0], resultType, false);
        case CEIL:
            return FloorCeilFunction.create(operands[0], resultType, true);
        case EQUALS:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.EQUALS);
        case NOT_EQUALS:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.NOT_EQUALS);
        case GREATER_THAN:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.GREATER_THAN);
        case GREATER_THAN_OR_EQUAL:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.GREATER_THAN_OR_EQUAL);
        case LESS_THAN:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.LESS_THAN);
        case LESS_THAN_OR_EQUAL:
            return ComparisonPredicate.create(operands[0], operands[1], ComparisonMode.LESS_THAN_OR_EQUAL);
        case SEARCH:
            return SearchPredicate.create(operands[0], operands[1]);
        case IS_TRUE:
            return IsTruePredicate.create(operands[0]);
        case IS_NOT_TRUE:
            return IsNotTruePredicate.create(operands[0]);
        case IS_FALSE:
            return IsFalsePredicate.create(operands[0]);
        case IS_NOT_FALSE:
            return IsNotFalsePredicate.create(operands[0]);
        case IS_NULL:
            return IsNullPredicate.create(operands[0]);
        case IS_NOT_NULL:
            return IsNotNullPredicate.create(operands[0]);
        case LIKE:
            boolean negated = ((HazelcastLikeOperator) operator).isNegated();
            Expression<?> escape1 = operands.length == 2 ? null : operands[2];
            return LikeFunction.create(operands[0], operands[1], escape1, negated);
        case TRIM:
            assert operands.length == 3;
            assert operands[0] instanceof SymbolExpression;
            SqlTrimFunction.Flag trimFlag = ((SymbolExpression) operands[0]).getSymbol();
            return TrimFunction.create(operands[2], operands[1], trimFlag.getLeft() == 1, trimFlag.getRight() == 1);
        case EXTRACT:
            assert operands.length == 2;
            assert operands[0] instanceof SymbolExpression;
            TimeUnitRange field = ((SymbolExpression) operands[0]).getSymbol();
            ExtractField extractField = convertField(field);
            return ExtractFunction.create(operands[1], extractField);
        case CASE:
            return CaseExpression.create(operands);
        case COALESCE:
            return CaseExpression.coalesce(operands);
        case NULLIF:
            return CaseExpression.nullif(operands[0], operands[1]);
        case OTHER:
            if (operator == HazelcastSqlOperatorTable.CONCAT) {
                assert operands.length == 2;
                return ConcatFunction.create(operands[0], operands[1]);
            }
            if (operator == HazelcastSqlOperatorTable.NOT_LIKE) {
                assert ((HazelcastLikeOperator) operator).isNegated();
                Expression<?> escape2 = operands.length == 2 ? null : operands[2];
                return LikeFunction.create(operands[0], operands[1], escape2, true);
            }
            break;
        case POSITION:
        case OTHER_FUNCTION:
            SqlFunction function = (SqlFunction) operator;
            // Math.
            if (function == HazelcastSqlOperatorTable.POWER) {
                assert operands.length == 2;
                return DoubleBiFunction.create(operands[0], operands[1], DoubleBiFunction.POWER);
            } else if (function == HazelcastSqlOperatorTable.SQUARE) {
                return DoubleFunction.create(operands[0], DoubleFunction.SQUARE);
            } else if (function == HazelcastSqlOperatorTable.SQRT) {
                return DoubleFunction.create(operands[0], DoubleFunction.SQRT);
            } else if (function == HazelcastSqlOperatorTable.CBRT) {
                return DoubleFunction.create(operands[0], DoubleFunction.CBRT);
            } else if (function == HazelcastSqlOperatorTable.COS) {
                return DoubleFunction.create(operands[0], DoubleFunction.COS);
            } else if (function == HazelcastSqlOperatorTable.SIN) {
                return DoubleFunction.create(operands[0], DoubleFunction.SIN);
            } else if (function == HazelcastSqlOperatorTable.TAN) {
                return DoubleFunction.create(operands[0], DoubleFunction.TAN);
            } else if (function == HazelcastSqlOperatorTable.COT) {
                return DoubleFunction.create(operands[0], DoubleFunction.COT);
            } else if (function == HazelcastSqlOperatorTable.ACOS) {
                return DoubleFunction.create(operands[0], DoubleFunction.ACOS);
            } else if (function == HazelcastSqlOperatorTable.ASIN) {
                return DoubleFunction.create(operands[0], DoubleFunction.ASIN);
            } else if (function == HazelcastSqlOperatorTable.ATAN) {
                return DoubleFunction.create(operands[0], DoubleFunction.ATAN);
            } else if (function == HazelcastSqlOperatorTable.ATAN2) {
                assert operands.length == 2;
                return DoubleBiFunction.create(operands[0], operands[1], DoubleBiFunction.ATAN2);
            } else if (function == HazelcastSqlOperatorTable.EXP) {
                return DoubleFunction.create(operands[0], DoubleFunction.EXP);
            } else if (function == HazelcastSqlOperatorTable.LN) {
                return DoubleFunction.create(operands[0], DoubleFunction.LN);
            } else if (function == HazelcastSqlOperatorTable.LOG10) {
                return DoubleFunction.create(operands[0], DoubleFunction.LOG10);
            } else if (function == HazelcastSqlOperatorTable.RAND) {
                return RandFunction.create(operands.length == 0 ? null : operands[0]);
            } else if (function == HazelcastSqlOperatorTable.ABS) {
                return AbsFunction.create(operands[0], resultType);
            } else if (function == SqlStdOperatorTable.PI) {
                return ConstantExpression.create(Math.PI, resultType);
            } else if (function == HazelcastSqlOperatorTable.SIGN) {
                return SignFunction.create(operands[0], resultType);
            } else if (function == HazelcastSqlOperatorTable.DEGREES) {
                return DoubleFunction.create(operands[0], DoubleFunction.DEGREES);
            } else if (function == HazelcastSqlOperatorTable.RADIANS) {
                return DoubleFunction.create(operands[0], DoubleFunction.RADIANS);
            } else if (function == HazelcastSqlOperatorTable.ROUND) {
                return RoundTruncateFunction.create(operands[0], operands.length == 1 ? null : operands[1], resultType, false);
            } else if (function == HazelcastSqlOperatorTable.TRUNCATE) {
                return RoundTruncateFunction.create(operands[0], operands.length == 1 ? null : operands[1], resultType, true);
            }
            if (function == CHAR_LENGTH || function == CHARACTER_LENGTH || function == LENGTH) {
                return CharLengthFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.UPPER) {
                return UpperFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.LOWER) {
                return LowerFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.INITCAP) {
                return InitcapFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.ASCII) {
                return AsciiFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.SUBSTRING) {
                Expression<?> input = operands[0];
                Expression<?> start = operands[1];
                Expression<?> length = operands.length > 2 ? operands[2] : null;
                return SubstringFunction.create(input, start, length);
            } else if (function == HazelcastSqlOperatorTable.LTRIM) {
                return TrimFunction.create(operands[0], null, true, false);
            } else if (function == HazelcastSqlOperatorTable.RTRIM) {
                return TrimFunction.create(operands[0], null, false, true);
            } else if (function == HazelcastSqlOperatorTable.BTRIM) {
                return TrimFunction.create(operands[0], null, true, true);
            } else if (function == HazelcastSqlOperatorTable.REPLACE) {
                return ReplaceFunction.create(operands[0], operands[1], operands[2]);
            } else if (function == HazelcastSqlOperatorTable.POSITION) {
                Expression<?> start = operands.length > 2 ? operands[2] : null;
                return PositionFunction.create(operands[0], operands[1], start);
            } else if (function == HazelcastSqlOperatorTable.TO_TIMESTAMP_TZ) {
                return ToTimestampTzFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.TO_EPOCH_MILLIS) {
                return ToEpochMillisFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.CONCAT_WS) {
                return ConcatWSFunction.create(operands);
            } else if (function == HazelcastSqlOperatorTable.JSON_QUERY) {
                final SqlJsonQueryWrapperBehavior wrapperBehavior = ((SymbolExpression) operands[2]).getSymbol();
                final SqlJsonQueryEmptyOrErrorBehavior onEmpty = ((SymbolExpression) operands[3]).getSymbol();
                final SqlJsonQueryEmptyOrErrorBehavior onError = ((SymbolExpression) operands[4]).getSymbol();
                return JsonQueryFunction.create(operands[0], operands[1], wrapperBehavior, onEmpty, onError);
            } else if (function == HazelcastJsonParseFunction.INSTANCE) {
                return JsonParseFunction.create(operands[0]);
            } else if (function == HazelcastSqlOperatorTable.JSON_VALUE) {
                final SqlJsonValueEmptyOrErrorBehavior onEmpty = ((SymbolExpression) operands[4]).getSymbol();
                final SqlJsonValueEmptyOrErrorBehavior onError = ((SymbolExpression) operands[5]).getSymbol();
                return JsonValueFunction.create(operands[0], operands[1], operands[2], operands[3], resultType, onEmpty, onError);
            } else if (function == HazelcastSqlOperatorTable.JSON_OBJECT) {
                final SqlJsonConstructorNullClause nullClause = ((SymbolExpression) operands[0]).getSymbol();
                final Expression<?>[] fields = Arrays.copyOfRange(operands, 1, operands.length);
                return JsonObjectFunction.create(fields, nullClause);
            } else if (function == HazelcastSqlOperatorTable.JSON_ARRAY) {
                final SqlJsonConstructorNullClause nullClause = ((SymbolExpression) operands[0]).getSymbol();
                final Expression<?>[] fields = Arrays.copyOfRange(operands, 1, operands.length);
                return JsonArrayFunction.create(fields, nullClause);
            }
            break;
        default:
            break;
    }
    throw QueryException.error("Unsupported operator: " + operator);
}
Also used : SqlOperator(org.apache.calcite.sql.SqlOperator) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType) TimeUnitRange(org.apache.calcite.avatica.util.TimeUnitRange) HazelcastLikeOperator(com.hazelcast.jet.sql.impl.validate.operators.string.HazelcastLikeOperator) SqlJsonQueryWrapperBehavior(org.apache.calcite.sql.SqlJsonQueryWrapperBehavior) SqlJsonQueryEmptyOrErrorBehavior(org.apache.calcite.sql.SqlJsonQueryEmptyOrErrorBehavior) SearchableExpression(com.hazelcast.sql.impl.expression.SearchableExpression) CastExpression(com.hazelcast.sql.impl.expression.CastExpression) CaseExpression(com.hazelcast.sql.impl.expression.CaseExpression) Expression(com.hazelcast.sql.impl.expression.Expression) SymbolExpression(com.hazelcast.sql.impl.expression.SymbolExpression) ConstantExpression(com.hazelcast.sql.impl.expression.ConstantExpression) SqlTrimFunction(org.apache.calcite.sql.fun.SqlTrimFunction) SymbolExpression(com.hazelcast.sql.impl.expression.SymbolExpression) ExtractField(com.hazelcast.sql.impl.expression.datetime.ExtractField) SqlJsonConstructorNullClause(org.apache.calcite.sql.SqlJsonConstructorNullClause) SqlJsonValueEmptyOrErrorBehavior(org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior) SqlFunction(org.apache.calcite.sql.SqlFunction)

Aggregations

SqlJsonValueEmptyOrErrorBehavior (org.apache.calcite.sql.SqlJsonValueEmptyOrErrorBehavior)3 RexNode (org.apache.calcite.rex.RexNode)2 HazelcastLikeOperator (com.hazelcast.jet.sql.impl.validate.operators.string.HazelcastLikeOperator)1 CaseExpression (com.hazelcast.sql.impl.expression.CaseExpression)1 CastExpression (com.hazelcast.sql.impl.expression.CastExpression)1 ConstantExpression (com.hazelcast.sql.impl.expression.ConstantExpression)1 Expression (com.hazelcast.sql.impl.expression.Expression)1 SearchableExpression (com.hazelcast.sql.impl.expression.SearchableExpression)1 SymbolExpression (com.hazelcast.sql.impl.expression.SymbolExpression)1 ExtractField (com.hazelcast.sql.impl.expression.datetime.ExtractField)1 QueryDataType (com.hazelcast.sql.impl.type.QueryDataType)1 ArrayList (java.util.ArrayList)1 TimeUnitRange (org.apache.calcite.avatica.util.TimeUnitRange)1 RelDataType (org.apache.calcite.rel.type.RelDataType)1 SqlFunction (org.apache.calcite.sql.SqlFunction)1 SqlJsonConstructorNullClause (org.apache.calcite.sql.SqlJsonConstructorNullClause)1 SqlJsonEmptyOrError (org.apache.calcite.sql.SqlJsonEmptyOrError)1 SqlJsonQueryEmptyOrErrorBehavior (org.apache.calcite.sql.SqlJsonQueryEmptyOrErrorBehavior)1 SqlJsonQueryWrapperBehavior (org.apache.calcite.sql.SqlJsonQueryWrapperBehavior)1 SqlLiteral (org.apache.calcite.sql.SqlLiteral)1