Search in sources :

Example 41 with QueryDataType

use of com.hazelcast.sql.impl.type.QueryDataType 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)

Example 42 with QueryDataType

use of com.hazelcast.sql.impl.type.QueryDataType in project hazelcast by hazelcast.

the class IndexResolver method createIndexScan.

/**
 * Create index scan for the given index if possible.
 *
 * @param scan         the original map scan
 * @param index        index to be considered
 * @param conjunctions CNF components of the original map filter
 * @param candidates   resolved candidates
 * @param ascs         a list of index field collations
 * @return index scan or {@code null}.
 */
public static RelNode createIndexScan(FullScanLogicalRel scan, MapTableIndex index, List<RexNode> conjunctions, Map<Integer, List<IndexComponentCandidate>> candidates, List<Boolean> ascs) {
    List<IndexComponentFilter> filters = new ArrayList<>(index.getFieldOrdinals().size());
    // Iterate over every index component from the beginning and try to form a filter to it
    for (int i = 0; i < index.getFieldOrdinals().size(); i++) {
        int fieldOrdinal = index.getFieldOrdinals().get(i);
        QueryDataType fieldConverterType = index.getFieldConverterTypes().get(i);
        List<IndexComponentCandidate> fieldCandidates = candidates.get(fieldOrdinal);
        if (fieldCandidates == null) {
            // used for index filter.
            break;
        }
        // Create the filter for the given index component if possible.
        // Separate candidates are possibly merged into a single complex filter at this stage.
        // Consider the index {a}, and the condition "WHERE a>1 AND a<5". In this case two distinct range candidates
        // {>1} and {<5} are combined into a single RANGE filter {>1 AND <5}
        IndexComponentFilter filter = selectComponentFilter(index.getType(), fieldCandidates, fieldConverterType);
        if (filter == null) {
            // Cannot create a filter for the given candidates, stop.
            break;
        }
        filters.add(filter);
        if (!(filter.getFilter() instanceof IndexEqualsFilter)) {
            // {a>1} filter.
            break;
        }
    }
    if (filters.isEmpty()) {
        // Failed to build any filters. The index cannot be used.
        return null;
    }
    // Now as filters are determined, construct the physical entity.
    return createIndexScan(scan, index, conjunctions, filters, ascs);
}
Also used : IndexEqualsFilter(com.hazelcast.sql.impl.exec.scan.index.IndexEqualsFilter) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType) ArrayList(java.util.ArrayList)

Example 43 with QueryDataType

use of com.hazelcast.sql.impl.type.QueryDataType in project hazelcast by hazelcast.

the class IndexResolver method prepareSingleColumnCandidateIsNull.

/**
 * Try creating a candidate filter for the "IS NULL" expression.
 * <p>
 * Returns the filter EQUALS(null) with "allowNulls-true".
 *
 * @param exp     original expression, e.g. {col IS NULL}
 * @param operand operand, e.g. {col}; CAST must be unwrapped before the method is invoked
 * @return candidate or {@code null}
 */
private static IndexComponentCandidate prepareSingleColumnCandidateIsNull(RexNode exp, RexNode operand) {
    if (operand.getKind() != SqlKind.INPUT_REF) {
        // The operand is not a column, e.g. {'literal' IS NULL}, index cannot be used
        return null;
    }
    int columnIndex = ((RexInputRef) operand).getIndex();
    QueryDataType type = HazelcastTypeUtils.toHazelcastType(operand.getType());
    // Create a value with "allowNulls=true"
    IndexFilterValue filterValue = new IndexFilterValue(singletonList(ConstantExpression.create(null, type)), singletonList(true));
    IndexFilter filter = new IndexEqualsFilter(filterValue);
    return new IndexComponentCandidate(exp, columnIndex, filter);
}
Also used : IndexEqualsFilter(com.hazelcast.sql.impl.exec.scan.index.IndexEqualsFilter) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType) IndexFilterValue(com.hazelcast.sql.impl.exec.scan.index.IndexFilterValue) RexInputRef(org.apache.calcite.rex.RexInputRef) IndexFilter(com.hazelcast.sql.impl.exec.scan.index.IndexFilter)

Example 44 with QueryDataType

use of com.hazelcast.sql.impl.type.QueryDataType in project hazelcast by hazelcast.

the class SlidingWindowAggregatePhysicalRel method outputValueMapping.

