use of org.apache.calcite.sql.SqlIntervalLiteral in project calcite by apache.
the class SqlTesterImpl method checkIntervalConv.
public void checkIntervalConv(String sql, String expected) {
SqlValidator validator = getValidator();
final SqlCall n = (SqlCall) parseAndValidate(validator, sql);
SqlNode node = null;
for (int i = 0; i < n.operandCount(); i++) {
node = stripAs(n.operand(i));
if (node instanceof SqlCall) {
node = ((SqlCall) node).operand(0);
break;
}
}
assertNotNull(node);
SqlIntervalLiteral intervalLiteral = (SqlIntervalLiteral) node;
SqlIntervalLiteral.IntervalValue interval = (SqlIntervalLiteral.IntervalValue) intervalLiteral.getValue();
long l = interval.getIntervalQualifier().isYearMonth() ? SqlParserUtil.intervalToMonths(interval) : SqlParserUtil.intervalToMillis(interval);
String actual = l + "";
assertEquals(expected, actual);
}
use of org.apache.calcite.sql.SqlIntervalLiteral in project calcite by apache.
the class RelToSqlConverter method visit.
/**
* @see #dispatch
*/
public Result visit(Match e) {
final RelNode input = e.getInput();
final Result x = visitChild(0, input);
final Context context = matchRecognizeContext(x.qualifiedContext());
SqlNode tableRef = x.asQueryOrValues();
final List<SqlNode> partitionSqlList = new ArrayList<>();
if (e.getPartitionKeys() != null) {
for (RexNode rex : e.getPartitionKeys()) {
SqlNode sqlNode = context.toSql(null, rex);
partitionSqlList.add(sqlNode);
}
}
final SqlNodeList partitionList = new SqlNodeList(partitionSqlList, POS);
final List<SqlNode> orderBySqlList = new ArrayList<>();
if (e.getOrderKeys() != null) {
for (RelFieldCollation fc : e.getOrderKeys().getFieldCollations()) {
if (fc.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) {
boolean first = fc.nullDirection == RelFieldCollation.NullDirection.FIRST;
SqlNode nullDirectionNode = dialect.emulateNullDirection(context.field(fc.getFieldIndex()), first, fc.direction.isDescending());
if (nullDirectionNode != null) {
orderBySqlList.add(nullDirectionNode);
fc = new RelFieldCollation(fc.getFieldIndex(), fc.getDirection(), RelFieldCollation.NullDirection.UNSPECIFIED);
}
}
orderBySqlList.add(context.toSql(fc));
}
}
final SqlNodeList orderByList = new SqlNodeList(orderBySqlList, SqlParserPos.ZERO);
final SqlLiteral rowsPerMatch = e.isAllRows() ? SqlMatchRecognize.RowsPerMatchOption.ALL_ROWS.symbol(POS) : SqlMatchRecognize.RowsPerMatchOption.ONE_ROW.symbol(POS);
final SqlNode after;
if (e.getAfter() instanceof RexLiteral) {
SqlMatchRecognize.AfterOption value = (SqlMatchRecognize.AfterOption) ((RexLiteral) e.getAfter()).getValue2();
after = SqlLiteral.createSymbol(value, POS);
} else {
RexCall call = (RexCall) e.getAfter();
String operand = RexLiteral.stringValue(call.getOperands().get(0));
after = call.getOperator().createCall(POS, new SqlIdentifier(operand, POS));
}
RexNode rexPattern = e.getPattern();
final SqlNode pattern = context.toSql(null, rexPattern);
final SqlLiteral strictStart = SqlLiteral.createBoolean(e.isStrictStart(), POS);
final SqlLiteral strictEnd = SqlLiteral.createBoolean(e.isStrictEnd(), POS);
RexLiteral rexInterval = (RexLiteral) e.getInterval();
SqlIntervalLiteral interval = null;
if (rexInterval != null) {
interval = (SqlIntervalLiteral) context.toSql(null, rexInterval);
}
final SqlNodeList subsetList = new SqlNodeList(POS);
for (Map.Entry<String, SortedSet<String>> entry : e.getSubsets().entrySet()) {
SqlNode left = new SqlIdentifier(entry.getKey(), POS);
List<SqlNode> rhl = Lists.newArrayList();
for (String right : entry.getValue()) {
rhl.add(new SqlIdentifier(right, POS));
}
subsetList.add(SqlStdOperatorTable.EQUALS.createCall(POS, left, new SqlNodeList(rhl, POS)));
}
final SqlNodeList measureList = new SqlNodeList(POS);
for (Map.Entry<String, RexNode> entry : e.getMeasures().entrySet()) {
final String alias = entry.getKey();
final SqlNode sqlNode = context.toSql(null, entry.getValue());
measureList.add(as(sqlNode, alias));
}
final SqlNodeList patternDefList = new SqlNodeList(POS);
for (Map.Entry<String, RexNode> entry : e.getPatternDefinitions().entrySet()) {
final String alias = entry.getKey();
final SqlNode sqlNode = context.toSql(null, entry.getValue());
patternDefList.add(as(sqlNode, alias));
}
final SqlNode matchRecognize = new SqlMatchRecognize(POS, tableRef, pattern, strictStart, strictEnd, patternDefList, measureList, after, subsetList, rowsPerMatch, partitionList, orderByList, interval);
return result(matchRecognize, Expressions.list(Clause.FROM), e, null);
}
use of org.apache.calcite.sql.SqlIntervalLiteral in project calcite by apache.
the class SqlValidatorImpl method validateLiteral.
public void validateLiteral(SqlLiteral literal) {
switch(literal.getTypeName()) {
case DECIMAL:
// Decimal and long have the same precision (as 64-bit integers), so
// the unscaled value of a decimal must fit into a long.
// REVIEW jvs 4-Aug-2004: This should probably be calling over to
// the available calculator implementations to see what they
// support. For now use ESP instead.
//
// jhyde 2006/12/21: I think the limits should be baked into the
// type system, not dependent on the calculator implementation.
BigDecimal bd = (BigDecimal) literal.getValue();
BigInteger unscaled = bd.unscaledValue();
long longValue = unscaled.longValue();
if (!BigInteger.valueOf(longValue).equals(unscaled)) {
// overflow
throw newValidationError(literal, RESOURCE.numberLiteralOutOfRange(bd.toString()));
}
break;
case DOUBLE:
validateLiteralAsDouble(literal);
break;
case BINARY:
final BitString bitString = (BitString) literal.getValue();
if ((bitString.getBitCount() % 8) != 0) {
throw newValidationError(literal, RESOURCE.binaryLiteralOdd());
}
break;
case DATE:
case TIME:
case TIMESTAMP:
Calendar calendar = literal.getValueAs(Calendar.class);
final int year = calendar.get(Calendar.YEAR);
final int era = calendar.get(Calendar.ERA);
if (year < 1 || era == GregorianCalendar.BC || year > 9999) {
throw newValidationError(literal, RESOURCE.dateLiteralOutOfRange(literal.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:
if (literal instanceof SqlIntervalLiteral) {
SqlIntervalLiteral.IntervalValue interval = (SqlIntervalLiteral.IntervalValue) literal.getValue();
SqlIntervalQualifier intervalQualifier = interval.getIntervalQualifier();
// ensure qualifier is good before attempting to validate literal
validateIntervalQualifier(intervalQualifier);
String intervalStr = interval.getIntervalLiteral();
// throws CalciteContextException if string is invalid
int[] values = intervalQualifier.evaluateIntervalLiteral(intervalStr, literal.getParserPosition(), typeFactory.getTypeSystem());
Util.discard(values);
}
break;
default:
}
}
use of org.apache.calcite.sql.SqlIntervalLiteral in project calcite by apache.
the class StandardConvertletTable method convertCast.
protected RexNode convertCast(SqlRexContext cx, final SqlCall call) {
RelDataTypeFactory typeFactory = cx.getTypeFactory();
assert call.getKind() == SqlKind.CAST;
final SqlNode left = call.operand(0);
final SqlNode right = call.operand(1);
if (right instanceof SqlIntervalQualifier) {
final SqlIntervalQualifier intervalQualifier = (SqlIntervalQualifier) right;
if (left instanceof SqlIntervalLiteral) {
RexLiteral sourceInterval = (RexLiteral) cx.convertExpression(left);
BigDecimal sourceValue = (BigDecimal) sourceInterval.getValue();
RexLiteral castedInterval = cx.getRexBuilder().makeIntervalLiteral(sourceValue, intervalQualifier);
return castToValidatedType(cx, call, castedInterval);
} else if (left instanceof SqlNumericLiteral) {
RexLiteral sourceInterval = (RexLiteral) cx.convertExpression(left);
BigDecimal sourceValue = (BigDecimal) sourceInterval.getValue();
final BigDecimal multiplier = intervalQualifier.getUnit().multiplier;
sourceValue = sourceValue.multiply(multiplier);
RexLiteral castedInterval = cx.getRexBuilder().makeIntervalLiteral(sourceValue, intervalQualifier);
return castToValidatedType(cx, call, castedInterval);
}
return castToValidatedType(cx, call, cx.convertExpression(left));
}
SqlDataTypeSpec dataType = (SqlDataTypeSpec) right;
if (SqlUtil.isNullLiteral(left, false)) {
return cx.convertExpression(left);
}
RexNode arg = cx.convertExpression(left);
RelDataType type = dataType.deriveType(typeFactory);
if (arg.getType().isNullable()) {
type = typeFactory.createTypeWithNullability(type, true);
}
if (null != dataType.getCollectionsTypeName()) {
final RelDataType argComponentType = arg.getType().getComponentType();
final RelDataType componentType = type.getComponentType();
if (argComponentType.isStruct() && !componentType.isStruct()) {
RelDataType tt = typeFactory.builder().add(argComponentType.getFieldList().get(0).getName(), componentType).build();
tt = typeFactory.createTypeWithNullability(tt, componentType.isNullable());
boolean isn = type.isNullable();
type = typeFactory.createMultisetType(tt, -1);
type = typeFactory.createTypeWithNullability(type, isn);
}
}
return cx.getRexBuilder().makeCast(type, arg);
}
use of org.apache.calcite.sql.SqlIntervalLiteral in project calcite by apache.
the class StandardConvertletTable method convertFloorCeil.
protected RexNode convertFloorCeil(SqlRexContext cx, SqlCall call) {
final boolean floor = call.getKind() == SqlKind.FLOOR;
// Rewrite floor, ceil of interval
if (call.operandCount() == 1 && call.operand(0) instanceof SqlIntervalLiteral) {
final SqlIntervalLiteral literal = call.operand(0);
SqlIntervalLiteral.IntervalValue interval = (SqlIntervalLiteral.IntervalValue) literal.getValue();
BigDecimal val = interval.getIntervalQualifier().getStartUnit().multiplier;
RexNode rexInterval = cx.convertExpression(literal);
final RexBuilder rexBuilder = cx.getRexBuilder();
RexNode zero = rexBuilder.makeExactLiteral(BigDecimal.valueOf(0));
RexNode cond = ge(rexBuilder, rexInterval, zero);
RexNode pad = rexBuilder.makeExactLiteral(val.subtract(BigDecimal.ONE));
RexNode cast = rexBuilder.makeReinterpretCast(rexInterval.getType(), pad, rexBuilder.makeLiteral(false));
RexNode sum = floor ? minus(rexBuilder, rexInterval, cast) : plus(rexBuilder, rexInterval, cast);
RexNode kase = floor ? case_(rexBuilder, rexInterval, cond, sum) : case_(rexBuilder, sum, cond, rexInterval);
RexNode factor = rexBuilder.makeExactLiteral(val);
RexNode div = divideInt(rexBuilder, kase, factor);
return multiply(rexBuilder, div, factor);
}
// normal floor, ceil function
return convertFunction(cx, (SqlFunction) call.getOperator(), call);
}
Aggregations