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);
}
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);
}
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);
}
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);
}
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();
});
}
Aggregations