blob: 313fda132c008cf1f6cc098631fa1a615724c875 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.sql2rel;
import org.apache.calcite.avatica.util.ByteString;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexBuilder;
import org.apache.calcite.rex.RexLiteral;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.sql.SqlCall;
import org.apache.calcite.sql.SqlIntervalQualifier;
import org.apache.calcite.sql.SqlLiteral;
import org.apache.calcite.sql.SqlTimeLiteral;
import org.apache.calcite.sql.SqlTimestampLiteral;
import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.calcite.util.BitString;
import org.apache.calcite.util.DateString;
import org.apache.calcite.util.NlsString;
import org.apache.calcite.util.TimeString;
import org.apache.calcite.util.TimestampString;
import org.apache.calcite.util.Util;
import java.math.BigDecimal;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Standard implementation of {@link SqlNodeToRexConverter}.
*/
public class SqlNodeToRexConverterImpl implements SqlNodeToRexConverter {
//~ Instance fields --------------------------------------------------------
private final SqlRexConvertletTable convertletTable;
//~ Constructors -----------------------------------------------------------
SqlNodeToRexConverterImpl(SqlRexConvertletTable convertletTable) {
this.convertletTable = convertletTable;
}
//~ Methods ----------------------------------------------------------------
@Override public RexNode convertCall(SqlRexContext cx, SqlCall call) {
final SqlRexConvertlet convertlet = convertletTable.get(call);
if (convertlet != null) {
return convertlet.convertCall(cx, call);
}
// No convertlet was suitable. (Unlikely, because the standard
// convertlet table has a fall-back for all possible calls.)
throw Util.needToImplement(call);
}
@Override public RexLiteral convertInterval(
SqlRexContext cx,
SqlIntervalQualifier intervalQualifier) {
RexBuilder rexBuilder = cx.getRexBuilder();
return rexBuilder.makeIntervalLiteral(intervalQualifier);
}
@Override public RexNode convertLiteral(
SqlRexContext cx,
SqlLiteral literal) {
final RexBuilder rexBuilder = cx.getRexBuilder();
if (literal.getValue() == null) {
if (literal.getTypeName() == SqlTypeName.NULL) {
RelDataType type = cx.getValidator().getValidatedNodeTypeIfKnown(literal);
if (type == null) {
type = rexBuilder.getTypeFactory().createSqlType(SqlTypeName.NULL);
}
return rexBuilder.makeNullLiteral(type);
} else {
RelDataType type = cx.getValidator().getValidatedNodeType(literal);
return rexBuilder.makeNullLiteral(type);
}
}
switch (literal.getTypeName()) {
case DECIMAL:
// exact number
BigDecimal bd = literal.getValueAs(BigDecimal.class);
RelDataType type = literal.createSqlType(cx.getTypeFactory());
return rexBuilder.makeExactLiteral(bd, type);
case DOUBLE:
// approximate type
// TODO: preserve fixed-point precision and large integers
return rexBuilder.makeApproxLiteral(literal.getValueAs(BigDecimal.class));
case CHAR:
return rexBuilder.makeCharLiteral(literal.getValueAs(NlsString.class));
case BOOLEAN:
return rexBuilder.makeLiteral(literal.getValueAs(Boolean.class));
case BINARY:
final BitString bitString = literal.getValueAs(BitString.class);
checkArgument((bitString.getBitCount() % 8) == 0, "incomplete octet");
// An even number of hexits (e.g. X'ABCD') makes whole number
// of bytes.
final ByteString byteString = new ByteString(bitString.getAsByteArray());
return rexBuilder.makeBinaryLiteral(byteString);
case SYMBOL:
return rexBuilder.makeFlag(literal.getValueAs(Enum.class));
case TIMESTAMP:
return rexBuilder.makeTimestampLiteral(
literal.getValueAs(TimestampString.class),
((SqlTimestampLiteral) literal).getPrec());
case TIMESTAMP_WITH_LOCAL_TIME_ZONE:
return rexBuilder.makeTimestampWithLocalTimeZoneLiteral(
literal.getValueAs(TimestampString.class),
((SqlTimestampLiteral) literal).getPrec());
case TIME:
return rexBuilder.makeTimeLiteral(
literal.getValueAs(TimeString.class),
((SqlTimeLiteral) literal).getPrec());
case DATE:
return rexBuilder.makeDateLiteral(literal.getValueAs(DateString.class));
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:
SqlIntervalQualifier sqlIntervalQualifier =
literal.getValueAs(SqlIntervalQualifier.class);
return rexBuilder.makeIntervalLiteral(
literal.getValueAs(BigDecimal.class),
sqlIntervalQualifier);
case UNKNOWN:
return convertLiteral(cx, cx.getValidator().resolveLiteral(literal));
default:
throw Util.unexpected(literal.getTypeName());
}
}
}