You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@calcite.apache.org by jh...@apache.org on 2014/09/19 03:03:03 UTC
[2/2] git commit: [OPTIQ-413] Add RelDataTypeSystem plugin,
allowing different max precision of a DECIMAL
[OPTIQ-413] Add RelDataTypeSystem plugin, allowing different max precision of a DECIMAL
Project: http://git-wip-us.apache.org/repos/asf/incubator-optiq/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-optiq/commit/0fd4e3d9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-optiq/tree/0fd4e3d9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-optiq/diff/0fd4e3d9
Branch: refs/heads/master
Commit: 0fd4e3d9ea63fa67a97ea8ba73e46a12e31af2b1
Parents: a2cc356
Author: Julian Hyde <jh...@apache.org>
Authored: Thu Sep 18 12:05:22 2014 -0700
Committer: Julian Hyde <jh...@apache.org>
Committed: Thu Sep 18 17:33:14 2014 -0700
----------------------------------------------------------------------
.../avatica/ConnectionConfigImpl.java | 59 +++++
.../hydromatic/avatica/ConnectionProperty.java | 4 +-
.../main/codegen/templates/CombinedParser.jj | 5 +-
.../optiq/config/OptiqConnectionConfig.java | 2 +
.../optiq/config/OptiqConnectionConfigImpl.java | 5 +
.../optiq/config/OptiqConnectionProperty.java | 7 +-
.../hydromatic/optiq/impl/jdbc/JdbcSchema.java | 3 +-
.../optiq/jdbc/JavaTypeFactoryImpl.java | 10 +-
.../optiq/jdbc/OptiqConnectionImpl.java | 12 +-
.../optiq/rules/java/RexToLixTranslator.java | 4 +-
.../hydromatic/optiq/tools/FrameworkConfig.java | 8 +
.../net/hydromatic/optiq/tools/Frameworks.java | 28 +-
.../eigenbase/rel/rules/ReduceDecimalsRule.java | 44 +++-
.../eigenbase/reltype/RelDataTypeFactory.java | 5 +
.../reltype/RelDataTypeFactoryImpl.java | 30 ++-
.../eigenbase/reltype/RelDataTypeSystem.java | 60 +++++
.../reltype/RelDataTypeSystemImpl.java | 98 +++++++
.../main/java/org/eigenbase/rex/RexBuilder.java | 9 +-
.../java/org/eigenbase/rex/RexExecutorImpl.java | 3 +-
.../org/eigenbase/sql/SqlIntervalQualifier.java | 258 ++++++++++---------
.../eigenbase/sql/SqlUnresolvedFunction.java | 6 +-
.../org/eigenbase/sql/parser/SqlParserUtil.java | 5 +-
.../org/eigenbase/sql/type/BasicSqlType.java | 41 +--
.../org/eigenbase/sql/type/IntervalSqlType.java | 45 ++--
.../org/eigenbase/sql/type/ReturnTypes.java | 18 +-
.../eigenbase/sql/type/SqlTypeFactoryImpl.java | 32 ++-
.../org/eigenbase/sql/type/SqlTypeName.java | 72 ++----
.../sql/validate/SqlValidatorImpl.java | 48 ++--
.../eigenbase/sql2rel/SqlToRelConverter.java | 11 +-
.../optiq/impl/clone/ArrayTableTest.java | 7 +-
.../optiq/test/MaterializationTest.java | 4 +-
.../hydromatic/optiq/tools/FrameworksTest.java | 68 +++++
.../org/eigenbase/relopt/RelOptUtilTest.java | 3 +-
.../relopt/volcano/VolcanoPlannerTest.java | 3 +-
.../sql/test/DefaultSqlTestFactory.java | 4 +-
.../org/eigenbase/sql/test/SqlAdvisorTest.java | 6 +-
.../eigenbase/sql/test/SqlOperatorBaseTest.java | 13 +-
.../java/org/eigenbase/test/RexProgramTest.java | 2 +-
.../org/eigenbase/test/RexTransformerTest.java | 2 +-
.../test/java/org/eigenbase/test/SargTest.java | 3 +-
.../java/org/eigenbase/test/SqlLimitsTest.java | 72 +++---
.../org/eigenbase/test/SqlToRelTestBase.java | 2 +-
.../eigenbase/test/SqlValidatorFeatureTest.java | 3 +-
.../org/eigenbase/test/SqlValidatorTest.java | 17 +-
.../org/eigenbase/test/SqlLimitsTest.xml | 14 +-
45 files changed, 775 insertions(+), 380 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/avatica/src/main/java/net/hydromatic/avatica/ConnectionConfigImpl.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/net/hydromatic/avatica/ConnectionConfigImpl.java b/avatica/src/main/java/net/hydromatic/avatica/ConnectionConfigImpl.java
index 89066eb..f406da2 100644
--- a/avatica/src/main/java/net/hydromatic/avatica/ConnectionConfigImpl.java
+++ b/avatica/src/main/java/net/hydromatic/avatica/ConnectionConfigImpl.java
@@ -16,6 +16,7 @@
*/
package net.hydromatic.avatica;
+import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties;
@@ -123,6 +124,31 @@ public class ConnectionConfigImpl implements ConnectionConfig {
//noinspection unchecked
return get_(enumConverter(enumClass), defaultValue.name());
}
+
+ /** Returns an instance of a plugin.
+ *
+ * <p>Throws if not set and no default.
+ * Also throws if the class does not implement the required interface,
+ * or if it does not have a public default constructor or an public static
+ * field called {@code #INSTANCE}. */
+ public <T> T getPlugin(Class<T> pluginClass, T defaultInstance) {
+ return getPlugin(pluginClass, (String) property.defaultValue(),
+ defaultInstance);
+ }
+
+ /** Returns an instance of a plugin, using a given class name if none is
+ * set.
+ *
+ * <p>Throws if not set and no default.
+ * Also throws if the class does not implement the required interface,
+ * or if it does not have a public default constructor or an public static
+ * field called {@code #INSTANCE}. */
+ public <T> T getPlugin(Class<T> pluginClass, String defaultClassName,
+ T defaultInstance) {
+ assert property.type() == ConnectionProperty.Type.PLUGIN;
+ return get_(pluginConverter(pluginClass, defaultInstance),
+ defaultClassName);
+ }
}
/** Callback to parse a property from string to its native type. */
@@ -165,6 +191,39 @@ public class ConnectionConfigImpl implements ConnectionConfig {
}
};
}
+
+ public static <T> Converter<T> pluginConverter(final Class<T> pluginClass,
+ final T defaultInstance) {
+ return new Converter<T>() {
+ public T apply(ConnectionProperty connectionProperty, String s) {
+ if (s == null) {
+ if (defaultInstance != null) {
+ return defaultInstance;
+ }
+ throw new RuntimeException("Required property '"
+ + connectionProperty.camelName() + "' not specified");
+ }
+ // First look for a C.INSTANCE field, then do new C().
+ try {
+ //noinspection unchecked
+ final Class<T> clazz = (Class) Class.forName(s);
+ assert pluginClass.isAssignableFrom(clazz);
+ try {
+ // We assume that if there is an INSTANCE field it is static and
+ // has the right type.
+ final Field field = clazz.getField("INSTANCE");
+ return pluginClass.cast(field.get(null));
+ } catch (NoSuchFieldException e) {
+ // ignore
+ }
+ return clazz.newInstance();
+ } catch (Exception e) {
+ throw new RuntimeException("Property '" + s
+ + "' not valid for plugin type " + pluginClass.getName(), e);
+ }
+ }
+ };
+ }
}
// End ConnectionConfigImpl.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/avatica/src/main/java/net/hydromatic/avatica/ConnectionProperty.java
----------------------------------------------------------------------
diff --git a/avatica/src/main/java/net/hydromatic/avatica/ConnectionProperty.java b/avatica/src/main/java/net/hydromatic/avatica/ConnectionProperty.java
index 2dda49a..5fcdc50 100644
--- a/avatica/src/main/java/net/hydromatic/avatica/ConnectionProperty.java
+++ b/avatica/src/main/java/net/hydromatic/avatica/ConnectionProperty.java
@@ -46,13 +46,15 @@ public interface ConnectionProperty {
enum Type {
BOOLEAN,
STRING,
- ENUM;
+ ENUM,
+ PLUGIN;
public boolean valid(Object defaultValue) {
switch (this) {
case BOOLEAN:
return defaultValue instanceof Boolean;
case STRING:
+ case PLUGIN:
return defaultValue instanceof String;
default:
return defaultValue instanceof Enum;
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/codegen/templates/CombinedParser.jj
----------------------------------------------------------------------
diff --git a/core/src/main/codegen/templates/CombinedParser.jj b/core/src/main/codegen/templates/CombinedParser.jj
index 6e3101b..2ccad91 100644
--- a/core/src/main/codegen/templates/CombinedParser.jj
+++ b/core/src/main/codegen/templates/CombinedParser.jj
@@ -33,6 +33,7 @@ package ${parser.package};
import ${importStr};
</#list>
+import org.eigenbase.reltype.RelDataType;
import org.eigenbase.sql.*;
import org.eigenbase.sql.parser.*;
import org.eigenbase.sql.fun.*;
@@ -3118,8 +3119,8 @@ SqlIntervalQualifier IntervalQualifier() :
{
SqlIntervalQualifier.TimeUnit start;
SqlIntervalQualifier.TimeUnit end = null;
- int startPrec = SqlIntervalQualifier.getDefaultPrecisionId();
- int secondFracPrec = SqlIntervalQualifier.getDefaultPrecisionId();
+ int startPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+ int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
}
{
(
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfig.java b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfig.java
index a8a49ab..304a3cb 100644
--- a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfig.java
+++ b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfig.java
@@ -44,6 +44,8 @@ public interface OptiqConnectionConfig extends ConnectionConfig {
boolean caseSensitive();
/** @see net.hydromatic.optiq.config.OptiqConnectionProperty#SPARK */
boolean spark();
+ /** @see net.hydromatic.optiq.config.OptiqConnectionProperty#TYPE_SYSTEM */
+ <T> T typeSystem(Class<T> typeSystemClass, T defaultTypeSystem);
}
// End OptiqConnectionConfig.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfigImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfigImpl.java b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfigImpl.java
index 719f33b..f08cc7c 100644
--- a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfigImpl.java
+++ b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionConfigImpl.java
@@ -82,6 +82,11 @@ public class OptiqConnectionConfigImpl extends ConnectionConfigImpl
public boolean spark() {
return OptiqConnectionProperty.SPARK.wrap(properties).getBoolean();
}
+
+ public <T> T typeSystem(Class<T> typeSystemClass, T defaultTypeSystem) {
+ return OptiqConnectionProperty.TYPE_SYSTEM.wrap(properties)
+ .getPlugin(typeSystemClass, defaultTypeSystem);
+ }
}
// End OptiqConnectionConfigImpl.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionProperty.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionProperty.java b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionProperty.java
index ba3089c..5f2d85c 100644
--- a/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionProperty.java
+++ b/core/src/main/java/net/hydromatic/optiq/config/OptiqConnectionProperty.java
@@ -68,7 +68,12 @@ public enum OptiqConnectionProperty implements ConnectionProperty {
SPARK("spark", Type.BOOLEAN, false),
/** Timezone, for example 'gmt-3'. Default is the JVM's time zone. */
- TIMEZONE("timezone", Type.STRING, null);
+ TIMEZONE("timezone", Type.STRING, null),
+
+ /** Type system. The name of a class that implements
+ * {@code org.eigenbase.reltype.RelDataTypeSystem} and has a public default
+ * constructor or an {@code INSTANCE} constant. */
+ TYPE_SYSTEM("typeSystem", Type.PLUGIN, null);
private final String camelName;
private final Type type;
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/impl/jdbc/JdbcSchema.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/impl/jdbc/JdbcSchema.java b/core/src/main/java/net/hydromatic/optiq/impl/jdbc/JdbcSchema.java
index b1940df..0301489 100644
--- a/core/src/main/java/net/hydromatic/optiq/impl/jdbc/JdbcSchema.java
+++ b/core/src/main/java/net/hydromatic/optiq/impl/jdbc/JdbcSchema.java
@@ -240,7 +240,8 @@ public class JdbcSchema implements Schema {
// Temporary type factory, just for the duration of this method. Allowable
// because we're creating a proto-type, not a type; before being used, the
// proto-type will be copied into a real type factory.
- final RelDataTypeFactory typeFactory = new SqlTypeFactoryImpl();
+ final RelDataTypeFactory typeFactory =
+ new SqlTypeFactoryImpl(RelDataTypeSystem.DEFAULT);
final RelDataTypeFactory.FieldInfoBuilder fieldInfo = typeFactory.builder();
while (resultSet.next()) {
final String columnName = resultSet.getString(4);
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/jdbc/JavaTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/jdbc/JavaTypeFactoryImpl.java b/core/src/main/java/net/hydromatic/optiq/jdbc/JavaTypeFactoryImpl.java
index 3202221..67fb093 100644
--- a/core/src/main/java/net/hydromatic/optiq/jdbc/JavaTypeFactoryImpl.java
+++ b/core/src/main/java/net/hydromatic/optiq/jdbc/JavaTypeFactoryImpl.java
@@ -53,6 +53,14 @@ public class JavaTypeFactoryImpl
syntheticTypes =
new HashMap<List<Pair<Type, Boolean>>, SyntheticRecordType>();
+ public JavaTypeFactoryImpl() {
+ this(RelDataTypeSystem.DEFAULT);
+ }
+
+ public JavaTypeFactoryImpl(RelDataTypeSystem typeSystem) {
+ super(typeSystem);
+ }
+
public RelDataType createStructType(Class type) {
List<RelDataTypeField> list = new ArrayList<RelDataTypeField>();
for (Field field : type.getFields()) {
@@ -178,7 +186,7 @@ public class JavaTypeFactoryImpl
}
if (type instanceof JavaType) {
return createTypeWithNullability(
- new BasicSqlType(type.getSqlTypeName()),
+ createSqlType(type.getSqlTypeName()),
type.isNullable());
}
return type;
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/jdbc/OptiqConnectionImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/jdbc/OptiqConnectionImpl.java b/core/src/main/java/net/hydromatic/optiq/jdbc/OptiqConnectionImpl.java
index d5c8592..80d77d3 100644
--- a/core/src/main/java/net/hydromatic/optiq/jdbc/OptiqConnectionImpl.java
+++ b/core/src/main/java/net/hydromatic/optiq/jdbc/OptiqConnectionImpl.java
@@ -35,6 +35,7 @@ import net.hydromatic.optiq.runtime.Hook;
import net.hydromatic.optiq.server.OptiqServer;
import net.hydromatic.optiq.server.OptiqServerStatement;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.advise.SqlAdvisor;
import org.eigenbase.sql.advise.SqlAdvisorValidator;
import org.eigenbase.sql.fun.SqlStdOperatorTable;
@@ -83,13 +84,18 @@ abstract class OptiqConnectionImpl
String url, Properties info, OptiqRootSchema rootSchema,
JavaTypeFactory typeFactory) {
super(driver, factory, url, info);
+ OptiqConnectionConfig cfg = new OptiqConnectionConfigImpl(info);
this.prepareFactory = driver.prepareFactory;
- this.typeFactory =
- typeFactory != null ? typeFactory : new JavaTypeFactoryImpl();
+ if (typeFactory != null) {
+ this.typeFactory = typeFactory;
+ } else {
+ final RelDataTypeSystem typeSystem =
+ cfg.typeSystem(RelDataTypeSystem.class, RelDataTypeSystem.DEFAULT);
+ this.typeFactory = new JavaTypeFactoryImpl(typeSystem);
+ }
this.rootSchema =
rootSchema != null ? rootSchema : OptiqSchema.createRootSchema(true);
- OptiqConnectionConfig cfg = new OptiqConnectionConfigImpl(info);
this.properties.put(InternalProperty.CASE_SENSITIVE, cfg.caseSensitive());
this.properties.put(InternalProperty.UNQUOTED_CASING, cfg.unquotedCasing());
this.properties.put(InternalProperty.QUOTED_CASING, cfg.quotedCasing());
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java b/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
index 369f9b1..4c13cfd 100644
--- a/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
+++ b/core/src/main/java/net/hydromatic/optiq/rules/java/RexToLixTranslator.java
@@ -251,7 +251,9 @@ public class RexToLixTranslator {
BuiltinMethod.INTERVAL_DAY_TIME_TO_STRING.method,
operand,
Expressions.constant(interval.foo()),
- Expressions.constant(interval.getFractionalSecondPrecision())));
+ Expressions.constant(
+ interval.getFractionalSecondPrecision(
+ typeFactory.getTypeSystem()))));
break;
case BOOLEAN:
convert = RexImpTable.optimize2(
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/tools/FrameworkConfig.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/tools/FrameworkConfig.java b/core/src/main/java/net/hydromatic/optiq/tools/FrameworkConfig.java
index 4e9cd84..98d0739 100644
--- a/core/src/main/java/net/hydromatic/optiq/tools/FrameworkConfig.java
+++ b/core/src/main/java/net/hydromatic/optiq/tools/FrameworkConfig.java
@@ -22,6 +22,7 @@ import net.hydromatic.optiq.config.Lex;
import org.eigenbase.relopt.Context;
import org.eigenbase.relopt.RelOptCostFactory;
import org.eigenbase.relopt.RelTraitDef;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.SqlOperatorTable;
import org.eigenbase.sql.parser.SqlParserImplFactory;
import org.eigenbase.sql2rel.SqlRexConvertletTable;
@@ -31,6 +32,8 @@ import com.google.common.collect.ImmutableList;
/**
* Interface that describes how to configure planning sessions generated
* using the Frameworks tools.
+ *
+ * @see Frameworks#newConfigBuilder()
*/
public interface FrameworkConfig {
/**
@@ -107,6 +110,11 @@ public interface FrameworkConfig {
* calling {@link org.eigenbase.relopt.RelOptPlanner#getContext()}.
*/
Context getContext();
+
+ /**
+ * Returns the type system.
+ */
+ RelDataTypeSystem getTypeSystem();
}
// End FrameworkConfig.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/net/hydromatic/optiq/tools/Frameworks.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/net/hydromatic/optiq/tools/Frameworks.java b/core/src/main/java/net/hydromatic/optiq/tools/Frameworks.java
index d08c29c..62b6f3f 100644
--- a/core/src/main/java/net/hydromatic/optiq/tools/Frameworks.java
+++ b/core/src/main/java/net/hydromatic/optiq/tools/Frameworks.java
@@ -18,6 +18,7 @@ package net.hydromatic.optiq.tools;
import net.hydromatic.optiq.SchemaPlus;
import net.hydromatic.optiq.config.Lex;
+import net.hydromatic.optiq.config.OptiqConnectionProperty;
import net.hydromatic.optiq.jdbc.OptiqConnection;
import net.hydromatic.optiq.jdbc.OptiqSchema;
import net.hydromatic.optiq.prepare.OptiqPrepareImpl;
@@ -29,6 +30,7 @@ import org.eigenbase.relopt.RelOptCluster;
import org.eigenbase.relopt.RelOptCostFactory;
import org.eigenbase.relopt.RelOptSchema;
import org.eigenbase.relopt.RelTraitDef;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.SqlOperatorTable;
import org.eigenbase.sql.fun.SqlStdOperatorTable;
import org.eigenbase.sql.parser.SqlParserImplFactory;
@@ -42,6 +44,7 @@ import com.google.common.collect.ImmutableList;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.List;
+import java.util.Properties;
/**
* Tools for invoking Optiq functionality without initializing a container /
@@ -134,8 +137,13 @@ public class Frameworks {
public static <R> R withPrepare(PrepareAction<R> action) {
try {
Class.forName("net.hydromatic.optiq.jdbc.Driver");
+ final Properties info = new Properties();
+ if (action.config.getTypeSystem() != RelDataTypeSystem.DEFAULT) {
+ info.setProperty(OptiqConnectionProperty.TYPE_SYSTEM.camelName(),
+ action.config.getTypeSystem().getClass().getName());
+ }
Connection connection =
- DriverManager.getConnection("jdbc:optiq:");
+ DriverManager.getConnection("jdbc:optiq:", info);
OptiqConnection optiqConnection =
connection.unwrap(OptiqConnection.class);
final OptiqServerStatement statement =
@@ -175,12 +183,14 @@ public class Frameworks {
private SchemaPlus defaultSchema;
private RelOptCostFactory costFactory;
private SqlParserImplFactory parserFactory = SqlParserImpl.FACTORY;
+ private RelDataTypeSystem typeSystem = RelDataTypeSystem.DEFAULT;
private ConfigBuilder() {}
public FrameworkConfig build() {
return new StdFrameworkConfig(context, convertletTable, operatorTable,
- programs, traitDefs, lex, defaultSchema, costFactory, parserFactory);
+ programs, traitDefs, lex, defaultSchema, costFactory, parserFactory,
+ typeSystem);
}
public ConfigBuilder context(Context c) {
@@ -250,6 +260,11 @@ public class Frameworks {
this.parserFactory = Preconditions.checkNotNull(parserFactory);
return this;
}
+
+ public ConfigBuilder typeSystem(RelDataTypeSystem typeSystem) {
+ this.typeSystem = Preconditions.checkNotNull(typeSystem);
+ return this;
+ }
}
/**
@@ -266,6 +281,7 @@ public class Frameworks {
private final SchemaPlus defaultSchema;
private final RelOptCostFactory costFactory;
private final SqlParserImplFactory parserFactory;
+ private final RelDataTypeSystem typeSystem;
public StdFrameworkConfig(Context context,
SqlRexConvertletTable convertletTable,
@@ -275,7 +291,8 @@ public class Frameworks {
Lex lex,
SchemaPlus defaultSchema,
RelOptCostFactory costFactory,
- SqlParserImplFactory parserFactory) {
+ SqlParserImplFactory parserFactory,
+ RelDataTypeSystem typeSystem) {
this.context = context;
this.convertletTable = convertletTable;
this.operatorTable = operatorTable;
@@ -285,6 +302,7 @@ public class Frameworks {
this.defaultSchema = defaultSchema;
this.costFactory = costFactory;
this.parserFactory = parserFactory;
+ this.typeSystem = typeSystem;
}
public Lex getLex() {
@@ -322,6 +340,10 @@ public class Frameworks {
public SqlOperatorTable getOperatorTable() {
return operatorTable;
}
+
+ public RelDataTypeSystem getTypeSystem() {
+ return typeSystem;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/rel/rules/ReduceDecimalsRule.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rel/rules/ReduceDecimalsRule.java b/core/src/main/java/org/eigenbase/rel/rules/ReduceDecimalsRule.java
index 1a9325d..d89561d 100644
--- a/core/src/main/java/org/eigenbase/rel/rules/ReduceDecimalsRule.java
+++ b/core/src/main/java/org/eigenbase/rel/rules/ReduceDecimalsRule.java
@@ -336,7 +336,9 @@ public class ReduceDecimalsRule extends RelOptRule {
* @return 10^scale as an exact numeric value
*/
protected RexNode makeScaleFactor(int scale) {
- assert (scale > 0) && (scale < SqlTypeName.MAX_NUMERIC_PRECISION);
+ assert scale > 0;
+ assert scale
+ < builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
return makeExactLiteral(powerOfTen(scale));
}
@@ -364,7 +366,9 @@ public class ReduceDecimalsRule extends RelOptRule {
* @return 10^scale / 2 as an exact numeric value
*/
protected RexNode makeRoundFactor(int scale) {
- assert (scale > 0) && (scale < SqlTypeName.MAX_NUMERIC_PRECISION);
+ assert scale > 0;
+ assert scale
+ < builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
return makeExactLiteral(powerOfTen(scale) / 2);
}
@@ -372,7 +376,9 @@ public class ReduceDecimalsRule extends RelOptRule {
* Calculates a power of ten, as a long value
*/
protected long powerOfTen(int scale) {
- assert (scale >= 0) && (scale < SqlTypeName.MAX_NUMERIC_PRECISION);
+ assert scale >= 0;
+ assert scale
+ < builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
return BigInteger.TEN.pow(scale).longValue();
}
@@ -400,7 +406,9 @@ public class ReduceDecimalsRule extends RelOptRule {
* @return value * 10^scale as an exact numeric value
*/
protected RexNode scaleUp(RexNode value, int scale) {
- assert (scale >= 0) && (scale < SqlTypeName.MAX_NUMERIC_PRECISION);
+ assert scale >= 0;
+ assert scale
+ < builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
if (scale == 0) {
return value;
}
@@ -422,8 +430,9 @@ public class ReduceDecimalsRule extends RelOptRule {
* exact numeric value
*/
protected RexNode scaleDown(RexNode value, int scale) {
- int maxPrecision = SqlTypeName.MAX_NUMERIC_PRECISION;
- assert (scale >= 0) && (scale <= maxPrecision);
+ final int maxPrecision =
+ builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
+ assert scale >= 0 && scale <= maxPrecision;
if (scale == 0) {
return value;
}
@@ -462,12 +471,13 @@ public class ReduceDecimalsRule extends RelOptRule {
* double precision arithmetic.
*
* @param value the integer representation of a decimal
- * @param scale a value from zero to {@link
- * SqlTypeName#MAX_NUMERIC_PRECISION MAX_NUMERIC_PRECISION}
+ * @param scale a value from zero to max precision
* @return value/10^scale as a double precision value
*/
protected RexNode scaleDownDouble(RexNode value, int scale) {
- assert (scale >= 0) && (scale <= SqlTypeName.MAX_NUMERIC_PRECISION);
+ assert scale >= 0;
+ assert scale
+ <= builder.getTypeFactory().getTypeSystem().getMaxNumericPrecision();
RexNode cast = ensureType(real8, value);
if (scale == 0) {
return cast;
@@ -495,8 +505,10 @@ public class ReduceDecimalsRule extends RelOptRule {
* corresponding to the input value
*/
protected RexNode ensureScale(RexNode value, int scale, int required) {
- int maxPrecision = SqlTypeName.MAX_NUMERIC_PRECISION;
- assert (scale <= maxPrecision) && (required <= maxPrecision);
+ final RelDataTypeSystem typeSystem =
+ builder.getTypeFactory().getTypeSystem();
+ final int maxPrecision = typeSystem.getMaxNumericPrecision();
+ assert scale <= maxPrecision && required <= maxPrecision;
assert required >= scale;
if (scale == required) {
return value;
@@ -509,7 +521,7 @@ public class ReduceDecimalsRule extends RelOptRule {
}
// TODO: make a validator exception for this
- if (scaleDiff >= SqlTypeName.MAX_NUMERIC_PRECISION) {
+ if (scaleDiff >= maxPrecision) {
throw Util.needToImplement(
"Source type with scale " + scale
+ " cannot be converted to target type with scale "
@@ -1002,11 +1014,13 @@ public class ReduceDecimalsRule extends RelOptRule {
RexNode decValue = call.operands.get(0);
int scale = decValue.getType().getScale();
RexNode value = decodeValue(decValue);
+ final RelDataTypeSystem typeSystem =
+ builder.getTypeFactory().getTypeSystem();
RexNode rewrite;
if (scale == 0) {
rewrite = decValue;
- } else if (scale == SqlTypeName.MAX_NUMERIC_PRECISION) {
+ } else if (scale == typeSystem.getMaxNumericPrecision()) {
rewrite =
makeCase(
makeIsNegative(value),
@@ -1049,11 +1063,13 @@ public class ReduceDecimalsRule extends RelOptRule {
RexNode decValue = call.operands.get(0);
int scale = decValue.getType().getScale();
RexNode value = decodeValue(decValue);
+ final RelDataTypeSystem typeSystem =
+ builder.getTypeFactory().getTypeSystem();
RexNode rewrite;
if (scale == 0) {
rewrite = decValue;
- } else if (scale == SqlTypeName.MAX_NUMERIC_PRECISION) {
+ } else if (scale == typeSystem.getMaxNumericPrecision()) {
rewrite =
makeCase(
makeIsPositive(value),
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactory.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactory.java b/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactory.java
index ab26365..0d9fd06 100644
--- a/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactory.java
+++ b/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactory.java
@@ -40,6 +40,11 @@ public interface RelDataTypeFactory {
//~ Methods ----------------------------------------------------------------
/**
+ * Returns the type system.
+ */
+ RelDataTypeSystem getTypeSystem();
+
+ /**
* Creates a type which corresponds to a Java class.
*
* @param clazz the Java class used to define the type
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactoryImpl.java b/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactoryImpl.java
index db9ceda..80d066c 100644
--- a/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactoryImpl.java
+++ b/core/src/main/java/org/eigenbase/reltype/RelDataTypeFactoryImpl.java
@@ -88,13 +88,30 @@ public abstract class RelDataTypeFactoryImpl implements RelDataTypeFactory {
.put(Timestamp.class, SqlTypeFamily.TIMESTAMP)
.build();
+ protected final RelDataTypeSystem typeSystem;
+
//~ Constructors -----------------------------------------------------------
+ /** Creates a type factory with default type system.
+ *
+ * @deprecated Will be removed after optiq-0.9.1.
+ */
protected RelDataTypeFactoryImpl() {
+ this(RelDataTypeSystem.DEFAULT);
+ Bug.upgrade("optiq-0.9.1");
+ }
+
+ /** Creates a type factory. */
+ protected RelDataTypeFactoryImpl(RelDataTypeSystem typeSystem) {
+ this.typeSystem = Preconditions.checkNotNull(typeSystem);
}
//~ Methods ----------------------------------------------------------------
+ public RelDataTypeSystem getTypeSystem() {
+ return typeSystem;
+ }
+
// implement RelDataTypeFactory
public RelDataType createJavaType(Class clazz) {
final JavaType javaType =
@@ -450,12 +467,12 @@ public abstract class RelDataTypeFactoryImpl implements RelDataTypeFactory {
int s2 = type2.getScale();
int scale = s1 + s2;
- scale = Math.min(scale, SqlTypeName.MAX_NUMERIC_SCALE);
+ scale = Math.min(scale, typeSystem.getMaxNumericScale());
int precision = p1 + p2;
precision =
Math.min(
precision,
- SqlTypeName.MAX_NUMERIC_PRECISION);
+ typeSystem.getMaxNumericPrecision());
RelDataType ret;
ret =
@@ -511,20 +528,21 @@ public abstract class RelDataTypeFactoryImpl implements RelDataTypeFactory {
int s1 = type1.getScale();
int s2 = type2.getScale();
+ final int maxNumericPrecision = typeSystem.getMaxNumericPrecision();
int dout =
Math.min(
p1 - s1 + s2,
- SqlTypeName.MAX_NUMERIC_PRECISION);
+ maxNumericPrecision);
int scale = Math.max(6, s1 + p2 + 1);
scale =
Math.min(
scale,
- SqlTypeName.MAX_NUMERIC_PRECISION - dout);
- scale = Math.min(scale, SqlTypeName.MAX_NUMERIC_SCALE);
+ maxNumericPrecision - dout);
+ scale = Math.min(scale, getTypeSystem().getMaxNumericScale());
int precision = dout + scale;
- assert precision <= SqlTypeName.MAX_NUMERIC_PRECISION;
+ assert precision <= maxNumericPrecision;
assert precision > 0;
RelDataType ret;
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystem.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystem.java b/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystem.java
new file mode 100644
index 0000000..e72722f
--- /dev/null
+++ b/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystem.java
@@ -0,0 +1,60 @@
+/*
+ * 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.eigenbase.reltype;
+
+import org.eigenbase.sql.type.SqlTypeName;
+
+/**
+ * Type system.
+ *
+ * <p>Provides behaviors concerning type limits and behaviors. For example,
+ * in the default system, a DECIMAL can have maximum precision 19, but Hive
+ * overrides to 38.
+ *
+ * <p>The default implementation is {@link #DEFAULT}.
+ */
+public interface RelDataTypeSystem {
+ /** Default type system. */
+ RelDataTypeSystem DEFAULT = new RelDataTypeSystemImpl() { };
+
+ /** Returns the maximum scale of a given type. */
+ int getMaxScale(SqlTypeName typeName);
+
+ /**
+ * Returns default precision for this type if supported, otherwise -1 if
+ * precision is either unsupported or must be specified explicitly.
+ *
+ * @return Default precision
+ */
+ int getDefaultPrecision(SqlTypeName typeName);
+
+ /**
+ * Returns the maximum precision (or length) allowed for this type, or -1 if
+ * precision/length are not applicable for this type.
+ *
+ * @return Maximum allowed precision
+ */
+ int getMaxPrecision(SqlTypeName typeName);
+
+ /** Returns the maximum scale of a NUMERIC or DECIMAL type. */
+ int getMaxNumericScale();
+
+ /** Returns the maximum precision of a NUMERIC or DECIMAL type. */
+ int getMaxNumericPrecision();
+}
+
+// End RelDataTypeFactory.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystemImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystemImpl.java b/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystemImpl.java
new file mode 100644
index 0000000..b158974
--- /dev/null
+++ b/core/src/main/java/org/eigenbase/reltype/RelDataTypeSystemImpl.java
@@ -0,0 +1,98 @@
+/*
+ * 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.eigenbase.reltype;
+
+import org.eigenbase.sql.type.SqlTypeName;
+
+/** Default implementation of {@link org.eigenbase.reltype.RelDataTypeSystem},
+ * providing parameters from the SQL standard.
+ *
+ * <p>To implement other type systems, create a derived class and override
+ * values as needed.
+ *
+ * <table border='1'>
+ * <tr><td>Parameter</td> <td>Value</td></tr>
+ * <tr><td>MAX_NUMERIC_SCALE</td><td>19</td></tr>
+ * </table>
+ */
+public abstract class RelDataTypeSystemImpl implements RelDataTypeSystem {
+ public int getMaxScale(SqlTypeName typeName) {
+ switch (typeName) {
+ case DECIMAL:
+ return getMaxNumericScale();
+ case INTERVAL_DAY_TIME:
+ case INTERVAL_YEAR_MONTH:
+ return SqlTypeName.MAX_INTERVAL_FRACTIONAL_SECOND_PRECISION;
+ default:
+ return -1;
+ }
+ }
+
+ public int getDefaultPrecision(SqlTypeName typeName) {
+ switch (typeName) {
+ case CHAR:
+ case BINARY:
+ case VARCHAR:
+ case VARBINARY:
+ return 1;
+ case TIME:
+ return 0;
+ case TIMESTAMP:
+ // TODO jvs 26-July-2004: should be 6 for microseconds,
+ // but we can't support that yet
+ return 0;
+ case DECIMAL:
+ return getMaxNumericPrecision();
+ case INTERVAL_DAY_TIME:
+ case INTERVAL_YEAR_MONTH:
+ return SqlTypeName.DEFAULT_INTERVAL_START_PRECISION;
+ default:
+ return -1;
+ }
+ }
+
+ public int getMaxPrecision(SqlTypeName typeName) {
+ switch (typeName) {
+ case DECIMAL:
+ return getMaxNumericPrecision();
+ case VARCHAR:
+ case CHAR:
+ return 65536;
+ case VARBINARY:
+ case BINARY:
+ return 65536;
+ case TIME:
+ case TIMESTAMP:
+ return SqlTypeName.MAX_DATETIME_PRECISION;
+ case INTERVAL_DAY_TIME:
+ case INTERVAL_YEAR_MONTH:
+ return SqlTypeName.MAX_INTERVAL_START_PRECISION;
+ default:
+ return -1;
+ }
+ }
+
+ public int getMaxNumericScale() {
+ return 19;
+ }
+
+ public int getMaxNumericPrecision() {
+ return 19;
+ }
+}
+
+// End RelDataTypeSystemImpl.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/rex/RexBuilder.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rex/RexBuilder.java b/core/src/main/java/org/eigenbase/rex/RexBuilder.java
index d393a16..251af45 100644
--- a/core/src/main/java/org/eigenbase/rex/RexBuilder.java
+++ b/core/src/main/java/org/eigenbase/rex/RexBuilder.java
@@ -529,7 +529,8 @@ public class RexBuilder {
if (endUnit == TimeUnit.SECOND) {
scale = Math.min(
intervalType.getIntervalQualifier()
- .getFractionalSecondPrecision(), 3);
+ .getFractionalSecondPrecision(typeFactory.getTypeSystem()),
+ 3);
}
BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
.divide(BigDecimal.TEN.pow(scale));
@@ -560,7 +561,8 @@ public class RexBuilder {
if (endUnit == TimeUnit.SECOND) {
scale = Math.min(
intervalType.getIntervalQualifier()
- .getFractionalSecondPrecision(), 3);
+ .getFractionalSecondPrecision(typeFactory.getTypeSystem()),
+ 3);
}
BigDecimal multiplier = BigDecimal.valueOf(endUnit.multiplier)
.divide(BigDecimal.TEN.pow(scale));
@@ -798,7 +800,8 @@ public class RexBuilder {
RelDataType relType;
int scale = bd.scale();
long l = bd.unscaledValue().longValue();
- assert (scale >= 0) && (scale <= SqlTypeName.MAX_NUMERIC_SCALE);
+ assert scale >= 0;
+ assert scale <= typeFactory.getTypeSystem().getMaxNumericScale() : scale;
assert BigDecimal.valueOf(l, scale).equals(bd);
if (scale == 0) {
if ((l >= Integer.MIN_VALUE) && (l <= Integer.MAX_VALUE)) {
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/rex/RexExecutorImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/rex/RexExecutorImpl.java b/core/src/main/java/org/eigenbase/rex/RexExecutorImpl.java
index b187344..da34a55 100644
--- a/core/src/main/java/org/eigenbase/rex/RexExecutorImpl.java
+++ b/core/src/main/java/org/eigenbase/rex/RexExecutorImpl.java
@@ -61,7 +61,8 @@ public class RexExecutorImpl implements RelOptPlanner.Executor {
programBuilder.addProject(
node, "c" + programBuilder.getProjectList().size());
}
- final JavaTypeFactoryImpl javaTypeFactory = new JavaTypeFactoryImpl();
+ final JavaTypeFactoryImpl javaTypeFactory =
+ new JavaTypeFactoryImpl(rexBuilder.getTypeFactory().getTypeSystem());
final BlockBuilder blockBuilder = new BlockBuilder();
final ParameterExpression root0_ =
Expressions.parameter(Object.class, "root0");
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/SqlIntervalQualifier.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/SqlIntervalQualifier.java b/core/src/main/java/org/eigenbase/sql/SqlIntervalQualifier.java
index 2d3eb7c..406ed57 100644
--- a/core/src/main/java/org/eigenbase/sql/SqlIntervalQualifier.java
+++ b/core/src/main/java/org/eigenbase/sql/SqlIntervalQualifier.java
@@ -20,6 +20,8 @@ import java.math.BigDecimal;
import java.util.*;
import java.util.regex.*;
+import org.eigenbase.reltype.RelDataType;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.parser.*;
import org.eigenbase.sql.type.*;
import org.eigenbase.sql.util.*;
@@ -29,6 +31,7 @@ import org.eigenbase.util14.DateTimeUtil;
import net.hydromatic.optiq.runtime.SqlFunctions;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import static org.eigenbase.util.Static.RESOURCE;
@@ -83,7 +86,6 @@ import static org.eigenbase.util.Static.RESOURCE;
public class SqlIntervalQualifier extends SqlNode {
//~ Static fields/initializers ---------------------------------------------
- private static final int USE_DEFAULT_PRECISION = -1;
private static final BigDecimal ZERO = BigDecimal.ZERO;
private static final BigDecimal THOUSAND = BigDecimal.valueOf(1000);
private static final BigDecimal INT_MAX_VALUE_PLUS_ONE =
@@ -204,9 +206,6 @@ public class SqlIntervalQualifier extends SqlNode {
private final TimeUnitRange timeUnitRange;
private final int fractionalSecondPrecision;
- private final boolean useDefaultStartPrecision;
- private final boolean useDefaultFractionalSecondPrecision;
-
//~ Constructors -----------------------------------------------------------
public SqlIntervalQualifier(
@@ -216,39 +215,10 @@ public class SqlIntervalQualifier extends SqlNode {
int fractionalSecondPrecision,
SqlParserPos pos) {
super(pos);
- assert null != startUnit;
-
- this.timeUnitRange = TimeUnitRange.of(startUnit, endUnit);
-
- // if unspecified, start precision = 2
- if (startPrecision == USE_DEFAULT_PRECISION) {
- useDefaultStartPrecision = true;
- if (this.isYearMonth()) {
- this.startPrecision =
- SqlTypeName.INTERVAL_YEAR_MONTH.getDefaultPrecision();
- } else {
- this.startPrecision =
- SqlTypeName.INTERVAL_DAY_TIME.getDefaultPrecision();
- }
- } else {
- useDefaultStartPrecision = false;
- this.startPrecision = startPrecision;
- }
-
- // unspecified fractional second precision = 6
- if (fractionalSecondPrecision == USE_DEFAULT_PRECISION) {
- useDefaultFractionalSecondPrecision = true;
- if (this.isYearMonth()) {
- this.fractionalSecondPrecision =
- SqlTypeName.INTERVAL_YEAR_MONTH.getDefaultScale();
- } else {
- this.fractionalSecondPrecision =
- SqlTypeName.INTERVAL_DAY_TIME.getDefaultScale();
- }
- } else {
- useDefaultFractionalSecondPrecision = false;
- this.fractionalSecondPrecision = fractionalSecondPrecision;
- }
+ this.timeUnitRange =
+ TimeUnitRange.of(Preconditions.checkNotNull(startUnit), endUnit);
+ this.startPrecision = startPrecision;
+ this.fractionalSecondPrecision = fractionalSecondPrecision;
}
public SqlIntervalQualifier(
@@ -257,14 +227,20 @@ public class SqlIntervalQualifier extends SqlNode {
SqlParserPos pos) {
this(
startUnit,
- USE_DEFAULT_PRECISION,
+ RelDataType.PRECISION_NOT_SPECIFIED,
endUnit,
- USE_DEFAULT_PRECISION,
+ RelDataType.PRECISION_NOT_SPECIFIED,
pos);
}
//~ Methods ----------------------------------------------------------------
+ public SqlTypeName typeName() {
+ return isYearMonth()
+ ? SqlTypeName.INTERVAL_YEAR_MONTH
+ : SqlTypeName.INTERVAL_DAY_TIME;
+ }
+
public SqlFunctions.TimeUnitRange foo() {
return SqlFunctions.TimeUnitRange.valueOf(timeUnitRange.name());
}
@@ -289,33 +265,34 @@ public class SqlIntervalQualifier extends SqlNode {
return true;
}
- public static int getDefaultPrecisionId() {
- return USE_DEFAULT_PRECISION;
+ public int getStartPrecision(RelDataTypeSystem typeSystem) {
+ if (startPrecision == RelDataType.PRECISION_NOT_SPECIFIED) {
+ return typeSystem.getDefaultPrecision(typeName());
+ } else {
+ return startPrecision;
+ }
}
- public int getStartPrecision() {
+ public int getStartPrecisionPreservingDefault() {
return startPrecision;
}
- public int getStartPrecisionPreservingDefault() {
- if (useDefaultStartPrecision) {
- return USE_DEFAULT_PRECISION;
- } else {
- return startPrecision;
- }
+ private boolean useDefaultStartPrecision() {
+ return startPrecision == RelDataType.PRECISION_NOT_SPECIFIED;
}
public static int combineStartPrecisionPreservingDefault(
+ RelDataTypeSystem typeSystem,
SqlIntervalQualifier qual1,
SqlIntervalQualifier qual2) {
- if (qual1.getStartPrecision()
- > qual2.getStartPrecision()) {
+ final int start1 = qual1.getStartPrecision(typeSystem);
+ final int start2 = qual2.getStartPrecision(typeSystem);
+ if (start1 > start2) {
// qual1 is more precise, but if it has the default indicator
// set, we need to return that indicator so result will also
// use default
return qual1.getStartPrecisionPreservingDefault();
- } else if (qual1.getStartPrecision()
- < qual2.getStartPrecision()) {
+ } else if (start1 < start2) {
// qual2 is more precise, but if it has the default indicator
// set, we need to return that indicator so result will also
// use default
@@ -323,39 +300,47 @@ public class SqlIntervalQualifier extends SqlNode {
} else {
// they are equal. return default if both are default,
// otherwise return exact precision
- if (qual1.useDefaultStartPrecision
- && qual2.useDefaultStartPrecision) {
+ if (qual1.useDefaultStartPrecision()
+ && qual2.useDefaultStartPrecision()) {
return qual1.getStartPrecisionPreservingDefault();
} else {
- return qual1.getStartPrecision();
+ return start1;
}
}
}
- public int getFractionalSecondPrecision() {
- return fractionalSecondPrecision;
+ public int getFractionalSecondPrecision(RelDataTypeSystem typeSystem) {
+ if (fractionalSecondPrecision == RelDataType.PRECISION_NOT_SPECIFIED) {
+ return typeName().getDefaultScale();
+ } else {
+ return fractionalSecondPrecision;
+ }
}
public int getFractionalSecondPrecisionPreservingDefault() {
- if (useDefaultFractionalSecondPrecision) {
- return USE_DEFAULT_PRECISION;
+ if (useDefaultFractionalSecondPrecision()) {
+ return RelDataType.PRECISION_NOT_SPECIFIED;
} else {
return startPrecision;
}
}
+ private boolean useDefaultFractionalSecondPrecision() {
+ return fractionalSecondPrecision == RelDataType.PRECISION_NOT_SPECIFIED;
+ }
+
public static int combineFractionalSecondPrecisionPreservingDefault(
+ RelDataTypeSystem typeSystem,
SqlIntervalQualifier qual1,
SqlIntervalQualifier qual2) {
- if (qual1.getFractionalSecondPrecision()
- > qual2.getFractionalSecondPrecision()) {
+ final int p1 = qual1.getFractionalSecondPrecision(typeSystem);
+ final int p2 = qual2.getFractionalSecondPrecision(typeSystem);
+ if (p1 > p2) {
// qual1 is more precise, but if it has the default indicator
// set, we need to return that indicator so result will also
// use default
return qual1.getFractionalSecondPrecisionPreservingDefault();
- } else if (
- qual1.getFractionalSecondPrecision()
- < qual2.getFractionalSecondPrecision()) {
+ } else if (p1 < p2) {
// qual2 is more precise, but if it has the default indicator
// set, we need to return that indicator so result will also
// use default
@@ -363,11 +348,11 @@ public class SqlIntervalQualifier extends SqlNode {
} else {
// they are equal. return default if both are default,
// otherwise return exact precision
- if (qual1.useDefaultFractionalSecondPrecision
- && qual2.useDefaultFractionalSecondPrecision) {
+ if (qual1.useDefaultFractionalSecondPrecision()
+ && qual2.useDefaultFractionalSecondPrecision()) {
return qual1.getFractionalSecondPrecisionPreservingDefault();
} else {
- return qual1.getFractionalSecondPrecision();
+ return p1;
}
}
}
@@ -381,29 +366,30 @@ public class SqlIntervalQualifier extends SqlNode {
}
public SqlNode clone(SqlParserPos pos) {
- return new SqlIntervalQualifier(
- timeUnitRange.startUnit,
- useDefaultStartPrecision ? USE_DEFAULT_PRECISION
- : startPrecision,
- timeUnitRange.endUnit,
- useDefaultFractionalSecondPrecision ? USE_DEFAULT_PRECISION
- : fractionalSecondPrecision,
- pos);
+ return new SqlIntervalQualifier(timeUnitRange.startUnit, startPrecision,
+ timeUnitRange.endUnit, fractionalSecondPrecision, pos);
}
public void unparse(
SqlWriter writer,
int leftPrec,
int rightPrec) {
+ unparse(RelDataTypeSystem.DEFAULT, writer);
+ }
+
+ public void unparse(RelDataTypeSystem typeSystem, SqlWriter writer) {
final String start = timeUnitRange.startUnit.name();
+ final int fractionalSecondPrecision =
+ getFractionalSecondPrecision(typeSystem);
+ final int startPrecision = getStartPrecision(typeSystem);
if (timeUnitRange.startUnit == TimeUnit.SECOND) {
- if (!useDefaultFractionalSecondPrecision) {
+ if (!useDefaultFractionalSecondPrecision()) {
final SqlWriter.Frame frame = writer.startFunCall(start);
writer.print(startPrecision);
writer.sep(",", true);
- writer.print(fractionalSecondPrecision);
+ writer.print(getFractionalSecondPrecision(typeSystem));
writer.endList(frame);
- } else if (!useDefaultStartPrecision) {
+ } else if (!useDefaultStartPrecision()) {
final SqlWriter.Frame frame = writer.startFunCall(start);
writer.print(startPrecision);
writer.endList(frame);
@@ -411,7 +397,7 @@ public class SqlIntervalQualifier extends SqlNode {
writer.keyword(start);
}
} else {
- if (!useDefaultStartPrecision) {
+ if (!useDefaultStartPrecision()) {
final SqlWriter.Frame frame = writer.startFunCall(start);
writer.print(startPrecision);
writer.endList(frame);
@@ -423,7 +409,7 @@ public class SqlIntervalQualifier extends SqlNode {
writer.keyword("TO");
final String end = timeUnitRange.endUnit.name();
if ((TimeUnit.SECOND == timeUnitRange.endUnit)
- && (!useDefaultFractionalSecondPrecision)) {
+ && (!useDefaultFractionalSecondPrecision())) {
final SqlWriter.Frame frame = writer.startFunCall(end);
writer.print(fractionalSecondPrecision);
writer.endList(frame);
@@ -474,21 +460,23 @@ public class SqlIntervalQualifier extends SqlNode {
return unsignedValue;
}
- private boolean isLeadFieldInRange(BigDecimal value, TimeUnit unit) {
+ private boolean isLeadFieldInRange(RelDataTypeSystem typeSystem,
+ BigDecimal value, TimeUnit unit) {
// we should never get handed a negative field value
assert value.compareTo(ZERO) >= 0;
// Leading fields are only restricted by startPrecision.
+ final int startPrecision = getStartPrecision(typeSystem);
return startPrecision < POWERS10.length
? value.compareTo(POWERS10[startPrecision]) < 0
: value.compareTo(INT_MAX_VALUE_PLUS_ONE) < 0;
}
- private void checkLeadFieldInRange(
- int sign, BigDecimal value, TimeUnit unit, SqlParserPos pos) {
- if (!isLeadFieldInRange(value, unit)) {
+ private void checkLeadFieldInRange(RelDataTypeSystem typeSystem, int sign,
+ BigDecimal value, TimeUnit unit, SqlParserPos pos) {
+ if (!isLeadFieldInRange(typeSystem, value, unit)) {
throw fieldExceedsPrecisionException(
- pos, sign, value, unit, startPrecision);
+ pos, sign, value, unit, getStartPrecision(typeSystem));
}
}
@@ -581,7 +569,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsYear(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -600,7 +588,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, year, TimeUnit.YEAR, pos);
+ checkLeadFieldInRange(typeSystem, sign, year, TimeUnit.YEAR, pos);
// package values up for return
return fillIntervalValueArray(sign, year, ZERO);
@@ -615,7 +603,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsYearToMonth(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -636,7 +624,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, year, TimeUnit.YEAR, pos);
+ checkLeadFieldInRange(typeSystem, sign, year, TimeUnit.YEAR, pos);
if (!(isSecondaryFieldInRange(month, TimeUnit.MONTH))) {
throw invalidValueException(pos, originalValue);
}
@@ -654,7 +642,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsMonth(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -673,7 +661,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, month, TimeUnit.MONTH, pos);
+ checkLeadFieldInRange(typeSystem, sign, month, TimeUnit.MONTH, pos);
// package values up for return
return fillIntervalValueArray(sign, ZERO, month);
@@ -688,7 +676,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsDay(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -707,7 +695,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, day, TimeUnit.DAY, pos);
+ checkLeadFieldInRange(typeSystem, sign, day, TimeUnit.DAY, pos);
// package values up for return
return fillIntervalValueArray(sign, day, ZERO, ZERO, ZERO, ZERO);
@@ -722,7 +710,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsDayToHour(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -743,7 +731,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, day, TimeUnit.DAY, pos);
+ checkLeadFieldInRange(typeSystem, sign, day, TimeUnit.DAY, pos);
if (!(isSecondaryFieldInRange(hour, TimeUnit.HOUR))) {
throw invalidValueException(pos, originalValue);
}
@@ -761,7 +749,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsDayToMinute(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -784,7 +772,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, day, TimeUnit.DAY, pos);
+ checkLeadFieldInRange(typeSystem, sign, day, TimeUnit.DAY, pos);
if (!(isSecondaryFieldInRange(hour, TimeUnit.HOUR))
|| !(isSecondaryFieldInRange(minute, TimeUnit.MINUTE))) {
throw invalidValueException(pos, originalValue);
@@ -803,7 +791,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsDayToSecond(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -817,6 +805,8 @@ public class SqlIntervalQualifier extends SqlNode {
// validate as DAY(startPrecision) TO MINUTE,
// e.g. 'DD HH:MM:SS' or 'DD HH:MM:SS.SSS'
// Note: must check two patterns, since fractional second is optional
+ final int fractionalSecondPrecision =
+ getFractionalSecondPrecision(typeSystem);
String intervalPatternWithFracSec =
"(\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})\\.(\\d{1,"
+ fractionalSecondPrecision + "})";
@@ -849,7 +839,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, day, TimeUnit.DAY, pos);
+ checkLeadFieldInRange(typeSystem, sign, day, TimeUnit.DAY, pos);
if (!(isSecondaryFieldInRange(hour, TimeUnit.HOUR))
|| !(isSecondaryFieldInRange(minute, TimeUnit.MINUTE))
|| !(isSecondaryFieldInRange(second, TimeUnit.SECOND))
@@ -876,7 +866,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsHour(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -895,7 +885,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, hour, TimeUnit.HOUR, pos);
+ checkLeadFieldInRange(typeSystem, sign, hour, TimeUnit.HOUR, pos);
// package values up for return
return fillIntervalValueArray(sign, ZERO, hour, ZERO, ZERO, ZERO);
@@ -911,7 +901,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsHourToMinute(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -932,7 +922,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, hour, TimeUnit.HOUR, pos);
+ checkLeadFieldInRange(typeSystem, sign, hour, TimeUnit.HOUR, pos);
if (!(isSecondaryFieldInRange(minute, TimeUnit.MINUTE))) {
throw invalidValueException(pos, originalValue);
}
@@ -951,7 +941,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsHourToSecond(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -964,6 +954,8 @@ public class SqlIntervalQualifier extends SqlNode {
// validate as HOUR(startPrecision) TO SECOND,
// e.g. 'HH:MM:SS' or 'HH:MM:SS.SSS'
// Note: must check two patterns, since fractional second is optional
+ final int fractionalSecondPrecision =
+ getFractionalSecondPrecision(typeSystem);
String intervalPatternWithFracSec =
"(\\d+):(\\d{1,2}):(\\d{1,2})\\.(\\d{1,"
+ fractionalSecondPrecision + "})";
@@ -995,7 +987,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, hour, TimeUnit.HOUR, pos);
+ checkLeadFieldInRange(typeSystem, sign, hour, TimeUnit.HOUR, pos);
if (!(isSecondaryFieldInRange(minute, TimeUnit.MINUTE))
|| !(isSecondaryFieldInRange(second, TimeUnit.SECOND))
|| !(isFractionalSecondFieldInRange(secondFrac))) {
@@ -1021,7 +1013,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsMinute(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -1040,7 +1032,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, minute, TimeUnit.MINUTE, pos);
+ checkLeadFieldInRange(typeSystem, sign, minute, TimeUnit.MINUTE, pos);
// package values up for return
return fillIntervalValueArray(sign, ZERO, ZERO, minute, ZERO, ZERO);
@@ -1056,7 +1048,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsMinuteToSecond(
- int sign,
+ RelDataTypeSystem typeSystem, int sign,
String value,
String originalValue,
SqlParserPos pos) {
@@ -1068,6 +1060,8 @@ public class SqlIntervalQualifier extends SqlNode {
// validate as MINUTE(startPrecision) TO SECOND,
// e.g. 'MM:SS' or 'MM:SS.SSS'
// Note: must check two patterns, since fractional second is optional
+ final int fractionalSecondPrecision =
+ getFractionalSecondPrecision(typeSystem);
String intervalPatternWithFracSec =
"(\\d+):(\\d{1,2})\\.(\\d{1," + fractionalSecondPrecision + "})";
String intervalPatternWithoutFracSec =
@@ -1097,7 +1091,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, minute, TimeUnit.MINUTE, pos);
+ checkLeadFieldInRange(typeSystem, sign, minute, TimeUnit.MINUTE, pos);
if (!(isSecondaryFieldInRange(second, TimeUnit.SECOND))
|| !(isFractionalSecondFieldInRange(secondFrac))) {
throw invalidValueException(pos, originalValue);
@@ -1122,6 +1116,7 @@ public class SqlIntervalQualifier extends SqlNode {
* @throws EigenbaseContextException if the interval value is illegal.
*/
private int[] evaluateIntervalLiteralAsSecond(
+ RelDataTypeSystem typeSystem,
int sign,
String value,
String originalValue,
@@ -1133,6 +1128,8 @@ public class SqlIntervalQualifier extends SqlNode {
// validate as SECOND(startPrecision, fractionalSecondPrecision)
// e.g. 'SS' or 'SS.SSS'
// Note: must check two patterns, since fractional second is optional
+ final int fractionalSecondPrecision =
+ getFractionalSecondPrecision(typeSystem);
String intervalPatternWithFracSec =
"(\\d+)\\.(\\d{1," + fractionalSecondPrecision + "})";
String intervalPatternWithoutFracSec =
@@ -1161,7 +1158,7 @@ public class SqlIntervalQualifier extends SqlNode {
}
// Validate individual fields
- checkLeadFieldInRange(sign, second, TimeUnit.SECOND, pos);
+ checkLeadFieldInRange(typeSystem, sign, second, TimeUnit.SECOND, pos);
if (!(isFractionalSecondFieldInRange(secondFrac))) {
throw invalidValueException(pos, originalValue);
}
@@ -1183,7 +1180,8 @@ public class SqlIntervalQualifier extends SqlNode {
* @return field values, never null
* @throws EigenbaseContextException if the interval value is illegal
*/
- public int[] evaluateIntervalLiteral(String value, SqlParserPos pos) {
+ public int[] evaluateIntervalLiteral(String value, SqlParserPos pos,
+ RelDataTypeSystem typeSystem) {
// save original value for if we have to throw
final String value0 = value;
@@ -1207,31 +1205,43 @@ public class SqlIntervalQualifier extends SqlNode {
// well as explicit or implicit precision and range.
switch (timeUnitRange) {
case YEAR:
- return evaluateIntervalLiteralAsYear(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsYear(typeSystem, sign, value, value0,
+ pos);
case YEAR_TO_MONTH:
- return evaluateIntervalLiteralAsYearToMonth(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsYearToMonth(typeSystem, sign, value,
+ value0, pos);
case MONTH:
- return evaluateIntervalLiteralAsMonth(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsMonth(typeSystem, sign, value, value0,
+ pos);
case DAY:
- return evaluateIntervalLiteralAsDay(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsDay(typeSystem, sign, value, value0, pos);
case DAY_TO_HOUR:
- return evaluateIntervalLiteralAsDayToHour(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsDayToHour(typeSystem, sign, value, value0,
+ pos);
case DAY_TO_MINUTE:
- return evaluateIntervalLiteralAsDayToMinute(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsDayToMinute(typeSystem, sign, value,
+ value0, pos);
case DAY_TO_SECOND:
- return evaluateIntervalLiteralAsDayToSecond(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsDayToSecond(typeSystem, sign, value,
+ value0, pos);
case HOUR:
- return evaluateIntervalLiteralAsHour(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsHour(typeSystem, sign, value, value0,
+ pos);
case HOUR_TO_MINUTE:
- return evaluateIntervalLiteralAsHourToMinute(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsHourToMinute(typeSystem, sign, value,
+ value0, pos);
case HOUR_TO_SECOND:
- return evaluateIntervalLiteralAsHourToSecond(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsHourToSecond(typeSystem, sign, value,
+ value0, pos);
case MINUTE:
- return evaluateIntervalLiteralAsMinute(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsMinute(typeSystem, sign, value, value0,
+ pos);
case MINUTE_TO_SECOND:
- return evaluateIntervalLiteralAsMinuteToSecond(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsMinuteToSecond(typeSystem, sign, value,
+ value0, pos);
case SECOND:
- return evaluateIntervalLiteralAsSecond(sign, value, value0, pos);
+ return evaluateIntervalLiteralAsSecond(typeSystem, sign, value, value0,
+ pos);
default:
throw invalidValueException(pos, value0);
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/SqlUnresolvedFunction.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/SqlUnresolvedFunction.java b/core/src/main/java/org/eigenbase/sql/SqlUnresolvedFunction.java
index a8a5ac6..a607022 100644
--- a/core/src/main/java/org/eigenbase/sql/SqlUnresolvedFunction.java
+++ b/core/src/main/java/org/eigenbase/sql/SqlUnresolvedFunction.java
@@ -19,7 +19,6 @@ package org.eigenbase.sql;
import java.util.List;
import org.eigenbase.reltype.RelDataType;
-import org.eigenbase.sql.type.BasicSqlType;
import org.eigenbase.sql.type.SqlOperandTypeChecker;
import org.eigenbase.sql.type.SqlOperandTypeInference;
import org.eigenbase.sql.type.SqlReturnTypeInference;
@@ -64,9 +63,8 @@ public class SqlUnresolvedFunction extends SqlFunction {
* fail.
*/
@Override
- public RelDataType inferReturnType(
- SqlOperatorBinding opBinding) {
- return new BasicSqlType(SqlTypeName.ANY);
+ public RelDataType inferReturnType(SqlOperatorBinding opBinding) {
+ return opBinding.getTypeFactory().createSqlType(SqlTypeName.ANY);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/parser/SqlParserUtil.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/parser/SqlParserUtil.java b/core/src/main/java/org/eigenbase/sql/parser/SqlParserUtil.java
index 30fe3d4..1297f35 100644
--- a/core/src/main/java/org/eigenbase/sql/parser/SqlParserUtil.java
+++ b/core/src/main/java/org/eigenbase/sql/parser/SqlParserUtil.java
@@ -22,6 +22,7 @@ import java.text.*;
import java.util.*;
import java.util.logging.*;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.*;
import org.eigenbase.trace.*;
import org.eigenbase.util.*;
@@ -135,7 +136,7 @@ public final class SqlParserUtil {
int[] ret;
try {
ret = intervalQualifier.evaluateIntervalLiteral(literal,
- intervalQualifier.getParserPosition());
+ intervalQualifier.getParserPosition(), RelDataTypeSystem.DEFAULT);
assert ret != null;
} catch (EigenbaseContextException e) {
throw Util.newInternal(
@@ -177,7 +178,7 @@ public final class SqlParserUtil {
int[] ret;
try {
ret = intervalQualifier.evaluateIntervalLiteral(literal,
- intervalQualifier.getParserPosition());
+ intervalQualifier.getParserPosition(), RelDataTypeSystem.DEFAULT);
assert ret != null;
} catch (EigenbaseContextException e) {
throw Util.newInternal(
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/type/BasicSqlType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/type/BasicSqlType.java b/core/src/main/java/org/eigenbase/sql/type/BasicSqlType.java
index ab79e8f..796f45b 100644
--- a/core/src/main/java/org/eigenbase/sql/type/BasicSqlType.java
+++ b/core/src/main/java/org/eigenbase/sql/type/BasicSqlType.java
@@ -18,6 +18,7 @@ package org.eigenbase.sql.type;
import java.nio.charset.*;
+import org.eigenbase.reltype.RelDataTypeSystem;
import org.eigenbase.sql.*;
import org.eigenbase.util.*;
@@ -30,8 +31,9 @@ public class BasicSqlType extends AbstractSqlType {
//~ Instance fields --------------------------------------------------------
- private int precision;
- private int scale;
+ private final int precision;
+ private final int scale;
+ private final RelDataTypeSystem typeSystem;
private SqlCollation collation;
private SerializableCharset wrappedCharset;
@@ -43,12 +45,11 @@ public class BasicSqlType extends AbstractSqlType {
*
* @param typeName Type name
*/
- public BasicSqlType(SqlTypeName typeName) {
- super(typeName, false, null);
+ public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName) {
+ this(typeSystem, typeName, false, PRECISION_NOT_SPECIFIED,
+ SCALE_NOT_SPECIFIED);
assert typeName.allowsPrecScale(false, false)
: "typeName.allowsPrecScale(false,false), typeName=" + typeName.name();
- this.precision = PRECISION_NOT_SPECIFIED;
- this.scale = SCALE_NOT_SPECIFIED;
computeDigest();
}
@@ -57,14 +58,11 @@ public class BasicSqlType extends AbstractSqlType {
*
* @param typeName Type name
*/
- public BasicSqlType(
- SqlTypeName typeName,
+ public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName,
int precision) {
- super(typeName, false, null);
+ this(typeSystem, typeName, false, precision, SCALE_NOT_SPECIFIED);
assert typeName.allowsPrecScale(true, false)
: "typeName.allowsPrecScale(true, false)";
- this.precision = precision;
- this.scale = SCALE_NOT_SPECIFIED;
computeDigest();
}
@@ -73,15 +71,24 @@ public class BasicSqlType extends AbstractSqlType {
*
* @param typeName Type name
*/
- public BasicSqlType(
+ public BasicSqlType(RelDataTypeSystem typeSystem, SqlTypeName typeName,
+ int precision, int scale) {
+ this(typeSystem, typeName, false, precision, scale);
+ assert typeName.allowsPrecScale(true, true);
+ computeDigest();
+ }
+
+ /** Internal constructor. */
+ private BasicSqlType(
+ RelDataTypeSystem typeSystem,
SqlTypeName typeName,
+ boolean nullable,
int precision,
int scale) {
- super(typeName, false, null);
- assert typeName.allowsPrecScale(true, true);
+ super(typeName, nullable, null);
+ this.typeSystem = typeSystem;
this.precision = precision;
this.scale = scale;
- computeDigest();
}
//~ Methods ----------------------------------------------------------------
@@ -137,7 +144,7 @@ public class BasicSqlType extends AbstractSqlType {
case BIGINT:
return 19;
case DECIMAL:
- return SqlTypeName.MAX_NUMERIC_PRECISION;
+ return RelDataTypeSystem.DEFAULT.getMaxNumericPrecision(); // FIXME
case REAL:
return 7;
case FLOAT:
@@ -205,7 +212,7 @@ public class BasicSqlType extends AbstractSqlType {
// since (for instance) TIME is equivalent to TIME(0).
if (withDetail) {
// -1 means there is no default value for precision
- if (typeName.getDefaultPrecision() > -1) {
+ if (typeSystem.getDefaultPrecision(typeName) > -1) {
printPrecision = true;
}
if (typeName.getDefaultScale() > -1) {
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/type/IntervalSqlType.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/type/IntervalSqlType.java b/core/src/main/java/org/eigenbase/sql/type/IntervalSqlType.java
index c3141f7..c82671c 100644
--- a/core/src/main/java/org/eigenbase/sql/type/IntervalSqlType.java
+++ b/core/src/main/java/org/eigenbase/sql/type/IntervalSqlType.java
@@ -19,6 +19,8 @@ package org.eigenbase.sql.type;
import org.eigenbase.reltype.*;
import org.eigenbase.sql.*;
import org.eigenbase.sql.parser.*;
+import org.eigenbase.sql.pretty.SqlPrettyWriter;
+import org.eigenbase.sql.util.SqlString;
/**
* IntervalSqlType represents a standard SQL datetime interval type.
@@ -26,6 +28,7 @@ import org.eigenbase.sql.parser.*;
public class IntervalSqlType extends AbstractSqlType {
//~ Instance fields --------------------------------------------------------
+ private final RelDataTypeSystem typeSystem;
private SqlIntervalQualifier intervalQualifier;
//~ Constructors -----------------------------------------------------------
@@ -34,14 +37,15 @@ public class IntervalSqlType extends AbstractSqlType {
* Constructs an IntervalSqlType. This should only be called from a factory
* method.
*/
- public IntervalSqlType(
+ public IntervalSqlType(RelDataTypeSystem typeSystem,
SqlIntervalQualifier intervalQualifier,
boolean isNullable) {
- super(
- intervalQualifier.isYearMonth() ? SqlTypeName.INTERVAL_YEAR_MONTH
+ super(intervalQualifier.isYearMonth()
+ ? SqlTypeName.INTERVAL_YEAR_MONTH
: SqlTypeName.INTERVAL_DAY_TIME,
isNullable,
null);
+ this.typeSystem = typeSystem;
this.intervalQualifier = intervalQualifier;
computeDigest();
}
@@ -51,7 +55,15 @@ public class IntervalSqlType extends AbstractSqlType {
// implement RelDataTypeImpl
protected void generateTypeString(StringBuilder sb, boolean withDetail) {
sb.append("INTERVAL ");
- sb.append(intervalQualifier.toString());
+ SqlDialect dialect = null;
+ dialect = SqlDialect.DUMMY;
+ SqlPrettyWriter writer = new SqlPrettyWriter(dialect);
+ writer.setAlwaysUseParentheses(false);
+ writer.setSelectListItemsOnSeparateLines(false);
+ writer.setIndentation(0);
+ intervalQualifier.unparse(writer, 0, 0);
+ final String sql = writer.toString();
+ sb.append(new SqlString(dialect, sql).getSql());
}
// implement RelDataType
@@ -88,10 +100,10 @@ public class IntervalSqlType extends AbstractSqlType {
int secondPrec =
this.intervalQualifier.getStartPrecisionPreservingDefault();
int fracPrec =
- SqlIntervalQualifier
- .combineFractionalSecondPrecisionPreservingDefault(
- this.intervalQualifier,
- that.intervalQualifier);
+ SqlIntervalQualifier.combineFractionalSecondPrecisionPreservingDefault(
+ typeSystem,
+ this.intervalQualifier,
+ that.intervalQualifier);
if (thisStart.ordinal() > thatStart.ordinal()) {
thisEnd = thisStart;
@@ -101,17 +113,15 @@ public class IntervalSqlType extends AbstractSqlType {
} else if (thisStart.ordinal() == thatStart.ordinal()) {
secondPrec =
SqlIntervalQualifier.combineStartPrecisionPreservingDefault(
+ typeFactory.getTypeSystem(),
this.intervalQualifier,
that.intervalQualifier);
- } else if (
- (null == thisEnd)
- || (thisEnd.ordinal() < thatStart.ordinal())) {
+ } else if (null == thisEnd || thisEnd.ordinal() < thatStart.ordinal()) {
thisEnd = thatStart;
}
if (null != thatEnd) {
- if ((null == thisEnd)
- || (thisEnd.ordinal() < thatEnd.ordinal())) {
+ if (null == thisEnd || thisEnd.ordinal() < thatEnd.ordinal()) {
thisEnd = thatEnd;
}
}
@@ -131,17 +141,14 @@ public class IntervalSqlType extends AbstractSqlType {
return (IntervalSqlType) intervalType;
}
- // implement RelDataType
- public int getPrecision() {
- return intervalQualifier.getStartPrecision();
+ @Override public int getPrecision() {
+ return intervalQualifier.getStartPrecision(typeSystem);
}
@Override
public int getScale() {
- // TODO Auto-generated method stub
- return intervalQualifier.getFractionalSecondPrecision();
+ return intervalQualifier.getFractionalSecondPrecision(typeSystem);
}
-
}
// End IntervalSqlType.java
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/type/ReturnTypes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/type/ReturnTypes.java b/core/src/main/java/org/eigenbase/sql/type/ReturnTypes.java
index 573c36c..55c2893 100644
--- a/core/src/main/java/org/eigenbase/sql/type/ReturnTypes.java
+++ b/core/src/main/java/org/eigenbase/sql/type/ReturnTypes.java
@@ -468,23 +468,21 @@ public abstract class ReturnTypes {
int s1 = type1.getScale();
int s2 = type2.getScale();
+ final RelDataTypeFactory typeFactory = opBinding.getTypeFactory();
int scale = Math.max(s1, s2);
- assert scale <= SqlTypeName.MAX_NUMERIC_SCALE;
+ final RelDataTypeSystem typeSystem = typeFactory.getTypeSystem();
+ assert scale <= typeSystem.getMaxNumericScale();
int precision = Math.max(p1 - s1, p2 - s2) + scale + 1;
precision =
Math.min(
precision,
- SqlTypeName.MAX_NUMERIC_PRECISION);
+ typeSystem.getMaxNumericPrecision());
assert precision > 0;
- RelDataType ret;
- ret =
- opBinding.getTypeFactory().createSqlType(
- SqlTypeName.DECIMAL,
- precision,
- scale);
-
- return ret;
+ return typeFactory.createSqlType(
+ SqlTypeName.DECIMAL,
+ precision,
+ scale);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-optiq/blob/0fd4e3d9/core/src/main/java/org/eigenbase/sql/type/SqlTypeFactoryImpl.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/eigenbase/sql/type/SqlTypeFactoryImpl.java b/core/src/main/java/org/eigenbase/sql/type/SqlTypeFactoryImpl.java
index 71ccbf9..04110b8 100644
--- a/core/src/main/java/org/eigenbase/sql/type/SqlTypeFactoryImpl.java
+++ b/core/src/main/java/org/eigenbase/sql/type/SqlTypeFactoryImpl.java
@@ -24,13 +24,14 @@ import org.eigenbase.sql.*;
import org.eigenbase.util.*;
/**
- * SqlTypeFactoryImpl provides a default implementation of {@link
- * RelDataTypeFactory} which supports SQL types.
+ * SqlTypeFactoryImpl provides a default implementation of
+ * {@link RelDataTypeFactory} which supports SQL types.
*/
public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
//~ Constructors -----------------------------------------------------------
- public SqlTypeFactoryImpl() {
+ public SqlTypeFactoryImpl(RelDataTypeSystem typeSystem) {
+ super(typeSystem);
}
//~ Methods ----------------------------------------------------------------
@@ -38,10 +39,10 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
// implement RelDataTypeFactory
public RelDataType createSqlType(SqlTypeName typeName) {
if (typeName.allowsPrec()) {
- return createSqlType(typeName, typeName.getDefaultPrecision());
+ return createSqlType(typeName, typeSystem.getDefaultPrecision(typeName));
}
assertBasic(typeName);
- RelDataType newType = new BasicSqlType(typeName);
+ RelDataType newType = new BasicSqlType(typeSystem, typeName);
return canonize(newType);
}
@@ -55,7 +56,7 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
assertBasic(typeName);
assert (precision >= 0)
|| (precision == RelDataType.PRECISION_NOT_SPECIFIED);
- RelDataType newType = new BasicSqlType(typeName, precision);
+ RelDataType newType = new BasicSqlType(typeSystem, typeName, precision);
newType = SqlTypeUtil.addCharsetAndCollation(newType, this);
return canonize(newType);
}
@@ -68,7 +69,8 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
assertBasic(typeName);
assert (precision >= 0)
|| (precision == RelDataType.PRECISION_NOT_SPECIFIED);
- RelDataType newType = new BasicSqlType(typeName, precision, scale);
+ RelDataType newType =
+ new BasicSqlType(typeSystem, typeName, precision, scale);
newType = SqlTypeUtil.addCharsetAndCollation(newType, this);
return canonize(newType);
}
@@ -100,7 +102,8 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
// implement RelDataTypeFactory
public RelDataType createSqlIntervalType(
SqlIntervalQualifier intervalQualifier) {
- RelDataType newType = new IntervalSqlType(intervalQualifier, false);
+ RelDataType newType =
+ new IntervalSqlType(typeSystem, intervalQualifier, false);
return canonize(newType);
}
@@ -339,23 +342,24 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
int p2 = type.getPrecision();
int s1 = resultType.getScale();
int s2 = type.getScale();
+ final int maxPrecision = typeSystem.getMaxNumericPrecision();
+ final int maxScale = typeSystem.getMaxNumericScale();
int dout = Math.max(p1 - s1, p2 - s2);
dout =
Math.min(
dout,
- SqlTypeName.MAX_NUMERIC_PRECISION);
+ maxPrecision);
int scale = Math.max(s1, s2);
scale =
Math.min(
scale,
- SqlTypeName.MAX_NUMERIC_PRECISION - dout);
- scale =
- Math.min(scale, SqlTypeName.MAX_NUMERIC_SCALE);
+ maxPrecision - dout);
+ scale = Math.min(scale, maxScale);
int precision = dout + scale;
- assert precision <= SqlTypeName.MAX_NUMERIC_PRECISION;
+ assert precision <= maxPrecision;
assert precision > 0;
resultType =
@@ -461,7 +465,7 @@ public class SqlTypeFactoryImpl extends RelDataTypeFactoryImpl {
}
private RelDataType copyIntervalType(RelDataType type, boolean nullable) {
- return new IntervalSqlType(
+ return new IntervalSqlType(typeSystem,
type.getIntervalQualifier(),
nullable);
}