use of org.apache.calcite.util.Sarg in project flink by apache.
the class RexSimplify method simplifySearch.
private RexNode simplifySearch(RexCall call, RexUnknownAs unknownAs) {
assert call.getKind() == SqlKind.SEARCH;
final RexNode a = call.getOperands().get(0);
if (call.getOperands().get(1) instanceof RexLiteral) {
RexLiteral literal = (RexLiteral) call.getOperands().get(1);
final Sarg sarg = literal.getValueAs(Sarg.class);
if (sarg.containsNull) {
final RexNode simplified = simplifyIs1(SqlKind.IS_NULL, a, unknownAs);
if (simplified != null && simplified.isAlwaysFalse()) {
final Sarg sarg2 = Sarg.of(false, sarg.rangeSet);
final RexLiteral literal2 = rexBuilder.makeLiteral(sarg2, literal.getType(), literal.getTypeName());
return call.clone(call.type, ImmutableList.of(a, literal2));
}
}
}
return call;
}
use of org.apache.calcite.util.Sarg in project flink by apache.
the class FlinkRexBuilder method makeIn.
/**
* Convert the conditions into the {@code IN} and fix [CALCITE-4888]: Unexpected {@link RexNode}
* when call {@link RelBuilder#in} to create an {@code IN} predicate with a list of varchar
* literals which have different length in {@link RexBuilder#makeIn}.
*
* <p>The bug is because the origin implementation doesn't take {@link
* FlinkTypeSystem#shouldConvertRaggedUnionTypesToVarying} into consideration. When this is
* true, the behaviour should not padding char. Please see
* https://issues.apache.org/jira/browse/CALCITE-4590 and
* https://issues.apache.org/jira/browse/CALCITE-2321. Please refer to {@code
* org.apache.calcite.rex.RexSimplify.RexSargBuilder#getType} for the correct behaviour.
*
* <p>Once CALCITE-4888 is fixed, this method (and related methods) should be removed.
*/
@Override
@SuppressWarnings("unchecked")
public RexNode makeIn(RexNode arg, List<? extends RexNode> ranges) {
if (areAssignable(arg, ranges)) {
// Fix calcite doesn't check literal whether is NULL here
List<RexNode> rangeWithoutNull = new ArrayList<>();
boolean containsNull = false;
for (RexNode node : ranges) {
if (isNull(node)) {
containsNull = true;
} else {
rangeWithoutNull.add(node);
}
}
final Sarg sarg = toSarg(Comparable.class, rangeWithoutNull, containsNull);
if (sarg != null) {
List<RelDataType> distinctTypes = Util.distinctList(ranges.stream().map(RexNode::getType).collect(Collectors.toList()));
RelDataType commonType = getTypeFactory().leastRestrictive(distinctTypes);
return makeCall(SqlStdOperatorTable.SEARCH, arg, makeSearchArgumentLiteral(sarg, commonType));
}
}
return RexUtil.composeDisjunction(this, ranges.stream().map(r -> makeCall(SqlStdOperatorTable.EQUALS, arg, r)).collect(Util.toImmutableList()));
}
use of org.apache.calcite.util.Sarg in project flink by apache.
the class RexLiteral method appendAsJava.
/**
* Appends the specified value in the provided destination as a Java string. The value must be
* consistent with the type, as per {@link #valueMatchesType}.
*
* <p>Typical return values:
*
* <ul>
* <li>true
* <li>null
* <li>"Hello, world!"
* <li>1.25
* <li>1234ABCD
* </ul>
*
* @param value Value to be appended to the provided destination as a Java string
* @param sb Destination to which to append the specified value
* @param typeName Type name to be used for the transformation of the value to a Java string
* @param type Type to be used for the transformation of the value to a Java string
* @param includeType Whether to include the data type in the Java representation
*/
private static void appendAsJava(Comparable value, StringBuilder sb, SqlTypeName typeName, RelDataType type, boolean java, RexDigestIncludeType includeType) {
switch(typeName) {
case CHAR:
NlsString nlsString = (NlsString) value;
if (java) {
Util.printJavaString(sb, nlsString.getValue(), true);
} else {
boolean includeCharset = (nlsString.getCharsetName() != null) && !nlsString.getCharsetName().equals(CalciteSystemProperty.DEFAULT_CHARSET.value());
sb.append(nlsString.asSql(includeCharset, false));
}
break;
case BOOLEAN:
assert value instanceof Boolean;
sb.append(value.toString());
break;
case DECIMAL:
assert value instanceof BigDecimal;
sb.append(value.toString());
break;
case DOUBLE:
assert value instanceof BigDecimal;
sb.append(Util.toScientificNotation((BigDecimal) value));
break;
case BIGINT:
assert value instanceof BigDecimal;
long narrowLong = ((BigDecimal) value).longValue();
sb.append(String.valueOf(narrowLong));
sb.append('L');
break;
case BINARY:
assert value instanceof ByteString;
sb.append("X'");
sb.append(((ByteString) value).toString(16));
sb.append("'");
break;
case NULL:
assert value == null;
sb.append("null");
break;
case SARG:
assert value instanceof Sarg;
// noinspection unchecked,rawtypes
Util.asStringBuilder(sb, sb2 -> printSarg(sb2, (Sarg) value, type));
break;
case SYMBOL:
assert value instanceof Enum;
sb.append("FLAG(");
sb.append(value.toString());
sb.append(")");
break;
case DATE:
assert value instanceof DateString;
sb.append(value.toString());
break;
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
assert value instanceof TimeString;
sb.append(value.toString());
break;
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
assert value instanceof TimestampString;
sb.append(value.toString());
break;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
case INTERVAL_DAY_SECOND:
case INTERVAL_HOUR:
case INTERVAL_HOUR_MINUTE:
case INTERVAL_HOUR_SECOND:
case INTERVAL_MINUTE:
case INTERVAL_MINUTE_SECOND:
case INTERVAL_SECOND:
assert value instanceof BigDecimal;
sb.append(value.toString());
break;
case MULTISET:
case ROW:
final List<RexLiteral> list = (List) value;
Util.asStringBuilder(sb, sb2 -> Util.printList(sb, list.size(), (sb3, i) -> sb3.append(list.get(i).computeDigest(includeType))));
break;
case GEOMETRY:
final String wkt = GeoFunctions.ST_AsWKT((Geometries.Geom) value);
sb.append(wkt);
break;
default:
assert valueMatchesType(value, typeName, true);
throw Util.needToImplement(typeName);
}
}
use of org.apache.calcite.util.Sarg in project herddb by diennea.
the class SQLExpressionCompiler method convertSearchOperator.
private static CompiledSQLExpression convertSearchOperator(RexCall p) {
if (p.operands.size() != 2) {
throw new StatementExecutionException("not implemented SEARCH with " + p.operands.size() + " operands");
}
CompiledSQLExpression left = compileExpression(p.operands.get(0));
RexNode rexNode = p.operands.get(1);
if (!(rexNode instanceof RexLiteral)) {
throw new StatementExecutionException("not implemented SEARCH with " + rexNode.getClass());
}
RexLiteral searchArgument = (RexLiteral) rexNode;
if (!SqlTypeName.SARG.equals(searchArgument.getTypeName())) {
throw new StatementExecutionException("not implemented SEARCH with " + searchArgument);
}
Sarg<?> sarg = (Sarg) searchArgument.getValue();
if (sarg == null) {
throw new StatementExecutionException("not implemented SEARCH with " + searchArgument);
}
RangeSet<?> rangeSet = sarg.rangeSet;
// pick the ranges in order
List<? extends Range<?>> ranges = new ArrayList<>(rangeSet.asDescendingSetOfRanges());
CompiledSQLExpression[] operands = new CompiledSQLExpression[ranges.size()];
CompiledSQLExpression rawResult = null;
if (ranges.size() == 2) {
// very creative way for '<>'
// x <> CONST -> x in (-INF, CONST) or x in (CONST, +INF)
Range<?> firstRange = ranges.get(1);
Range<?> secondRange = ranges.get(0);
if (!firstRange.hasLowerBound() && firstRange.hasUpperBound() && secondRange.hasLowerBound() && !secondRange.hasUpperBound()) {
Comparable from = firstRange.upperEndpoint();
Comparable to = secondRange.lowerEndpoint();
if (Objects.equals(from, to)) {
ConstantExpression fromExpression = new ConstantExpression(safeValue(from, searchArgument.getType(), searchArgument.getTypeName()), CalcitePlanner.convertToHerdType(searchArgument.getType()));
rawResult = new CompiledNotEqualsExpression(left, fromExpression);
}
}
}
if (rawResult == null) {
int index = 0;
for (Range<?> range : ranges) {
if (!range.hasLowerBound() || !range.hasUpperBound()) {
throw new StatementExecutionException("not implemented SEARCH with " + searchArgument + " without BOUNDS");
}
Comparable from = range.lowerEndpoint();
Comparable to = range.upperEndpoint();
CompiledSQLExpression result;
if (from != null && Objects.equals(from, to)) {
ConstantExpression fromExpression = new ConstantExpression(safeValue(from, searchArgument.getType(), searchArgument.getTypeName()), CalcitePlanner.convertToHerdType(searchArgument.getType()));
result = new CompiledEqualsExpression(left, fromExpression);
} else {
ConstantExpression fromExpression = new ConstantExpression(safeValue(from, searchArgument.getType(), searchArgument.getTypeName()), CalcitePlanner.convertToHerdType(searchArgument.getType()));
ConstantExpression toExpression = new ConstantExpression(safeValue(to, searchArgument.getType(), searchArgument.getTypeName()), CalcitePlanner.convertToHerdType(searchArgument.getType()));
CompiledSQLExpression lowerBound;
CompiledSQLExpression upperBound;
switch(range.lowerBoundType()) {
case OPEN:
lowerBound = new CompiledGreaterThanExpression(left, fromExpression);
break;
case CLOSED:
lowerBound = new CompiledGreaterThanEqualsExpression(left, fromExpression);
break;
default:
throw new UnsupportedOperationException("FROM = " + from + " TO = " + to);
}
switch(range.upperBoundType()) {
case OPEN:
upperBound = new CompiledMinorThanExpression(left, toExpression);
break;
case CLOSED:
upperBound = new CompiledMinorThanEqualsExpression(left, toExpression);
break;
default:
throw new UnsupportedOperationException("FROM = " + from + " TO = " + to);
}
result = new CompiledAndExpression(lowerBound, upperBound);
}
operands[index++] = result;
}
if (operands.length == 1) {
rawResult = operands[0];
} else {
rawResult = new CompiledMultiOrExpression(operands);
}
}
switch(sarg.nullAs) {
case UNKNOWN:
return rawResult;
case TRUE:
// LEFT IS NULL OR (rawResult)
return new CompiledOrExpression(new CompiledIsNullExpression(false, left), rawResult);
case FALSE:
// LEFT IS NOT NULL AND (rawResult)
return new CompiledAndExpression(new CompiledIsNullExpression(true, left), rawResult);
default:
throw new UnsupportedOperationException("sarg.nullAs " + sarg.nullAs);
}
}
Aggregations