Skip to content

Commit

Permalink
[CALCITE-1947] Add time/timestamp with local time zone types to optim…
Browse files Browse the repository at this point in the history
…izer

Close apache#519
  • Loading branch information
jcamachor committed Sep 5, 2017
1 parent f10950b commit 939c9a6
Show file tree
Hide file tree
Showing 38 changed files with 1,361 additions and 258 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1655,7 +1655,14 @@ public Expression implement(RexToLixTranslator translator, RexCall call,
case 2:
final Type type;
final Method floorMethod;
Expression operand = translatedOperands.get(0);
switch (call.getType().getSqlTypeName()) {
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
operand = Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, translator.getRoot()));
// fall through
case TIMESTAMP:
type = long.class;
floorMethod = timestampMethod;
Expand All @@ -1671,19 +1678,19 @@ public Expression implement(RexToLixTranslator translator, RexCall call,
case YEAR:
case MONTH:
return Expressions.call(floorMethod, tur,
call(translatedOperands, type, TimeUnit.DAY));
call(operand, type, TimeUnit.DAY));
default:
return call(translatedOperands, type, timeUnitRange.startUnit);
return call(operand, type, timeUnitRange.startUnit);
}
default:
throw new AssertionError();
}
}

private Expression call(List<Expression> translatedOperands, Type type,
private Expression call(Expression operand, Type type,
TimeUnit timeUnit) {
return Expressions.call(SqlFunctions.class, methodName,
Types.castIfNecessary(type, translatedOperands.get(0)),
Types.castIfNecessary(type, operand),
Types.castIfNecessary(type,
Expressions.constant(timeUnit.multiplier)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ Expression translateCast(
Expressions.call(BuiltInMethod.FLOOR_DIV.method,
operand, Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
int.class);
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_DATE.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIME:
Expand All @@ -254,13 +262,64 @@ Expression translateCast(
convert =
Expressions.call(BuiltInMethod.STRING_TO_TIME.method, operand);
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIME.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP:
convert = Expressions.convert_(
Expressions.call(
BuiltInMethod.FLOOR_MOD.method,
operand,
Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
int.class);
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIME.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIME_WITH_LOCAL_TIME_ZONE:
switch (sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert =
Expressions.call(BuiltInMethod.STRING_TO_TIME_WITH_LOCAL_TIME_ZONE.method, operand);
break;
case TIME:
convert = Expressions.call(
BuiltInMethod.TIME_STRING_TO_TIME_WITH_LOCAL_TIME_ZONE.method,
RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIME_TO_STRING.method,
operand)),
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIMESTAMP:
convert = Expressions.call(
BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method,
operand)),
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIME_WITH_LOCAL_TIME_ZONE.method,
operand));
}
break;
case TIMESTAMP:
Expand All @@ -285,6 +344,82 @@ Expression translateCast(
Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
Expressions.convert_(operand, long.class));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method,
Expressions.call(
BuiltInMethod.UNIX_DATE_TO_STRING.method,
Expressions.call(BuiltInMethod.CURRENT_DATE.method, root)),
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
}
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
switch (sourceType.getSqlTypeName()) {
case CHAR:
case VARCHAR:
convert =
Expressions.call(
BuiltInMethod.STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
operand);
break;
case DATE:
convert = Expressions.call(
BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method,
Expressions.multiply(
Expressions.convert_(operand, long.class),
Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)))),
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIME:
convert = Expressions.call(
BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method,
Expressions.add(
Expressions.multiply(
Expressions.convert_(
Expressions.call(BuiltInMethod.CURRENT_DATE.method, root),
long.class),
Expressions.constant(DateTimeUtils.MILLIS_PER_DAY)),
Expressions.convert_(operand, long.class)))),
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
Expressions.call(
BuiltInMethod.UNIX_DATE_TO_STRING.method,
Expressions.call(BuiltInMethod.CURRENT_DATE.method, root)),
operand));
break;
case TIMESTAMP:
convert = Expressions.call(
BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method,
operand)),
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
}
break;
case BOOLEAN:
Expand Down Expand Up @@ -315,13 +450,29 @@ Expression translateCast(
BuiltInMethod.UNIX_TIME_TO_STRING.method,
operand));
break;
case TIME_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIME_WITH_LOCAL_TIME_ZONE_TO_STRING.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case TIMESTAMP:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.UNIX_TIMESTAMP_TO_STRING.method,
operand));
break;
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
convert = RexImpTable.optimize2(
operand,
Expressions.call(
BuiltInMethod.TIMESTAMP_WITH_LOCAL_TIME_ZONE_TO_STRING.method,
operand,
Expressions.call(BuiltInMethod.TIME_ZONE.method, root)));
break;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
Expand Down Expand Up @@ -621,13 +772,15 @@ public static Expression translateLiteral(
Expressions.constant(bd.toString()));
case DATE:
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
value2 = literal.getValueAs(Integer.class);
javaClass = int.class;
break;
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,12 +176,14 @@ public Type getJavaClass(RelDataType type) {
return String.class;
case DATE:
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case INTEGER:
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
return type.isNullable() ? Integer.class : int.class;
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
case BIGINT:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ public Double averageTypeValueSize(RelDataType type) {
case DECIMAL:
case DATE:
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
Expand All @@ -289,6 +290,7 @@ public Double averageTypeValueSize(RelDataType type) {
case DOUBLE:
case FLOAT: // sic
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
Expand Down Expand Up @@ -339,13 +341,15 @@ public double typeValueSize(RelDataType type, Comparable value) {
case REAL:
case DATE:
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
case INTERVAL_MONTH:
return 4d;
case BIGINT:
case DOUBLE:
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.calcite.plan.RelOptUtil;
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelCollationTraitDef;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelFieldCollation;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.Project;
Expand Down Expand Up @@ -102,7 +103,7 @@ public void onMatch(RelOptRuleCall call) {
final RexCall cast = (RexCall) node;
final RexCallBinding binding =
RexCallBinding.create(cluster.getTypeFactory(), cast,
ImmutableList.of(RexUtil.apply(map, sort.getCollation())));
ImmutableList.of(RelCollations.of(RexUtil.apply(map, fc))));
if (cast.getOperator().getMonotonicity(binding) == SqlMonotonicity.NOT_MONOTONIC) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ public int getMaxScale(SqlTypeName typeName) {
case DOUBLE:
return 15;
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case DATE:
return 0; // SQL99 part 2 section 6.1 syntax rule 30
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
// farrago supports only 0 (see
// SqlTypeName.getDefaultPrecision), but it should be 6
// (microseconds) per SQL99 part 2 section 6.1 syntax rule 30.
Expand All @@ -120,7 +122,9 @@ public int getMaxScale(SqlTypeName typeName) {
case BINARY:
return 65536;
case TIME:
case TIME_WITH_LOCAL_TIME_ZONE:
case TIMESTAMP:
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
return SqlTypeName.MAX_DATETIME_PRECISION;
case INTERVAL_YEAR:
case INTERVAL_YEAR_MONTH:
Expand Down Expand Up @@ -159,6 +163,8 @@ public int getMaxScale(SqlTypeName typeName) {
return isPrefix ? "x'" : "'";
case TIMESTAMP:
return isPrefix ? "TIMESTAMP '" : "'";
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
return isPrefix ? "TIMESTAMP WITH LOCAL TIME ZONE '" : "'";
case INTERVAL_DAY:
case INTERVAL_DAY_HOUR:
case INTERVAL_DAY_MINUTE:
Expand All @@ -176,6 +182,8 @@ public int getMaxScale(SqlTypeName typeName) {
return isPrefix ? "INTERVAL '" : "' YEAR TO MONTH";
case TIME:
return isPrefix ? "TIME '" : "'";
case TIME_WITH_LOCAL_TIME_ZONE:
return isPrefix ? "TIME WITH LOCAL TIME ZONE '" : "'";
case DATE:
return isPrefix ? "DATE '" : "'";
case ARRAY:
Expand Down
Loading

0 comments on commit 939c9a6

Please sign in to comment.