use of org.apache.calcite.rex.RexLiteral in project calcite by apache.
the class RexTransformerTest method testExactLiteral.
/**
* Test case for
* <a href="https://issues.apache.org/jira/browse/CALCITE-814">[CALCITE-814]
* RexBuilder reverses precision and scale of DECIMAL literal</a>
* and
* <a href="https://issues.apache.org/jira/browse/CALCITE-1344">[CALCITE-1344]
* Incorrect inferred precision when BigDecimal value is less than 1</a>.
*/
@Test
public void testExactLiteral() {
final RexLiteral literal = rexBuilder.makeExactLiteral(new BigDecimal("-1234.56"));
assertThat(literal.getType().getFullTypeString(), is("DECIMAL(6, 2) NOT NULL"));
assertThat(literal.getValue().toString(), is("-1234.56"));
final RexLiteral literal2 = rexBuilder.makeExactLiteral(new BigDecimal("1234.56"));
assertThat(literal2.getType().getFullTypeString(), is("DECIMAL(6, 2) NOT NULL"));
assertThat(literal2.getValue().toString(), is("1234.56"));
final RexLiteral literal3 = rexBuilder.makeExactLiteral(new BigDecimal("0.0123456"));
assertThat(literal3.getType().getFullTypeString(), is("DECIMAL(8, 7) NOT NULL"));
assertThat(literal3.getValue().toString(), is("0.0123456"));
final RexLiteral literal4 = rexBuilder.makeExactLiteral(new BigDecimal("0.01234560"));
assertThat(literal4.getType().getFullTypeString(), is("DECIMAL(9, 8) NOT NULL"));
assertThat(literal4.getValue().toString(), is("0.01234560"));
}
use of org.apache.calcite.rex.RexLiteral in project calcite by apache.
the class DruidDateTimeUtils method literalValue.
@Nullable
protected static TimestampString literalValue(RexNode node, TimeZone timeZone) {
switch(node.getKind()) {
case LITERAL:
switch(((RexLiteral) node).getTypeName()) {
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
return ((RexLiteral) node).getValueAs(TimestampString.class);
case TIMESTAMP:
// Cast timestamp to timestamp with local time zone
final TimestampString t = ((RexLiteral) node).getValueAs(TimestampString.class);
return new TimestampWithTimeZoneString(t.toString() + " " + timeZone.getID()).withTimeZone(DateTimeUtils.UTC_ZONE).getLocalTimestampString();
case DATE:
// Cast date to timestamp with local time zone
final DateString d = ((RexLiteral) node).getValueAs(DateString.class);
return new TimestampWithTimeZoneString(TimestampString.fromMillisSinceEpoch(d.getMillisSinceEpoch()).toString() + " " + timeZone.getID()).withTimeZone(DateTimeUtils.UTC_ZONE).getLocalTimestampString();
}
break;
case CAST:
// We can handle that case by traversing the dummy CAST.
assert node instanceof RexCall;
final RexCall call = (RexCall) node;
final RexNode operand = call.getOperands().get(0);
final RelDataType callType = call.getType();
final RelDataType operandType = operand.getType();
if (operand.getKind() == SqlKind.LITERAL && callType.getSqlTypeName() == operandType.getSqlTypeName() && (callType.getSqlTypeName() == SqlTypeName.DATE || callType.getSqlTypeName() == SqlTypeName.TIMESTAMP || callType.getSqlTypeName() == SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE) && callType.isNullable() && !operandType.isNullable()) {
return literalValue(operand, timeZone);
}
}
return null;
}
use of org.apache.calcite.rex.RexLiteral in project calcite by apache.
the class DruidJsonFilter method toBoundDruidFilter.
/**
* @param rexNode rexNode to translate
* @param rowType row type associated to Filter
* @param druidQuery druid query
*
* @return valid Druid Json Bound Filter or null if it can not translate the rexNode.
*/
@Nullable
private static DruidJsonFilter toBoundDruidFilter(RexNode rexNode, RelDataType rowType, DruidQuery druidQuery) {
final RexCall rexCall = (RexCall) rexNode;
final RexLiteral rexLiteral;
if (rexCall.getOperands().size() < 2) {
return null;
}
final RexNode refNode;
final RexNode lhs = rexCall.getOperands().get(0);
final RexNode rhs = rexCall.getOperands().get(1);
final boolean lhsIsRef;
if (lhs.getKind() == SqlKind.LITERAL && rhs.getKind() != SqlKind.LITERAL) {
rexLiteral = (RexLiteral) lhs;
refNode = rhs;
lhsIsRef = false;
} else if (rhs.getKind() == SqlKind.LITERAL && lhs.getKind() != SqlKind.LITERAL) {
rexLiteral = (RexLiteral) rhs;
refNode = lhs;
lhsIsRef = true;
} else {
// must have at least one literal
return null;
}
if (RexLiteral.isNullLiteral(rexLiteral)) {
// we are not handling is NULL filter here thus we bail out if Literal is null
return null;
}
final String literalValue = DruidJsonFilter.toDruidLiteral(rexLiteral, rowType, druidQuery);
if (literalValue == null) {
// can not translate literal better bail out
return null;
}
final boolean isNumeric = refNode.getType().getFamily() == SqlTypeFamily.NUMERIC || rexLiteral.getType().getFamily() == SqlTypeFamily.NUMERIC;
final Pair<String, ExtractionFunction> druidColumn = DruidQuery.toDruidColumn(refNode, rowType, druidQuery);
final String columnName = druidColumn.left;
final ExtractionFunction extractionFunction = druidColumn.right;
if (columnName == null) {
// no column name better bail out.
return null;
}
switch(rexCall.getKind()) {
case LESS_THAN_OR_EQUAL:
case LESS_THAN:
if (lhsIsRef) {
return new JsonBound(columnName, null, false, literalValue, rexCall.getKind() == SqlKind.LESS_THAN, isNumeric, extractionFunction);
} else {
return new JsonBound(columnName, literalValue, rexCall.getKind() == SqlKind.LESS_THAN, null, false, isNumeric, extractionFunction);
}
case GREATER_THAN_OR_EQUAL:
case GREATER_THAN:
if (!lhsIsRef) {
return new JsonBound(columnName, null, false, literalValue, rexCall.getKind() == SqlKind.GREATER_THAN, isNumeric, extractionFunction);
} else {
return new JsonBound(columnName, literalValue, rexCall.getKind() == SqlKind.GREATER_THAN, null, false, isNumeric, extractionFunction);
}
default:
return null;
}
}
use of org.apache.calcite.rex.RexLiteral in project calcite by apache.
the class DruidJsonFilter method toEqualityKindDruidFilter.
/**
* @param rexNode rexNode to translate to Druid Json Filter
* @param rowType rowType associated to rexNode
* @param druidQuery druid query
*
* @return Druid Json filter or null if it can not translate
*/
@Nullable
private static DruidJsonFilter toEqualityKindDruidFilter(RexNode rexNode, RelDataType rowType, DruidQuery druidQuery) {
if (rexNode.getKind() != SqlKind.EQUALS && rexNode.getKind() != SqlKind.NOT_EQUALS) {
throw new AssertionError(DruidQuery.format("Expecting EQUALS or NOT_EQUALS but got [%s]", rexNode.getKind()));
}
final RexCall rexCall = (RexCall) rexNode;
if (rexCall.getOperands().size() < 2) {
return null;
}
final RexLiteral rexLiteral;
final RexNode refNode;
final RexNode lhs = rexCall.getOperands().get(0);
final RexNode rhs = rexCall.getOperands().get(1);
if (lhs.getKind() == SqlKind.LITERAL && rhs.getKind() != SqlKind.LITERAL) {
rexLiteral = (RexLiteral) lhs;
refNode = rhs;
} else if (rhs.getKind() == SqlKind.LITERAL && lhs.getKind() != SqlKind.LITERAL) {
rexLiteral = (RexLiteral) rhs;
refNode = lhs;
} else {
// must have at least one literal
return null;
}
if (RexLiteral.isNullLiteral(rexLiteral)) {
// we are not handling is NULL filter here thus we bail out if Literal is null
return null;
}
final String literalValue = toDruidLiteral(rexLiteral, rowType, druidQuery);
if (literalValue == null) {
// can not translate literal better bail out
return null;
}
final boolean isNumeric = refNode.getType().getFamily() == SqlTypeFamily.NUMERIC || rexLiteral.getType().getFamily() == SqlTypeFamily.NUMERIC;
final Pair<String, ExtractionFunction> druidColumn = DruidQuery.toDruidColumn(refNode, rowType, druidQuery);
final String columnName = druidColumn.left;
final ExtractionFunction extractionFunction = druidColumn.right;
if (columnName == null) {
// no column name better bail out.
return null;
}
final DruidJsonFilter partialFilter;
if (isNumeric) {
// need bound filter since it one of operands is numeric
partialFilter = new JsonBound(columnName, literalValue, false, literalValue, false, true, extractionFunction);
} else {
partialFilter = new JsonSelector(columnName, literalValue, extractionFunction);
}
if (rexNode.getKind() == SqlKind.EQUALS) {
return partialFilter;
}
return toNotDruidFilter(partialFilter);
}
use of org.apache.calcite.rex.RexLiteral in project calcite by apache.
the class DruidJsonFilter method toDruidLiteral.
/**
* @param rexNode rexNode to translate to Druid literal equivalante
* @param rowType rowType associated to rexNode
* @param druidQuery druid Query
*
* @return non null string or null if it can not translate to valid Druid equivalent
*/
@Nullable
private static String toDruidLiteral(RexNode rexNode, RelDataType rowType, DruidQuery druidQuery) {
final SimpleDateFormat dateFormatter = new SimpleDateFormat(TimeExtractionFunction.ISO_TIME_FORMAT, Locale.ROOT);
final String timeZone = druidQuery.getConnectionConfig().timeZone();
if (timeZone != null) {
dateFormatter.setTimeZone(TimeZone.getTimeZone(timeZone));
}
final String val;
final RexLiteral rhsLiteral = (RexLiteral) rexNode;
if (SqlTypeName.NUMERIC_TYPES.contains(rhsLiteral.getTypeName())) {
val = String.valueOf(RexLiteral.value(rhsLiteral));
} else if (SqlTypeName.CHAR_TYPES.contains(rhsLiteral.getTypeName())) {
val = String.valueOf(RexLiteral.stringValue(rhsLiteral));
} else if (SqlTypeName.TIMESTAMP == rhsLiteral.getTypeName() || SqlTypeName.DATE == rhsLiteral.getTypeName() || SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE == rhsLiteral.getTypeName()) {
TimestampString timestampString = DruidDateTimeUtils.literalValue(rexNode, TimeZone.getTimeZone(timeZone));
if (timestampString == null) {
throw new AssertionError("Cannot translate Literal" + rexNode + " of type " + rhsLiteral.getTypeName() + " to TimestampString");
}
// @TODO this is unnecessary we can send time as Long (eg millis since epoch) to druid
val = dateFormatter.format(timestampString.getMillisSinceEpoch());
} else {
// Don't know how to filter on this kind of literal.
val = null;
}
return val;
}
Aggregations