@SuppressWarnings("checkstyle:MagicNumber")
public KeyedWindowResultFunction<? super Object, ? super JetSqlRow, ?> outputValueMapping() {
    int[] windowBoundsIndexMask = new int[getRowType().getFieldCount()];
    QueryDataType descriptorType = HazelcastTypeUtils.toHazelcastType(timestampExpression.getType());
    for (Integer index : windowStartIndexes) {
        windowBoundsIndexMask[index] = -1;
    }
    for (Integer index : windowEndIndexes) {
        windowBoundsIndexMask[index] = -2;
    }
    for (int i = 0, j = 0; i < windowBoundsIndexMask.length; i++) {
        if (windowBoundsIndexMask[i] >= 0) {
            windowBoundsIndexMask[i] = j++;
        }
    }
    return (start, end, ignoredKey, result, isEarly) -> insertWindowBound(result, start, end, descriptorType, windowBoundsIndexMask);
}
Also used : WatermarkedFields(com.hazelcast.jet.sql.impl.opt.metadata.WatermarkedFields) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType) HashMap(java.util.HashMap) QueryParameterMetadata(com.hazelcast.sql.impl.QueryParameterMetadata) ArrayList(java.util.ArrayList) JetSqlRow(com.hazelcast.sql.impl.row.JetSqlRow) ObjectArrayKey(com.hazelcast.jet.sql.impl.ObjectArrayKey) SlidingWindowPolicy(com.hazelcast.jet.core.SlidingWindowPolicy) HazelcastRelOptCluster(org.apache.calcite.plan.HazelcastRelOptCluster) AggregateOperation(com.hazelcast.jet.aggregate.AggregateOperation) RexNode(org.apache.calcite.rex.RexNode) Map(java.util.Map) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) Expression(com.hazelcast.sql.impl.expression.Expression) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelOptCluster(org.apache.calcite.plan.RelOptCluster) ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) FunctionEx(com.hazelcast.function.FunctionEx) KeyedWindowResultFunction(com.hazelcast.jet.core.function.KeyedWindowResultFunction) HazelcastTypeUtils(com.hazelcast.jet.sql.impl.validate.types.HazelcastTypeUtils) RexBuilder(org.apache.calcite.rex.RexBuilder) PlanNodeSchema(com.hazelcast.sql.impl.plan.node.PlanNodeSchema) OptUtils(com.hazelcast.jet.sql.impl.opt.OptUtils) RelNode(org.apache.calcite.rel.RelNode) Aggregate(org.apache.calcite.rel.core.Aggregate) ConstantFunctionEx(com.hazelcast.jet.impl.util.ConstantFunctionEx) Vertex(com.hazelcast.jet.core.Vertex) List(java.util.List) ExpressionEvalContext(com.hazelcast.sql.impl.expression.ExpressionEvalContext) RexVisitor(org.apache.calcite.rex.RexVisitor) WindowUtils.insertWindowBound(com.hazelcast.jet.sql.impl.aggregate.WindowUtils.insertWindowBound) AggregateCall(org.apache.calcite.rel.core.AggregateCall) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType)

Example 45 with QueryDataType

use of com.hazelcast.sql.impl.type.QueryDataType in project hazelcast by hazelcast.

the class MetadataCompactResolver method resolveAndValidateFields.

@Override
public Stream<MappingField> resolveAndValidateFields(boolean isKey, List<MappingField> userFields, Map<String, String> options, InternalSerializationService serializationService) {
    if (userFields.isEmpty()) {
        throw QueryException.error("Column list is required for Compact format");
    }
    String typeNameProperty = isKey ? OPTION_KEY_COMPACT_TYPE_NAME : OPTION_VALUE_COMPACT_TYPE_NAME;
    String typeName = options.get(typeNameProperty);
    if (typeName == null) {
        throw QueryException.error("Unable to resolve table metadata. Missing ['typeName'] option");
    }
    Map<QueryPath, MappingField> fields = extractFields(userFields, isKey);
    return fields.entrySet().stream().map(entry -> {
        QueryPath path = entry.getKey();
        if (path.getPath() == null) {
            throw QueryException.error("Cannot use the '" + path + "' field with Compact serialization");
        }
        QueryDataType type = entry.getValue().type();
        if (type == QueryDataType.OBJECT) {
            throw QueryException.error("Cannot derive Compact type for '" + type.getTypeFamily() + "'");
        }
        return entry.getValue();
    });
}
Also used : QueryPath(com.hazelcast.sql.impl.extract.QueryPath) QueryDataType(com.hazelcast.sql.impl.type.QueryDataType) MappingField(com.hazelcast.sql.impl.schema.MappingField)

Aggregations

QueryDataType (com.hazelcast.sql.impl.type.QueryDataType)61 QueryPath (com.hazelcast.sql.impl.extract.QueryPath)23 MappingField (com.hazelcast.sql.impl.schema.MappingField)17 ArrayList (java.util.ArrayList)16 TableField (com.hazelcast.sql.impl.schema.TableField)14 MapTableField (com.hazelcast.sql.impl.schema.map.MapTableField)13 HazelcastTable (com.hazelcast.jet.sql.impl.schema.HazelcastTable)10 RelDataType (org.apache.calcite.rel.type.RelDataType)7 OptimizerTestSupport (com.hazelcast.jet.sql.impl.opt.OptimizerTestSupport)6 IndexScanMapPhysicalRel (com.hazelcast.jet.sql.impl.opt.physical.IndexScanMapPhysicalRel)6 FullScanPhysicalRel (com.hazelcast.jet.sql.impl.opt.physical.FullScanPhysicalRel)5 Nonnull (javax.annotation.Nonnull)5 IndexEqualsFilter (com.hazelcast.sql.impl.exec.scan.index.IndexEqualsFilter)4 Test (org.junit.Test)4 IndexType (com.hazelcast.config.IndexType)3 KvMetadata (com.hazelcast.jet.sql.impl.connector.keyvalue.KvMetadata)3 ParallelJVMTest (com.hazelcast.test.annotation.ParallelJVMTest)3 QuickTest (com.hazelcast.test.annotation.QuickTest)3 HashMap (java.util.HashMap)3 List (java.util.List)3