From e382cabf69cd6171266413a7b25d544522c979b8 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Thu, 14 Sep 2017 07:27:57 +0200 Subject: [PATCH 1/2] [CALCITE-1913] Replace usages of DatabaseProduct with dialect methods and introduce a configurable SqlDialectFactory --- .../adapter/cassandra/CassandraSchema.java | 4 +- .../calcite/adapter/jdbc/JdbcRules.java | 23 +- .../calcite/adapter/jdbc/JdbcSchema.java | 47 +++- .../jdbc/JdbcToEnumerableConverter.java | 25 +- .../calcite/adapter/jdbc/JdbcUtils.java | 24 +- .../apache/calcite/model/JsonJdbcSchema.java | 7 + .../apache/calcite/model/ModelHandler.java | 21 +- .../calcite/prepare/CalcitePrepareImpl.java | 1 - .../org/apache/calcite/prepare/Prepare.java | 3 - .../rel/rel2sql/RelToSqlConverter.java | 17 +- .../calcite/rel/rel2sql/SqlImplementor.java | 145 +----------- .../sql/SqlAbstractDateTimeLiteral.java | 2 +- .../apache/calcite/sql/SqlDateLiteral.java | 9 +- .../org/apache/calcite/sql/SqlDialect.java | 216 ++++++++++++------ .../apache/calcite/sql/SqlDialectFactory.java | 42 ++++ .../calcite/sql/SqlDialectFactoryImpl.java | 127 ++++++++++ .../java/org/apache/calcite/sql/SqlNode.java | 3 +- .../org/apache/calcite/sql/SqlNodeList.java | 23 ++ .../org/apache/calcite/sql/SqlSampleSpec.java | 4 +- .../apache/calcite/sql/SqlTimeLiteral.java | 7 + .../calcite/sql/SqlTimestampLiteral.java | 9 +- .../calcite/sql/dialect/AccessSqlDialect.java | 40 ++++ .../calcite/sql/dialect/AnsiSqlDialect.java | 51 +++++ .../sql/dialect/CalciteSqlDialect.java | 37 +++ .../calcite/sql/dialect/Db2SqlDialect.java | 54 +++++ .../calcite/sql/dialect/DerbySqlDialect.java | 40 ++++ .../sql/dialect/FirebirdSqlDialect.java | 39 ++++ .../calcite/sql/dialect/H2SqlDialect.java | 50 ++++ .../calcite/sql/dialect/HiveSqlDialect.java | 47 ++++ .../calcite/sql/dialect/HsqldbHandler.java | 1 + .../calcite/sql/dialect/HsqldbSqlDialect.java | 136 +++++++++++ .../sql/dialect/InfobrightSqlDialect.java | 39 ++++ .../sql/dialect/InformixSqlDialect.java | 39 ++++ .../sql/dialect/IngressSqlDialect.java | 39 ++++ .../sql/dialect/InterbaseSqlDialect.java | 39 ++++ .../calcite/sql/dialect/LucidbSqlDialect.java | 39 ++++ .../calcite/sql/dialect/MssqlHandler.java | 1 + .../calcite/sql/dialect/MssqlSqlDialect.java | 147 ++++++++++++ .../calcite/sql/dialect/MysqlHandler.java | 1 + .../calcite/sql/dialect/MysqlSqlDialect.java | 212 +++++++++++++++++ .../sql/dialect/NeoviewSqlDialect.java | 39 ++++ .../sql/dialect/NetezzaSqlDialect.java | 39 ++++ .../calcite/sql/dialect/OracleHandler.java | 1 + .../calcite/sql/dialect/OracleSqlDialect.java | 85 +++++++ .../sql/dialect/ParaccelSqlDialect.java | 39 ++++ .../sql/dialect/PhoenixSqlDialect.java | 50 ++++ .../sql/dialect/PostgresqlHandler.java | 1 + .../sql/dialect/PostgresqlSqlDialect.java | 80 +++++++ .../sql/dialect/RedshiftSqlDialect.java | 50 ++++ .../calcite/sql/dialect/SybaseSqlDialect.java | 39 ++++ .../sql/dialect/TeradataSqlDialect.java | 39 ++++ .../sql/dialect/VerticaSqlDialect.java | 39 ++++ .../calcite/sql/pretty/SqlPrettyWriter.java | 3 +- .../calcite/sql/type/IntervalSqlType.java | 3 +- .../rel/rel2sql/RelToSqlConverterTest.java | 3 +- .../calcite/sql/parser/SqlParserTest.java | 20 +- .../calcite/sql/test/SqlOperatorBaseTest.java | 9 +- .../calcite/sql/test/SqlPrettyWriterTest.java | 26 +-- .../calcite/sql/test/SqlTesterImpl.java | 4 +- .../apache/calcite/test/SqlLimitsTest.java | 4 +- .../apache/calcite/tools/FrameworksTest.java | 4 +- .../java/org/apache/calcite/util/Smalls.java | 8 +- .../org/apache/calcite/util/UtilTest.java | 6 +- 63 files changed, 2064 insertions(+), 337 deletions(-) create mode 100644 core/src/main/java/org/apache/calcite/sql/SqlDialectFactory.java create mode 100644 core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java create mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java diff --git a/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraSchema.java b/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraSchema.java index 00a7a4036ff9..709c7b4adff6 100644 --- a/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraSchema.java +++ b/cassandra/src/main/java/org/apache/calcite/adapter/cassandra/CassandraSchema.java @@ -29,9 +29,9 @@ import org.apache.calcite.schema.Table; import org.apache.calcite.schema.impl.AbstractSchema; import org.apache.calcite.schema.impl.MaterializedViewTable; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.pretty.SqlPrettyWriter; @@ -266,7 +266,7 @@ private void addMaterializedViews() { StringWriter stringWriter = new StringWriter(query.length()); PrintWriter printWriter = new PrintWriter(stringWriter); - SqlWriter writer = new SqlPrettyWriter(SqlDialect.CALCITE, true, printWriter); + SqlWriter writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT, true, printWriter); parsedQuery.unparse(writer, 0, 0); query = stringWriter.toString(); diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java index 736c78d1f8d4..c4e4c8281184 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcRules.java @@ -69,7 +69,6 @@ import org.apache.calcite.schema.ModifiableTable; import org.apache.calcite.sql.SqlAggFunction; import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlKind; import org.apache.calcite.util.ImmutableBitSet; import org.apache.calcite.util.Util; import org.apache.calcite.util.trace.CalciteTrace; @@ -109,21 +108,6 @@ public static List rules(JdbcConvention out) { new JdbcValuesRule(out)); } - static final ImmutableList AGG_FUNCS; - static final ImmutableList MYSQL_AGG_FUNCS; - - static { - ImmutableList.Builder builder = ImmutableList.builder(); - builder.add(SqlKind.COUNT); - builder.add(SqlKind.SUM); - builder.add(SqlKind.SUM0); - builder.add(SqlKind.MIN); - builder.add(SqlKind.MAX); - AGG_FUNCS = builder.build(); - builder.add(SqlKind.SINGLE_VALUE); - MYSQL_AGG_FUNCS = builder.build(); - } - /** Abstract base class for rule that converts to JDBC. */ abstract static class JdbcConverterRule extends ConverterRule { protected final JdbcConvention out; @@ -477,12 +461,7 @@ public RelNode convert(RelNode rel) { /** Returns whether this JDBC data source can implement a given aggregate * function. */ private static boolean canImplement(SqlAggFunction aggregation, SqlDialect sqlDialect) { - switch (sqlDialect.getDatabaseProduct()) { - case MYSQL: - return MYSQL_AGG_FUNCS.contains(aggregation.getKind()); - default: - return AGG_FUNCS.contains(aggregation.getKind()); - } + return sqlDialect.supportsAggregateFunction(aggregation.getKind()); } /** Aggregate operator implemented in JDBC convention. */ diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java index 31e262e37973..bc783183e277 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java @@ -32,6 +32,8 @@ import org.apache.calcite.schema.Schemas; import org.apache.calcite.schema.Table; import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlDialectFactory; +import org.apache.calcite.sql.SqlDialectFactoryImpl; import org.apache.calcite.sql.type.SqlTypeFactoryImpl; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.util.Util; @@ -102,9 +104,19 @@ public static JdbcSchema create( DataSource dataSource, String catalog, String schema) { + return create(parentSchema, name, dataSource, new SqlDialectFactoryImpl(), catalog, schema); + } + + public static JdbcSchema create( + SchemaPlus parentSchema, + String name, + DataSource dataSource, + SqlDialectFactory dialectFactory, + String catalog, + String schema) { final Expression expression = Schemas.subSchemaExpression(parentSchema, name, JdbcSchema.class); - final SqlDialect dialect = createDialect(dataSource); + final SqlDialect dialect = createDialect(dialectFactory, dataSource); final JdbcConvention convention = JdbcConvention.of(dialect, expression, name); return new JdbcSchema(dataSource, dialect, convention, catalog, schema); @@ -140,13 +152,38 @@ public static JdbcSchema create( } String jdbcCatalog = (String) operand.get("jdbcCatalog"); String jdbcSchema = (String) operand.get("jdbcSchema"); - return JdbcSchema.create( - parentSchema, name, dataSource, jdbcCatalog, jdbcSchema); + String sqlDialectFactory = (String) operand.get("sqlDialectFactory"); + + if (sqlDialectFactory == null || sqlDialectFactory.isEmpty()) { + return JdbcSchema.create( + parentSchema, name, dataSource, jdbcCatalog, jdbcSchema); + } else { + SqlDialectFactory factory; + try { + factory = (SqlDialectFactory) Class.forName(sqlDialectFactory).newInstance(); + } catch (Exception ex) { + throw new RuntimeException("Could not instantiate SqlDialectFactory: " + + sqlDialectFactory, ex); + } + return JdbcSchema.create( + parentSchema, name, dataSource, factory, jdbcCatalog, jdbcSchema); + } } - /** Returns a suitable SQL dialect for the given data source. */ + /** + * Returns a suitable SQL dialect for the given data source.. + * + * @param dataSource The data source + * @deprecated Use {@link #createDialect(SqlDialectFactory, DataSource)} instead + */ + @Deprecated public static SqlDialect createDialect(DataSource dataSource) { - return JdbcUtils.DialectPool.INSTANCE.get(dataSource); + return createDialect(new SqlDialectFactoryImpl(), dataSource); + } + + /** Returns a suitable SQL dialect for the given data source. */ + public static SqlDialect createDialect(SqlDialectFactory dialectFactory, DataSource dataSource) { + return JdbcUtils.DialectPool.INSTANCE.get(dialectFactory, dataSource); } /** Creates a JDBC data source with the given specification. */ diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java index c74e7412926b..ec81f06ff0b3 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcToEnumerableConverter.java @@ -100,7 +100,7 @@ public Result implement(EnumerableRelImplementor implementor, Prefer pref) { final ParameterExpression resultSet_ = Expressions.parameter(Modifier.FINAL, ResultSet.class, builder.newName("resultSet")); - CalendarPolicy calendarPolicy = CalendarPolicy.of(jdbcConvention.dialect); + SqlDialect.CalendarPolicy calendarPolicy = jdbcConvention.dialect.getCalendarPolicy(); final Expression calendar_; switch (calendarPolicy) { case LOCAL: @@ -179,7 +179,7 @@ private UnaryExpression getTimeZoneExpression( private void generateGet(EnumerableRelImplementor implementor, PhysType physType, BlockBuilder builder, ParameterExpression resultSet_, int i, Expression target, Expression calendar_, - CalendarPolicy calendarPolicy) { + SqlDialect.CalendarPolicy calendarPolicy) { final Primitive primitive = Primitive.ofBoxOr(physType.fieldClass(i)); final RelDataType fieldType = physType.getRowType().getFieldList().get(i).getType(); @@ -299,27 +299,6 @@ private String generateSql(SqlDialect dialect) { jdbcImplementor.visitChild(0, getInput()); return result.asStatement().toSqlString(dialect).getSql(); } - - /** Whether this JDBC driver needs you to pass a Calendar object to methods - * such as {@link ResultSet#getTimestamp(int, java.util.Calendar)}. */ - private enum CalendarPolicy { - NONE, - NULL, - LOCAL, - DIRECT, - SHIFT; - - static CalendarPolicy of(SqlDialect dialect) { - switch (dialect.getDatabaseProduct()) { - case MYSQL: - return SHIFT; - case HSQLDB: - default: - // NULL works for hsqldb-2.3; nothing worked for hsqldb-1.8. - return NULL; - } - } - } } // End JdbcToEnumerableConverter.java diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java index bb8e558b4cbe..15d479f981be 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java @@ -21,6 +21,7 @@ import org.apache.calcite.linq4j.function.Function0; import org.apache.calcite.linq4j.function.Function1; import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlDialectFactory; import org.apache.calcite.util.ImmutableNullableList; import org.apache.calcite.util.Pair; @@ -58,15 +59,18 @@ private JdbcUtils() { /** Pool of dialects. */ static class DialectPool { - final Map map0 = new IdentityHashMap<>(); + final Map> map0 = new IdentityHashMap<>(); final Map map = new HashMap<>(); public static final DialectPool INSTANCE = new DialectPool(); - SqlDialect get(DataSource dataSource) { - final SqlDialect sqlDialect = map0.get(dataSource); - if (sqlDialect != null) { - return sqlDialect; + synchronized SqlDialect get(SqlDialectFactory dialectFactory, DataSource dataSource) { + Map dialectMap = map0.get(dataSource); + if (dialectMap != null) { + final SqlDialect sqlDialect = dialectMap.get(dialectFactory); + if (sqlDialect != null) { + return sqlDialect; + } } Connection connection = null; try { @@ -74,12 +78,16 @@ SqlDialect get(DataSource dataSource) { DatabaseMetaData metaData = connection.getMetaData(); String productName = metaData.getDatabaseProductName(); String productVersion = metaData.getDatabaseProductVersion(); - List key = ImmutableList.of(productName, productVersion); + List key = ImmutableList.of(productName, productVersion, dialectFactory); SqlDialect dialect = map.get(key); if (dialect == null) { - dialect = SqlDialect.create(metaData); + dialect = dialectFactory.create(metaData); map.put(key, dialect); - map0.put(dataSource, dialect); + if (dialectMap == null) { + dialectMap = new IdentityHashMap<>(); + map0.put(dataSource, dialectMap); + } + dialectMap.put(dialectFactory, dialect); } connection.close(); connection = null; diff --git a/core/src/main/java/org/apache/calcite/model/JsonJdbcSchema.java b/core/src/main/java/org/apache/calcite/model/JsonJdbcSchema.java index 761dab5e770c..4c8aaf584b97 100644 --- a/core/src/main/java/org/apache/calcite/model/JsonJdbcSchema.java +++ b/core/src/main/java/org/apache/calcite/model/JsonJdbcSchema.java @@ -32,6 +32,13 @@ public class JsonJdbcSchema extends JsonSchema { */ public String jdbcDriver; + /** The FQN of the {@link org.apache.calcite.sql.SqlDialectFactory} implementation. + * + *

Optional. If not specified, uses whichever class the JDBC + * {@link java.sql.DriverManager} chooses. + */ + public String sqlDialectFactory; + /** JDBC connect string, for example "jdbc:mysql://localhost/foodmart". * *

Optional. diff --git a/core/src/main/java/org/apache/calcite/model/ModelHandler.java b/core/src/main/java/org/apache/calcite/model/ModelHandler.java index 6af4395ea676..4397f6933b52 100644 --- a/core/src/main/java/org/apache/calcite/model/ModelHandler.java +++ b/core/src/main/java/org/apache/calcite/model/ModelHandler.java @@ -37,6 +37,7 @@ import org.apache.calcite.schema.impl.TableFunctionImpl; import org.apache.calcite.schema.impl.TableMacroImpl; import org.apache.calcite.schema.impl.ViewTable; +import org.apache.calcite.sql.SqlDialectFactory; import org.apache.calcite.util.Pair; import org.apache.calcite.util.Util; @@ -320,9 +321,23 @@ public void visit(JsonJdbcSchema jsonSchema) { jsonSchema.jdbcDriver, jsonSchema.jdbcUser, jsonSchema.jdbcPassword); - JdbcSchema schema = - JdbcSchema.create(parentSchema, jsonSchema.name, dataSource, - jsonSchema.jdbcCatalog, jsonSchema.jdbcSchema); + final JdbcSchema schema; + if (jsonSchema.sqlDialectFactory == null || jsonSchema.sqlDialectFactory.isEmpty()) { + schema = + JdbcSchema.create(parentSchema, jsonSchema.name, dataSource, + jsonSchema.jdbcCatalog, jsonSchema.jdbcSchema); + } else { + SqlDialectFactory factory; + try { + factory = (SqlDialectFactory) Class.forName(jsonSchema.sqlDialectFactory).newInstance(); + } catch (Exception ex) { + throw new RuntimeException("Could not instantiate SqlDialectFactory: " + + jsonSchema.sqlDialectFactory, ex); + } + schema = + JdbcSchema.create(parentSchema, jsonSchema.name, dataSource, + factory, jsonSchema.jdbcCatalog, jsonSchema.jdbcSchema); + } final SchemaPlus schemaPlus = parentSchema.add(jsonSchema.name, schema); populateSchema(jsonSchema, schemaPlus); } diff --git a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java index ec57a8d1c624..74b62d51cbd7 100644 --- a/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java +++ b/core/src/main/java/org/apache/calcite/prepare/CalcitePrepareImpl.java @@ -1120,7 +1120,6 @@ public RelNode get() { private PreparedResult prepare_(Supplier fn, RelDataType resultType) { - queryString = null; Class runtimeContextClass = Object.class; init(runtimeContextClass); diff --git a/core/src/main/java/org/apache/calcite/prepare/Prepare.java b/core/src/main/java/org/apache/calcite/prepare/Prepare.java index 8cb09c3fe09e..42d8cdf9e809 100644 --- a/core/src/main/java/org/apache/calcite/prepare/Prepare.java +++ b/core/src/main/java/org/apache/calcite/prepare/Prepare.java @@ -87,7 +87,6 @@ public abstract class Prepare { protected final CalcitePrepare.Context context; protected final CatalogReader catalogReader; - protected String queryString = null; /** * Convention via which results should be returned by execution. */ @@ -241,8 +240,6 @@ public PreparedResult prepareSql( Class runtimeContextClass, SqlValidator validator, boolean needsValidation) { - queryString = sqlQuery.toString(); - init(runtimeContextClass); final SqlToRelConverter.ConfigBuilder builder = diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java index b4e1a08d4953..be3dc00328b5 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java @@ -198,8 +198,8 @@ public Result visit(Aggregate e) { for (AggregateCall aggCall : e.getAggCallList()) { SqlNode aggCallSqlNode = builder.context.toSql(aggCall); if (aggCall.getAggregation() instanceof SqlSingleValueAggFunction) { - aggCallSqlNode = - rewriteSingleValueExpr(aggCallSqlNode, dialect); + aggCallSqlNode = dialect. + rewriteSingleValueExpr(aggCallSqlNode); } addSelect(selectList, aggCallSqlNode, e.getRowType()); } @@ -397,12 +397,13 @@ public Result visit(Match e) { final List orderBySqlList = new ArrayList<>(); if (e.getOrderKeys() != null) { for (RelFieldCollation fc : e.getOrderKeys().getFieldCollations()) { - if (fc.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED - && dialect.getDatabaseProduct() == SqlDialect.DatabaseProduct.MYSQL) { - orderBySqlList.add( - ISNULL_FUNCTION.createCall(POS, context.field(fc.getFieldIndex()))); - fc = new RelFieldCollation(fc.getFieldIndex(), fc.getDirection(), - RelFieldCollation.NullDirection.UNSPECIFIED); + if (fc.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) { + SqlNode nullDirectionNode = dialect.emulateNullDirection(context, fc); + if (nullDirectionNode != null) { + orderBySqlList.add(nullDirectionNode); + fc = new RelFieldCollation(fc.getFieldIndex(), fc.getDirection(), + RelFieldCollation.NullDirection.UNSPECIFIED); + } } orderBySqlList.add(context.toSql(fc)); } diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java index 57155b7524d8..bb5e3845012d 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java @@ -41,14 +41,10 @@ import org.apache.calcite.rex.RexWindow; import org.apache.calcite.rex.RexWindowBound; import org.apache.calcite.sql.JoinType; -import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlBinaryOperator; import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlDynamicParam; -import org.apache.calcite.sql.SqlFunction; -import org.apache.calcite.sql.SqlFunctionCategory; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlJoin; import org.apache.calcite.sql.SqlKind; @@ -65,13 +61,8 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.fun.SqlSumEmptyIsZeroAggFunction; import org.apache.calcite.sql.parser.SqlParserPos; -import org.apache.calcite.sql.type.BasicSqlType; -import org.apache.calcite.sql.type.InferTypes; -import org.apache.calcite.sql.type.OperandTypes; -import org.apache.calcite.sql.type.ReturnTypes; import org.apache.calcite.sql.type.SqlTypeFamily; import org.apache.calcite.sql.type.SqlTypeName; -import org.apache.calcite.sql.type.SqlTypeUtil; import org.apache.calcite.sql.validate.SqlValidatorUtil; import org.apache.calcite.util.DateString; import org.apache.calcite.util.TimeString; @@ -84,9 +75,6 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.math.BigDecimal; import java.util.AbstractList; import java.util.ArrayList; @@ -104,17 +92,9 @@ * State for generating a SQL statement. */ public abstract class SqlImplementor { - private static final Logger LOGGER = - LoggerFactory.getLogger(SqlImplementor.class); public static final SqlParserPos POS = SqlParserPos.ZERO; - /** MySQL specific function. */ - public static final SqlFunction ISNULL_FUNCTION = - new SqlFunction("ISNULL", SqlKind.OTHER_FUNCTION, - ReturnTypes.BOOLEAN, InferTypes.FIRST_KNOWN, - OperandTypes.ANY, SqlFunctionCategory.SYSTEM); - public final SqlDialect dialect; protected final Set aliasSet = new LinkedHashSet<>(); protected final Map ordinalMap = new HashMap<>(); @@ -127,82 +107,6 @@ protected SqlImplementor(SqlDialect dialect) { public abstract Result visitChild(int i, RelNode e); - /** Rewrite SINGLE_VALUE into expression based on database variants - * E.g. HSQLDB, MYSQL, ORACLE, etc - */ - public static SqlNode rewriteSingleValueExpr(SqlNode aggCall, - SqlDialect sqlDialect) { - final SqlNode operand = ((SqlBasicCall) aggCall).operand(0); - final SqlNode caseOperand; - final SqlNode elseExpr; - final SqlNode countCall = - SqlStdOperatorTable.COUNT.createCall(POS, operand); - - final SqlLiteral nullLiteral = SqlLiteral.createNull(POS); - final SqlNode wrappedOperand; - switch (sqlDialect.getDatabaseProduct()) { - case MYSQL: - case HSQLDB: - // For MySQL, generate - // CASE COUNT(*) - // WHEN 0 THEN NULL - // WHEN 1 THEN - // ELSE (SELECT NULL UNION ALL SELECT NULL) - // END - // - // For hsqldb, generate - // CASE COUNT(*) - // WHEN 0 THEN NULL - // WHEN 1 THEN MIN() - // ELSE (VALUES 1 UNION ALL VALUES 1) - // END - caseOperand = countCall; - - final SqlNodeList selectList = new SqlNodeList(POS); - selectList.add(nullLiteral); - final SqlNode unionOperand; - switch (sqlDialect.getDatabaseProduct()) { - case MYSQL: - wrappedOperand = operand; - unionOperand = new SqlSelect(POS, SqlNodeList.EMPTY, selectList, - null, null, null, null, SqlNodeList.EMPTY, null, null, null); - break; - default: - wrappedOperand = SqlStdOperatorTable.MIN.createCall(POS, operand); - unionOperand = SqlStdOperatorTable.VALUES.createCall(POS, - SqlLiteral.createApproxNumeric("0", POS)); - } - - SqlCall unionAll = SqlStdOperatorTable.UNION_ALL - .createCall(POS, unionOperand, unionOperand); - - final SqlNodeList selectList2 = new SqlNodeList(POS); - selectList2.add(nullLiteral); - elseExpr = SqlStdOperatorTable.SCALAR_QUERY.createCall(POS, unionAll); - break; - - default: - LOGGER.debug("SINGLE_VALUE rewrite not supported for {}", - sqlDialect.getDatabaseProduct()); - return aggCall; - } - - final SqlNodeList whenList = new SqlNodeList(POS); - whenList.add(SqlLiteral.createExactNumeric("0", POS)); - whenList.add(SqlLiteral.createExactNumeric("1", POS)); - - final SqlNodeList thenList = new SqlNodeList(POS); - thenList.add(nullLiteral); - thenList.add(wrappedOperand); - - SqlNode caseExpr = - new SqlCase(POS, caseOperand, whenList, thenList, elseExpr); - - LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr); - - return caseExpr; - } - public void addSelect(List selectList, SqlNode node, RelDataType rowType) { String name = rowType.getFieldNames().get(selectList.size()); @@ -677,7 +581,7 @@ public SqlNode toSql(RexProgram program, RexNode rex) { assert nodeList.size() == 1; return nodeList.get(0); } else { - nodeList.add(toSql(call.getType())); + nodeList.add(dialect.getCastSpec(call.getType())); } } if (op instanceof SqlBinaryOperator && nodeList.size() > 2) { @@ -785,35 +689,6 @@ private SqlNode createLeftCall(SqlOperator op, List nodeList) { return op.createCall(new SqlNodeList(ImmutableList.of(call, last), POS)); } - private SqlNode toSql(RelDataType type) { - switch (dialect.getDatabaseProduct()) { - case MYSQL: - switch (type.getSqlTypeName()) { - case VARCHAR: - // MySQL doesn't have a VARCHAR type, only CHAR. - return new SqlDataTypeSpec(new SqlIdentifier("CHAR", POS), - type.getPrecision(), -1, null, null, POS); - case INTEGER: - return new SqlDataTypeSpec(new SqlIdentifier("_UNSIGNED", POS), - type.getPrecision(), -1, null, null, POS); - } - break; - } - if (type instanceof BasicSqlType) { - return new SqlDataTypeSpec( - new SqlIdentifier(type.getSqlTypeName().name(), POS), - type.getPrecision(), - type.getScale(), - type.getCharset() != null - && dialect.supportsCharSet() - ? type.getCharset().name() - : null, - null, - POS); - } - return SqlTypeUtil.convertTypeToSpec(type); - } - private List toSql(RexProgram program, List operandList) { final List list = new ArrayList<>(); for (RexNode rex : operandList) { @@ -1163,7 +1038,7 @@ public Result resetAlias() { public class Builder { private final RelNode rel; final List clauses; - private final SqlSelect select; + final SqlSelect select; public final Context context; private final Map aliases; @@ -1212,14 +1087,14 @@ public void setOffset(SqlNode offset) { public void addOrderItem(List orderByList, RelFieldCollation field) { - if (field.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED - && dialect.getDatabaseProduct() == SqlDialect.DatabaseProduct.MYSQL) { - orderByList.add( - ISNULL_FUNCTION.createCall(POS, - context.field(field.getFieldIndex()))); - field = new RelFieldCollation(field.getFieldIndex(), - field.getDirection(), - RelFieldCollation.NullDirection.UNSPECIFIED); + if (field.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) { + SqlNode nullDirectionNode = dialect.emulateNullDirection(context, field); + if (nullDirectionNode != null) { + orderByList.add(nullDirectionNode); + field = new RelFieldCollation(field.getFieldIndex(), + field.getDirection(), + RelFieldCollation.NullDirection.UNSPECIFIED); + } } orderByList.add(context.toSql(field)); } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlAbstractDateTimeLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlAbstractDateTimeLiteral.java index 59dfc692c07d..05d77d153a9a 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlAbstractDateTimeLiteral.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlAbstractDateTimeLiteral.java @@ -33,7 +33,7 @@ *

  • TIMESTAMP '1969-07-21 03:15 GMT'
  • * */ -abstract class SqlAbstractDateTimeLiteral extends SqlLiteral { +public abstract class SqlAbstractDateTimeLiteral extends SqlLiteral { //~ Instance fields -------------------------------------------------------- protected final boolean hasTimeZone; diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDateLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlDateLiteral.java index 1a757f62c8fc..b26f86af18c5 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDateLiteral.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDateLiteral.java @@ -65,14 +65,7 @@ public void unparse( SqlWriter writer, int leftPrec, int rightPrec) { - switch (writer.getDialect().getDatabaseProduct()) { - case MSSQL: - writer.literal("'" + this.toFormattedString() + "'"); - break; - default: - writer.literal(this.toString()); - break; - } + writer.getDialect().unparseDateTimeLiteral(writer, this, leftPrec, rightPrec); } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java index 6bc25ca93a5d..3ea36c279413 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java @@ -20,15 +20,26 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.linq4j.function.Experimental; import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.rel2sql.SqlImplementor; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.dialect.HsqldbHandler; import org.apache.calcite.sql.dialect.MssqlHandler; import org.apache.calcite.sql.dialect.MysqlHandler; import org.apache.calcite.sql.dialect.OracleHandler; import org.apache.calcite.sql.dialect.PostgresqlHandler; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.BasicSqlType; +import org.apache.calcite.sql.type.SqlTypeUtil; import com.google.common.base.Preconditions; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.sql.DatabaseMetaData; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.text.SimpleDateFormat; @@ -46,14 +57,17 @@ public class SqlDialect { //~ Static fields/initializers --------------------------------------------- private static final Handler DEFAULT_HANDLER = new BaseHandler(); + protected static final Logger LOGGER = + LoggerFactory.getLogger(SqlDialect.class); /** * A dialect useful for generating generic SQL. If you need to do something * database-specific like quoting identifiers, don't rely on this dialect to * do what you want. */ + @Deprecated // to be removed before 2.0 public static final SqlDialect DUMMY = - DatabaseProduct.UNKNOWN.getDialect(); + AnsiSqlDialect.DEFAULT; /** * A dialect useful for generating SQL which can be parsed by the @@ -61,16 +75,19 @@ public class SqlDialect { * want a dialect that knows the full capabilities of the database, create * one from a connection. */ + @Deprecated // to be removed before 2.0 public static final SqlDialect CALCITE = - DatabaseProduct.CALCITE.getDialect(); + CalciteSqlDialect.DEFAULT; //~ Instance fields -------------------------------------------------------- private final String identifierQuoteString; private final String identifierEndQuoteString; private final String identifierEscapedQuote; + @Deprecated // to be removed before 2.0 private final DatabaseProduct databaseProduct; private final NullCollation nullCollation; + @Deprecated // to be removed before 2.0 private final Handler handler; //~ Constructors ----------------------------------------------------------- @@ -84,47 +101,37 @@ public class SqlDialect { * * @param databaseMetaData used to determine which dialect of SQL to * generate + * @deprecated Replaced by {@link SqlDialectFactory} */ + @Deprecated // to be removed before 2.0 public static SqlDialect create(DatabaseMetaData databaseMetaData) { - String identifierQuoteString; - try { - identifierQuoteString = databaseMetaData.getIdentifierQuoteString(); - } catch (SQLException e) { - throw FakeUtil.newInternal(e, "while quoting identifier"); - } - String databaseProductName; - try { - databaseProductName = databaseMetaData.getDatabaseProductName(); - } catch (SQLException e) { - throw FakeUtil.newInternal(e, "while detecting database product"); - } - String databaseProductVersion; - try { - databaseProductVersion = databaseMetaData.getDatabaseProductVersion(); - } catch (SQLException e) { - throw FakeUtil.newInternal(e, "while detecting database version"); - } - final DatabaseProduct databaseProduct = - getProduct(databaseProductName, databaseProductVersion); - NullCollation nullCollation; + return new SqlDialectFactoryImpl().create(databaseMetaData); + } + + protected static NullCollation getNullCollation(DatabaseMetaData databaseMetaData) { try { if (databaseMetaData.nullsAreSortedAtEnd()) { - nullCollation = NullCollation.LAST; + return NullCollation.LAST; } else if (databaseMetaData.nullsAreSortedAtStart()) { - nullCollation = NullCollation.FIRST; + return NullCollation.FIRST; } else if (databaseMetaData.nullsAreSortedLow()) { - nullCollation = NullCollation.LOW; + return NullCollation.LOW; } else if (databaseMetaData.nullsAreSortedHigh()) { - nullCollation = NullCollation.HIGH; + return NullCollation.HIGH; } else { throw new IllegalArgumentException("cannot deduce null collation"); } } catch (SQLException e) { throw new IllegalArgumentException("cannot deduce null collation", e); } - Handler handler = chooseHandler(databaseProduct); - return new SqlDialect(databaseProduct, databaseProductName, - identifierQuoteString, nullCollation, handler); + } + + protected static String getIdentifierQuoteString(DatabaseMetaData databaseMetaData) { + try { + return databaseMetaData.getIdentifierQuoteString(); + } catch (SQLException e) { + throw new IllegalArgumentException("cannot deduce identifier quote string", e); + } } @Deprecated // to be removed before 2.0 @@ -141,6 +148,40 @@ public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, nullCollation, DEFAULT_HANDLER); } + @Deprecated // to be removed before 2.0, replace with constructor without DatabaseProduct + protected SqlDialect(DatabaseProduct databaseProduct, DatabaseMetaData databaseMetaData) { + this( + databaseProduct, + getIdentifierQuoteString(databaseMetaData), + getNullCollation(databaseMetaData) + ); + } + + @Deprecated // to be removed before 2.0, replace with constructor without DatabaseProduct + protected SqlDialect(DatabaseProduct databaseProduct, String identifierQuoteString, + NullCollation nullCollation) { + this.nullCollation = Preconditions.checkNotNull(nullCollation); + this.databaseProduct = Preconditions.checkNotNull(databaseProduct); + this.handler = null; + if (identifierQuoteString != null) { + identifierQuoteString = identifierQuoteString.trim(); + if (identifierQuoteString.equals("")) { + identifierQuoteString = null; + } + } + this.identifierQuoteString = identifierQuoteString; + this.identifierEndQuoteString = + identifierQuoteString == null + ? null + : identifierQuoteString.equals("[") + ? "]" + : identifierQuoteString; + this.identifierEscapedQuote = + identifierQuoteString == null + ? null + : this.identifierEndQuoteString + this.identifierEndQuoteString; + } + /** * Creates a SqlDialect. * @@ -152,6 +193,7 @@ public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, * @param nullCollation Whether NULL values appear first or last * @param handler Handler for un-parsing */ + @Deprecated // to be removed before 2.0 @Experimental public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString, NullCollation nullCollation, @@ -189,6 +231,7 @@ public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, * @param productVersion Product version * @return database product */ + @Deprecated // to be removed before 2.0 public static DatabaseProduct getProduct( String productName, String productVersion) { @@ -363,9 +406,13 @@ public String quoteStringLiteral(String val) { } } - public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, - int rightPrec) { - handler.unparseCall(writer, call, leftPrec, rightPrec); + public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + call.getOperator().unparse(writer, call, leftPrec, rightPrec); + } + + public void unparseDateTimeLiteral(SqlWriter writer, SqlAbstractDateTimeLiteral literal, + int leftPrec, int rightPrec) { + writer.literal(literal.toString()); } /** @@ -434,18 +481,12 @@ public String unquoteStringLiteral(String val) { } protected boolean allowsAs() { - switch (databaseProduct) { - case ORACLE: - case HIVE: - return false; - default: - return true; - } + return true; } // -- behaviors -- protected boolean requiresAliasForFromItems() { - return getDatabaseProduct() == DatabaseProduct.POSTGRESQL; + return false; } /** Returns whether a qualified table in the FROM clause has an implicit alias @@ -471,12 +512,7 @@ protected boolean requiresAliasForFromItems() { *

    Returns true for all databases except DB2. */ public boolean hasImplicitTableAlias() { - switch (databaseProduct) { - case DB2: - return false; - default: - return true; - } + return true; } /** @@ -512,7 +548,9 @@ public String quoteTimestampLiteral(Timestamp timestamp) { * {@link SqlDialect.DatabaseProduct#UNKNOWN} if not known, never null. * * @return Database product + * @deprecated Going to be removed without replacement */ + @Deprecated // to be removed before 2.0 public DatabaseProduct getDatabaseProduct() { return databaseProduct; } @@ -522,18 +560,59 @@ public DatabaseProduct getDatabaseProduct() { * data type, for instance {@code VARCHAR(30) CHARACTER SET `ISO-8859-1`}. */ public boolean supportsCharSet() { - switch (databaseProduct) { - case DB2: - case H2: - case HSQLDB: - case MYSQL: - case ORACLE: - case PHOENIX: - case POSTGRESQL: - return false; - default: + return true; + } + + public boolean supportsAggregateFunction(SqlKind kind) { + switch (kind) { + case COUNT: + case SUM: + case SUM0: + case MIN: + case MAX: return true; } + return false; + } + + public CalendarPolicy getCalendarPolicy() { + return CalendarPolicy.NULL; + } + + public SqlNode getCastSpec(RelDataType type) { + if (type instanceof BasicSqlType) { + return new SqlDataTypeSpec( + new SqlIdentifier(type.getSqlTypeName().name(), SqlParserPos.ZERO), + type.getPrecision(), + type.getScale(), + type.getCharset() != null + && supportsCharSet() + ? type.getCharset().name() + : null, + null, + SqlParserPos.ZERO); + } + return SqlTypeUtil.convertTypeToSpec(type); + } + + /** Rewrite SINGLE_VALUE into expression based on database variants + * E.g. HSQLDB, MYSQL, ORACLE, etc + */ + public SqlNode rewriteSingleValueExpr(SqlNode aggCall) { + LOGGER.debug("SINGLE_VALUE rewrite not supported for {}", databaseProduct); + return aggCall; + } + + /** + * Returns the SqlNode for emulating the null direction for the given field + * or null if no emulation needs to be done. + * + * @param context The translation context + * @param field The field for which to emulate null direction + * @return A SqlNode for null direction emulation or null if not required + */ + public SqlNode emulateNullDirection(SqlImplementor.Context context, RelFieldCollation field) { + return null; } /** @@ -544,14 +623,7 @@ public boolean supportsCharSet() { * {@code LIMIT 20 OFFSET 10}. */ public boolean supportsOffsetFetch() { - switch (databaseProduct) { - case MYSQL: - case HIVE: - case REDSHIFT: - return false; - default: - return true; - } + return true; } /** Returns how NULL values are sorted if an ORDER BY item does not contain @@ -626,6 +698,17 @@ public static String replace( } } + + /** Whether this JDBC driver needs you to pass a Calendar object to methods + * such as {@link ResultSet#getTimestamp(int, java.util.Calendar)}. */ + public enum CalendarPolicy { + NONE, + NULL, + LOCAL, + DIRECT, + SHIFT; + } + /** * Rough list of flavors of database. * @@ -638,6 +721,7 @@ public static String replace( * extend the dialect to describe the particular capability, for example, * whether the database allows expressions to appear in the GROUP BY clause. */ + @Deprecated // to be removed before 2.0 public enum DatabaseProduct { ACCESS("Access", "\"", NullCollation.HIGH), CALCITE("Apache Calcite", "\"", NullCollation.HIGH), @@ -719,6 +803,7 @@ public SqlDialect getDialect() { * *

    Instances are stateless and therefore immutable. */ + @Deprecated // to be removed before 2.0 @Experimental public interface Handler { void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, @@ -726,6 +811,7 @@ void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, } /** Base class for dialect handlers. */ + @Deprecated // to be removed before 2.0 @Experimental public static class BaseHandler implements Handler { public void unparseCall(SqlWriter writer, SqlCall call, diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactory.java b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactory.java new file mode 100644 index 000000000000..73de073b6e8c --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactory.java @@ -0,0 +1,42 @@ +/* + * 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.sql; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; + +/** + * SqlDialectFactory constructs a SqlDialect appropriate + * for a given database metadata object. + */ +public interface SqlDialectFactory { + + /** + * Creates a SqlDialect from a DatabaseMetaData. + * + *

    Does not maintain a reference to the DatabaseMetaData -- or, more + * importantly, to its {@link Connection} -- after this call has + * returned. + * + * @param databaseMetaData used to determine which dialect of SQL to + * generate + */ + SqlDialect create(DatabaseMetaData databaseMetaData); + +} + +// End SqlDialectFactory.java diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java new file mode 100644 index 000000000000..bd9e01a47af4 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java @@ -0,0 +1,127 @@ +/* + * 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.sql; + +import org.apache.calcite.sql.dialect.AccessSqlDialect; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; +import org.apache.calcite.sql.dialect.Db2SqlDialect; +import org.apache.calcite.sql.dialect.DerbySqlDialect; +import org.apache.calcite.sql.dialect.FirebirdSqlDialect; +import org.apache.calcite.sql.dialect.H2SqlDialect; +import org.apache.calcite.sql.dialect.HiveSqlDialect; +import org.apache.calcite.sql.dialect.HsqldbSqlDialect; +import org.apache.calcite.sql.dialect.InfobrightSqlDialect; +import org.apache.calcite.sql.dialect.InformixSqlDialect; +import org.apache.calcite.sql.dialect.IngressSqlDialect; +import org.apache.calcite.sql.dialect.InterbaseSqlDialect; +import org.apache.calcite.sql.dialect.LucidbSqlDialect; +import org.apache.calcite.sql.dialect.MssqlSqlDialect; +import org.apache.calcite.sql.dialect.MysqlSqlDialect; +import org.apache.calcite.sql.dialect.NeoviewSqlDialect; +import org.apache.calcite.sql.dialect.NetezzaSqlDialect; +import org.apache.calcite.sql.dialect.OracleSqlDialect; +import org.apache.calcite.sql.dialect.ParaccelSqlDialect; +import org.apache.calcite.sql.dialect.PhoenixSqlDialect; +import org.apache.calcite.sql.dialect.PostgresqlSqlDialect; +import org.apache.calcite.sql.dialect.RedshiftSqlDialect; +import org.apache.calcite.sql.dialect.SybaseSqlDialect; +import org.apache.calcite.sql.dialect.TeradataSqlDialect; +import org.apache.calcite.sql.dialect.VerticaSqlDialect; + +import java.sql.DatabaseMetaData; +import java.sql.SQLException; +import java.util.Locale; + +/** + * The default implementation of a SqlDialectFactory. + */ +public class SqlDialectFactoryImpl implements SqlDialectFactory { + + /** + * {@inheritDoc} + */ + public SqlDialect create(DatabaseMetaData databaseMetaData) { + String databaseProductName; + try { + databaseProductName = databaseMetaData.getDatabaseProductName(); + } catch (SQLException e) { + throw new RuntimeException("while detecting database product", e); + } + final String upperProductName = + databaseProductName.toUpperCase(Locale.ROOT).trim(); + switch (upperProductName) { + case "ACCESS": + return new AccessSqlDialect(databaseMetaData); + case "APACHE DERBY": + return new DerbySqlDialect(databaseMetaData); + case "DBMS:CLOUDSCAPE": + return new DerbySqlDialect(databaseMetaData); + case "HIVE": + return new HiveSqlDialect(databaseMetaData); + case "INGRES": + return new IngressSqlDialect(databaseMetaData); + case "INTERBASE": + return new InterbaseSqlDialect(databaseMetaData); + case "LUCIDDB": + return new LucidbSqlDialect(databaseMetaData); + case "ORACLE": + return new OracleSqlDialect(databaseMetaData); + case "PHOENIX": + return new PhoenixSqlDialect(databaseMetaData); + case "MYSQL (INFOBRIGHT)": + return new InfobrightSqlDialect(databaseMetaData); + case "MYSQL": + return new MysqlSqlDialect(databaseMetaData); + case "REDSHIFT": + return new RedshiftSqlDialect(databaseMetaData); + } + // Now the fuzzy matches. + if (databaseProductName.startsWith("DB2")) { + return new Db2SqlDialect(databaseMetaData); + } else if (upperProductName.contains("FIREBIRD")) { + return new FirebirdSqlDialect(databaseMetaData); + } else if (databaseProductName.startsWith("Informix")) { + return new InformixSqlDialect(databaseMetaData); + } else if (upperProductName.contains("NETEZZA")) { + return new NetezzaSqlDialect(databaseMetaData); + } else if (upperProductName.contains("PARACCEL")) { + return new ParaccelSqlDialect(databaseMetaData); + } else if (databaseProductName.startsWith("HP Neoview")) { + return new NeoviewSqlDialect(databaseMetaData); + } else if (upperProductName.contains("POSTGRE")) { + return new PostgresqlSqlDialect(databaseMetaData); + } else if (upperProductName.contains("SQL SERVER")) { + return new MssqlSqlDialect(databaseMetaData); + } else if (upperProductName.contains("SYBASE")) { + return new SybaseSqlDialect(databaseMetaData); + } else if (upperProductName.contains("TERADATA")) { + return new TeradataSqlDialect(databaseMetaData); + } else if (upperProductName.contains("HSQL")) { + return new HsqldbSqlDialect(databaseMetaData); + } else if (upperProductName.contains("H2")) { + return new H2SqlDialect(databaseMetaData); + } else if (upperProductName.contains("VERTICA")) { + return new VerticaSqlDialect(databaseMetaData); + } else { + return new AnsiSqlDialect(databaseMetaData); + } + + } + +} + +// End SqlDialectFactoryImpl.java diff --git a/core/src/main/java/org/apache/calcite/sql/SqlNode.java b/core/src/main/java/org/apache/calcite/sql/SqlNode.java index e7c77fbf98fc..7c37dce6a304 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlNode.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlNode.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.sql; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.pretty.SqlPrettyWriter; import org.apache.calcite.sql.util.SqlString; @@ -132,7 +133,7 @@ public String toString() { */ public SqlString toSqlString(SqlDialect dialect, boolean forceParens) { if (dialect == null) { - dialect = SqlDialect.DUMMY; + dialect = AnsiSqlDialect.DEFAULT; } SqlPrettyWriter writer = new SqlPrettyWriter(dialect); writer.setAlwaysUseParentheses(forceParens); diff --git a/core/src/main/java/org/apache/calcite/sql/SqlNodeList.java b/core/src/main/java/org/apache/calcite/sql/SqlNodeList.java index 09258641cb67..b5380132b3e3 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlNodeList.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlNodeList.java @@ -184,6 +184,29 @@ public static boolean isEmptyList(final SqlNode node) { return false; } + public static SqlNodeList of(SqlNode node1) { + SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO); + list.add(node1); + return list; + } + + public static SqlNodeList of(SqlNode node1, SqlNode node2) { + SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO); + list.add(node1); + list.add(node2); + return list; + } + + public static SqlNodeList of(SqlNode node1, SqlNode node2, SqlNode... nodes) { + SqlNodeList list = new SqlNodeList(SqlParserPos.ZERO); + list.add(node1); + list.add(node2); + for (SqlNode node : nodes) { + list.add(node); + } + return list; + } + public void validateExpr(SqlValidator validator, SqlValidatorScope scope) { // While a SqlNodeList is not always a valid expression, this // implementation makes that assumption. It just validates the members diff --git a/core/src/main/java/org/apache/calcite/sql/SqlSampleSpec.java b/core/src/main/java/org/apache/calcite/sql/SqlSampleSpec.java index 498b9ede5a94..73e9d082e941 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlSampleSpec.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlSampleSpec.java @@ -16,6 +16,8 @@ */ package org.apache.calcite.sql; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; + /** * Specification of a SQL sample. * @@ -94,7 +96,7 @@ public String getName() { public String toString() { return "SUBSTITUTE(" - + SqlDialect.CALCITE.quoteStringLiteral(name) + + CalciteSqlDialect.DEFAULT.quoteStringLiteral(name) + ")"; } } diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java index 4327e2aad7f8..57644448d3cd 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlTimeLiteral.java @@ -58,6 +58,13 @@ public String toString() { public String toFormattedString() { return getTime().toString(precision); } + + public void unparse( + SqlWriter writer, + int leftPrec, + int rightPrec) { + writer.getDialect().unparseDateTimeLiteral(writer, this, leftPrec, rightPrec); + } } // End SqlTimeLiteral.java diff --git a/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java b/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java index cc659d5749b8..c81187ba34aa 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlTimestampLiteral.java @@ -63,14 +63,7 @@ public void unparse( SqlWriter writer, int leftPrec, int rightPrec) { - switch (writer.getDialect().getDatabaseProduct()) { - case MSSQL: - writer.literal("'" + this.toFormattedString() + "'"); - break; - default: - writer.literal(this.toString()); - break; - } + writer.getDialect().unparseDateTimeLiteral(writer, this, leftPrec, rightPrec); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java new file mode 100644 index 000000000000..02914a885821 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java @@ -0,0 +1,40 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Access database. + */ +public class AccessSqlDialect extends SqlDialect { + + public static final SqlDialect DEFAULT = new AccessSqlDialect(); + + public AccessSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.ACCESS, databaseMetaData); + } + + private AccessSqlDialect() { + super(DatabaseProduct.ACCESS, "\"", NullCollation.HIGH); + } +} + +// End AccessSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java new file mode 100644 index 000000000000..65985b05351a --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java @@ -0,0 +1,51 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for an unknown ANSI compatible database. + */ +public class AnsiSqlDialect extends SqlDialect { + /** + * A dialect useful for generating generic SQL. If you need to do something + * database-specific like quoting identifiers, don't rely on this dialect to + * do what you want. + */ + public static final SqlDialect DEFAULT = new AnsiSqlDialect(); + + public AnsiSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.UNKNOWN, + databaseMetaData + ); + } + + private AnsiSqlDialect() { + super( + DatabaseProduct.UNKNOWN, + "`", + NullCollation.HIGH + ); + } +} + +// End AnsiSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java new file mode 100644 index 000000000000..927ba189f7bc --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java @@ -0,0 +1,37 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +/** + * A SqlDialect implementation that produces SQL that is parseable by Calcite. + */ +public class CalciteSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new CalciteSqlDialect(); + + private CalciteSqlDialect() { + super( + DatabaseProduct.CALCITE, + "\"", + NullCollation.HIGH + ); + } +} + +// End CalciteSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java new file mode 100644 index 000000000000..6312a350ae88 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java @@ -0,0 +1,54 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Db2 database. + */ +public class Db2SqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new Db2SqlDialect(); + + public Db2SqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.DB2, + databaseMetaData + ); + } + + private Db2SqlDialect() { + super( + DatabaseProduct.DB2, + null, + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } + + @Override public boolean hasImplicitTableAlias() { + return false; + } +} + +// End Db2SqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java new file mode 100644 index 000000000000..9afaec77b12d --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java @@ -0,0 +1,40 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Derby database. + */ +public class DerbySqlDialect extends SqlDialect { + + public static final SqlDialect DEFAULT = new DerbySqlDialect(); + + public DerbySqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.DERBY, databaseMetaData); + } + + private DerbySqlDialect() { + super(DatabaseProduct.DERBY, null, NullCollation.HIGH); + } +} + +// End DerbySqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java new file mode 100644 index 000000000000..10d12b3cfc55 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Firebird database. + */ +public class FirebirdSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new FirebirdSqlDialect(); + + public FirebirdSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.FIREBIRD, databaseMetaData); + } + + private FirebirdSqlDialect() { + super(DatabaseProduct.FIREBIRD, null, NullCollation.HIGH); + } +} + +// End FirebirdSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java new file mode 100644 index 000000000000..9c9b647d4d51 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java @@ -0,0 +1,50 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the H2 database. + */ +public class H2SqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new H2SqlDialect(); + + public H2SqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.H2, + databaseMetaData + ); + } + + private H2SqlDialect() { + super( + DatabaseProduct.H2, + "\"", + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } +} + +// End H2SqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java new file mode 100644 index 000000000000..6291666a1d35 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java @@ -0,0 +1,47 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Hive database. + */ +public class HiveSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new HiveSqlDialect(); + + public HiveSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.HIVE, databaseMetaData); + } + + private HiveSqlDialect() { + super(DatabaseProduct.HIVE, null, NullCollation.HIGH); + } + + @Override protected boolean allowsAs() { + return false; + } + + @Override public boolean supportsOffsetFetch() { + return false; + } +} + +// End HiveSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java index 62e54bfd299d..5d12a58604ad 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java @@ -30,6 +30,7 @@ *

    It reverts to the unparse method of the operator * if this database's implementation is standard. */ +@Deprecated // to be removed before 2.0 public class HsqldbHandler extends SqlDialect.BaseHandler { public static final HsqldbHandler INSTANCE = new HsqldbHandler(); diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java new file mode 100644 index 000000000000..98d968298221 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java @@ -0,0 +1,136 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.avatica.util.TimeUnitRange; +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.fun.SqlCase; +import org.apache.calcite.sql.fun.SqlFloorFunction; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Hsqldb database. + */ +public class HsqldbSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new HsqldbSqlDialect(); + + public HsqldbSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.HSQLDB, + databaseMetaData + ); + } + + private HsqldbSqlDialect() { + super( + DatabaseProduct.HSQLDB, + null, + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } + + @Override public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + switch (call.getKind()) { + case FLOOR: + if (call.operandCount() != 2) { + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + + final SqlLiteral timeUnitNode = call.operand(1); + final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); + + final String translatedLit = convertTimeUnit(timeUnit); + SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, translatedLit, + timeUnitNode.getParserPosition()); + SqlFloorFunction.unparseDatetimeFunction(writer, call2, "TRUNC", true); + break; + + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + } + } + + @Override public SqlNode rewriteSingleValueExpr(SqlNode aggCall) { + final SqlNode operand = ((SqlBasicCall) aggCall).operand(0); + final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO); + final SqlNode unionOperand = SqlStdOperatorTable.VALUES.createCall(SqlParserPos.ZERO, + SqlLiteral.createApproxNumeric("0", SqlParserPos.ZERO)); + // For hsqldb, generate + // CASE COUNT(*) + // WHEN 0 THEN NULL + // WHEN 1 THEN MIN() + // ELSE (VALUES 1 UNION ALL VALUES 1) + // END + final SqlNode caseExpr = + new SqlCase(SqlParserPos.ZERO, + SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand), + SqlNodeList.of( + SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO), + SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO) + ), + SqlNodeList.of( + nullLiteral, + SqlStdOperatorTable.MIN.createCall(SqlParserPos.ZERO, operand) + ), + SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO, + SqlStdOperatorTable.UNION_ALL + .createCall(SqlParserPos.ZERO, unionOperand, unionOperand))); + + LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr); + + return caseExpr; + } + + private static String convertTimeUnit(TimeUnitRange unit) { + switch (unit) { + case YEAR: + return "YYYY"; + case MONTH: + return "MM"; + case DAY: + return "DD"; + case WEEK: + return "WW"; + case HOUR: + return "HH24"; + case MINUTE: + return "MI"; + case SECOND: + return "SS"; + default: + throw new AssertionError("could not convert time unit to HSQLDB equivalent: " + + unit); + } + } +} + +// End HsqldbSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java new file mode 100644 index 000000000000..f2fa3b271fd6 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Infobright database. + */ +public class InfobrightSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new InfobrightSqlDialect(); + + public InfobrightSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.INFOBRIGHT, databaseMetaData); + } + + private InfobrightSqlDialect() { + super(DatabaseProduct.INFOBRIGHT, "`", NullCollation.HIGH); + } +} + +// End InfobrightSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java new file mode 100644 index 000000000000..5a40bf2ad6aa --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Informix database. + */ +public class InformixSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new InformixSqlDialect(); + + public InformixSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.INFORMIX, databaseMetaData); + } + + private InformixSqlDialect() { + super(DatabaseProduct.INFORMIX, null, NullCollation.HIGH); + } +} + +// End InformixSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java new file mode 100644 index 000000000000..3b14f39ae767 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Ingress database. + */ +public class IngressSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new IngressSqlDialect(); + + public IngressSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.INGRES, databaseMetaData); + } + + private IngressSqlDialect() { + super(DatabaseProduct.INGRES, null, NullCollation.HIGH); + } +} + +// End IngressSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java new file mode 100644 index 000000000000..46be34465f3a --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Interbase database. + */ +public class InterbaseSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new InterbaseSqlDialect(); + + public InterbaseSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.INTERBASE, databaseMetaData); + } + + private InterbaseSqlDialect() { + super(DatabaseProduct.INTERBASE, null, NullCollation.HIGH); + } +} + +// End InterbaseSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java new file mode 100644 index 000000000000..92ba67e6a419 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Lucidb database. + */ +public class LucidbSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new LucidbSqlDialect(); + + public LucidbSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.LUCIDDB, databaseMetaData); + } + + private LucidbSqlDialect() { + super(DatabaseProduct.LUCIDDB, "\"", NullCollation.HIGH); + } +} + +// End LucidbSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java index 31aa2876f228..0f313458f84c 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java @@ -35,6 +35,7 @@ *

    It reverts to the unparse method of the operator * if this database's implementation is standard. */ +@Deprecated // to be removed before 2.0 public class MssqlHandler extends SqlDialect.BaseHandler { public static final MssqlHandler INSTANCE = new MssqlHandler(); public static final SqlFunction MSSQL_SUBSTRING = diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java new file mode 100644 index 000000000000..d8bafbd2fea8 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java @@ -0,0 +1,147 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.avatica.util.TimeUnitRange; +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlAbstractDateTimeLiteral; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlFunction; +import org.apache.calcite.sql.SqlFunctionCategory; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.type.ReturnTypes; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Mssql database. + */ +public class MssqlSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new MssqlSqlDialect(); + + private static final SqlFunction MSSQL_SUBSTRING = + new SqlFunction("SUBSTRING", SqlKind.OTHER_FUNCTION, + ReturnTypes.ARG0_NULLABLE_VARYING, null, null, + SqlFunctionCategory.STRING); + + public MssqlSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.MSSQL, + databaseMetaData + ); + } + + private MssqlSqlDialect() { + super( + DatabaseProduct.MSSQL, + "[", + NullCollation.HIGH + ); + } + + @Override public void unparseDateTimeLiteral(SqlWriter writer, SqlAbstractDateTimeLiteral literal, + int leftPrec, int rightPrec) { + writer.literal("'" + literal.toFormattedString() + "'"); + } + + @Override public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + if (call.getOperator() == SqlStdOperatorTable.SUBSTRING) { + if (call.operandCount() != 3) { + throw new IllegalArgumentException("MSSQL SUBSTRING requires FROM and FOR arguments"); + } + SqlUtil.unparseFunctionSyntax(MSSQL_SUBSTRING, writer, call); + } else { + switch (call.getKind()) { + case FLOOR: + if (call.operandCount() != 2) { + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + unparseFloor(writer, call); + break; + + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + } + } + } + + /** + * Unparses datetime floor for Microsoft SQL Server. + * There is no TRUNC function, so simulate this using calls to CONVERT. + * + * @param writer Writer + * @param call Call + */ + private void unparseFloor(SqlWriter writer, SqlCall call) { + SqlLiteral node = call.operand(1); + TimeUnitRange unit = (TimeUnitRange) node.getValue(); + + switch (unit) { + case YEAR: + unparseFloorWithUnit(writer, call, 4, "-01-01"); + break; + case MONTH: + unparseFloorWithUnit(writer, call, 7, "-01"); + break; + case WEEK: + writer.print("CONVERT(DATETIME, CONVERT(VARCHAR(10), " + + "DATEADD(day, - (6 + DATEPART(weekday, "); + call.operand(0).unparse(writer, 0, 0); + writer.print(")) % 7, "); + call.operand(0).unparse(writer, 0, 0); + writer.print("), 126))"); + break; + case DAY: + unparseFloorWithUnit(writer, call, 10, ""); + break; + case HOUR: + unparseFloorWithUnit(writer, call, 13, ":00:00"); + break; + case MINUTE: + unparseFloorWithUnit(writer, call, 16, ":00"); + break; + case SECOND: + unparseFloorWithUnit(writer, call, 19, ":00"); + break; + default: + throw new IllegalArgumentException("MSSQL does not support FLOOR for time unit: " + + unit); + } + } + + private void unparseFloorWithUnit(SqlWriter writer, SqlCall call, int charLen, + String offset) { + writer.print("CONVERT"); + SqlWriter.Frame frame = writer.startList("(", ")"); + writer.print("DATETIME, CONVERT(VARCHAR(" + charLen + "), "); + call.operand(0).unparse(writer, 0, 0); + writer.print(", 126)"); + + if (offset.length() > 0) { + writer.print("+'" + offset + "'"); + } + writer.endList(frame); + } +} + +// End MssqlSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java index adf70619356b..55bb860b2a35 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java @@ -29,6 +29,7 @@ *

    It reverts to the unparse method of the operator * if this database's implementation is standard. */ +@Deprecated // to be removed before 2.0 public class MysqlHandler extends SqlDialect.BaseHandler { public static final MysqlHandler INSTANCE = new MysqlHandler(); diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java new file mode 100644 index 000000000000..8833b221c7d7 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java @@ -0,0 +1,212 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.avatica.util.TimeUnitRange; +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.rel.RelFieldCollation; +import org.apache.calcite.rel.rel2sql.SqlImplementor; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.SqlBasicCall; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDataTypeSpec; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlFunction; +import org.apache.calcite.sql.SqlFunctionCategory; +import org.apache.calcite.sql.SqlIdentifier; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlNodeList; +import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.fun.SqlCase; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; +import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.InferTypes; +import org.apache.calcite.sql.type.OperandTypes; +import org.apache.calcite.sql.type.ReturnTypes; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Mysql database. + */ +public class MysqlSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new MysqlSqlDialect(); + + /** MySQL specific function. */ + public static final SqlFunction ISNULL_FUNCTION = + new SqlFunction("ISNULL", SqlKind.OTHER_FUNCTION, + ReturnTypes.BOOLEAN, InferTypes.FIRST_KNOWN, + OperandTypes.ANY, SqlFunctionCategory.SYSTEM); + + public MysqlSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.MYSQL, databaseMetaData); + } + + private MysqlSqlDialect() { + super(DatabaseProduct.MYSQL, "`", NullCollation.HIGH); + } + + @Override public boolean supportsCharSet() { + return false; + } + + @Override public boolean supportsOffsetFetch() { + return false; + } + + @Override public SqlNode emulateNullDirection(SqlImplementor.Context context, + RelFieldCollation field) { + return ISNULL_FUNCTION.createCall(SqlParserPos.ZERO, context.field(field.getFieldIndex())); + } + + @Override public boolean supportsAggregateFunction(SqlKind kind) { + switch (kind) { + case COUNT: + case SUM: + case SUM0: + case MIN: + case MAX: + case SINGLE_VALUE: + return true; + } + return false; + } + + @Override public CalendarPolicy getCalendarPolicy() { + return CalendarPolicy.SHIFT; + } + + @Override public SqlNode getCastSpec(RelDataType type) { + switch (type.getSqlTypeName()) { + case VARCHAR: + // MySQL doesn't have a VARCHAR type, only CHAR. + return new SqlDataTypeSpec(new SqlIdentifier("CHAR", SqlParserPos.ZERO), + type.getPrecision(), -1, null, null, SqlParserPos.ZERO); + case INTEGER: + return new SqlDataTypeSpec(new SqlIdentifier("_UNSIGNED", SqlParserPos.ZERO), + type.getPrecision(), -1, null, null, SqlParserPos.ZERO); + } + return super.getCastSpec(type); + } + + @Override public SqlNode rewriteSingleValueExpr(SqlNode aggCall) { + final SqlNode operand = ((SqlBasicCall) aggCall).operand(0); + final SqlLiteral nullLiteral = SqlLiteral.createNull(SqlParserPos.ZERO); + final SqlNode unionOperand = new SqlSelect(SqlParserPos.ZERO, SqlNodeList.EMPTY, + SqlNodeList.of(nullLiteral), null, null, null, null, SqlNodeList.EMPTY, null, null, null); + // For MySQL, generate + // CASE COUNT(*) + // WHEN 0 THEN NULL + // WHEN 1 THEN + // ELSE (SELECT NULL UNION ALL SELECT NULL) + // END + final SqlNode caseExpr = + new SqlCase(SqlParserPos.ZERO, + SqlStdOperatorTable.COUNT.createCall(SqlParserPos.ZERO, operand), + SqlNodeList.of( + SqlLiteral.createExactNumeric("0", SqlParserPos.ZERO), + SqlLiteral.createExactNumeric("1", SqlParserPos.ZERO) + ), + SqlNodeList.of( + nullLiteral, + operand + ), + SqlStdOperatorTable.SCALAR_QUERY.createCall(SqlParserPos.ZERO, + SqlStdOperatorTable.UNION_ALL + .createCall(SqlParserPos.ZERO, unionOperand, unionOperand))); + + LOGGER.debug("SINGLE_VALUE rewritten into [{}]", caseExpr); + + return caseExpr; + } + + @Override public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + switch (call.getKind()) { + case FLOOR: + if (call.operandCount() != 2) { + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + + unparseFloor(writer, call); + break; + + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + } + } + + /** + * Unparses datetime floor for MySQL. There is no TRUNC function, so simulate + * this using calls to DATE_FORMAT. + * + * @param writer Writer + * @param call Call + */ + private void unparseFloor(SqlWriter writer, SqlCall call) { + SqlLiteral node = call.operand(1); + TimeUnitRange unit = (TimeUnitRange) node.getValue(); + + if (unit == TimeUnitRange.WEEK) { + writer.print("STR_TO_DATE"); + SqlWriter.Frame frame = writer.startList("(", ")"); + + writer.print("DATE_FORMAT("); + call.operand(0).unparse(writer, 0, 0); + writer.print(", '%x%v-1'), '%x%v-%w'"); + writer.endList(frame); + return; + } + + String format; + switch (unit) { + case YEAR: + format = "%Y-01-01"; + break; + case MONTH: + format = "%Y-%m-01"; + break; + case DAY: + format = "%Y-%m-%d"; + break; + case HOUR: + format = "%Y-%m-%d %k:00:00"; + break; + case MINUTE: + format = "%Y-%m-%d %k:%i:00"; + break; + case SECOND: + format = "%Y-%m-%d %k:%i:%s"; + break; + default: + throw new AssertionError("MYSQL does not support FLOOR for time unit: " + + unit); + } + + writer.print("DATE_FORMAT"); + SqlWriter.Frame frame = writer.startList("(", ")"); + call.operand(0).unparse(writer, 0, 0); + writer.sep(",", true); + writer.print("'" + format + "'"); + writer.endList(frame); + } +} + +// End MysqlSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java new file mode 100644 index 000000000000..43c5a979a5f4 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Neoview database. + */ +public class NeoviewSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new NeoviewSqlDialect(); + + public NeoviewSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.NEOVIEW, databaseMetaData); + } + + private NeoviewSqlDialect() { + super(DatabaseProduct.NEOVIEW, null, NullCollation.HIGH); + } +} + +// End NeoviewSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java new file mode 100644 index 000000000000..ec324f2490dc --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Netezza database. + */ +public class NetezzaSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new NetezzaSqlDialect(); + + public NetezzaSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.NETEZZA, databaseMetaData); + } + + private NetezzaSqlDialect() { + super(DatabaseProduct.NETEZZA, "\"", NullCollation.HIGH); + } +} + +// End NetezzaSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java index a67eb01d7b45..53d56ec08db8 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java @@ -33,6 +33,7 @@ *

    It reverts to the unparse method of the operator * if this database's implementation is standard. */ +@Deprecated // to be removed before 2.0 public class OracleHandler extends SqlDialect.BaseHandler { public static final OracleHandler INSTANCE = new OracleHandler(); diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java new file mode 100644 index 000000000000..4f3a4aef38fd --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java @@ -0,0 +1,85 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.avatica.util.TimeUnitRange; +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlUtil; +import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.fun.OracleSqlOperatorTable; +import org.apache.calcite.sql.fun.SqlFloorFunction; +import org.apache.calcite.sql.fun.SqlStdOperatorTable; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Oracle database. + */ +public class OracleSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new OracleSqlDialect(); + + public OracleSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.ORACLE, databaseMetaData + ); + } + + private OracleSqlDialect() { + super( + DatabaseProduct.ORACLE, + "\"", + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } + + @Override protected boolean allowsAs() { + return false; + } + + @Override public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + if (call.getOperator() == SqlStdOperatorTable.SUBSTRING) { + SqlUtil.unparseFunctionSyntax(OracleSqlOperatorTable.SUBSTR, writer, call); + } else { + switch (call.getKind()) { + case FLOOR: + if (call.operandCount() != 2) { + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + + final SqlLiteral timeUnitNode = call.operand(1); + final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); + + SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), + timeUnitNode.getParserPosition()); + SqlFloorFunction.unparseDatetimeFunction(writer, call2, "TRUNC", true); + break; + + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + } + } + } +} + +// End OracleSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java new file mode 100644 index 000000000000..28290221a5d3 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Paraccel database. + */ +public class ParaccelSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new ParaccelSqlDialect(); + + public ParaccelSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.PARACCEL, databaseMetaData); + } + + private ParaccelSqlDialect() { + super(DatabaseProduct.PARACCEL, "\"", NullCollation.HIGH); + } +} + +// End ParaccelSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java new file mode 100644 index 000000000000..c7d6fc823523 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java @@ -0,0 +1,50 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Phoenix database. + */ +public class PhoenixSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new PhoenixSqlDialect(); + + public PhoenixSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.PHOENIX, + databaseMetaData + ); + } + + private PhoenixSqlDialect() { + super( + DatabaseProduct.PHOENIX, + "\"", + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } +} + +// End PhoenixSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java index 8b35346c0365..aeb629da16ce 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java @@ -30,6 +30,7 @@ *

    It reverts to the unparse method of the operator * if this database's implementation is standard. */ +@Deprecated // to be removed before 2.0 public class PostgresqlHandler extends SqlDialect.BaseHandler { public static final PostgresqlHandler INSTANCE = new PostgresqlHandler(); diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java new file mode 100644 index 000000000000..c0cd220a9307 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java @@ -0,0 +1,80 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.avatica.util.TimeUnitRange; +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlCall; +import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.fun.SqlFloorFunction; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Postgresql database. + */ +public class PostgresqlSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new PostgresqlSqlDialect(); + + public PostgresqlSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.POSTGRESQL, + databaseMetaData + ); + } + + private PostgresqlSqlDialect() { + super( + DatabaseProduct.POSTGRESQL, + "\"", + NullCollation.HIGH + ); + } + + @Override public boolean supportsCharSet() { + return false; + } + + @Override protected boolean requiresAliasForFromItems() { + return true; + } + + @Override public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, int rightPrec) { + switch (call.getKind()) { + case FLOOR: + if (call.operandCount() != 2) { + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + + final SqlLiteral timeUnitNode = call.operand(1); + final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); + + SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), + timeUnitNode.getParserPosition()); + SqlFloorFunction.unparseDatetimeFunction(writer, call2, "DATE_TRUNC", false); + break; + + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + } + } +} + +// End PostgresqlSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java new file mode 100644 index 000000000000..9b8d578f99cf --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java @@ -0,0 +1,50 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Redshift database. + */ +public class RedshiftSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new RedshiftSqlDialect(); + + public RedshiftSqlDialect(DatabaseMetaData databaseMetaData) { + super( + DatabaseProduct.REDSHIFT, + databaseMetaData + ); + } + + private RedshiftSqlDialect() { + super( + DatabaseProduct.REDSHIFT, + "\"", + NullCollation.HIGH + ); + } + + @Override public boolean supportsOffsetFetch() { + return false; + } +} + +// End RedshiftSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java new file mode 100644 index 000000000000..23c3b768093a --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Sybase database. + */ +public class SybaseSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new SybaseSqlDialect(); + + public SybaseSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.SYBASE, databaseMetaData); + } + + private SybaseSqlDialect() { + super(DatabaseProduct.SYBASE, null, NullCollation.HIGH); + } +} + +// End SybaseSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java new file mode 100644 index 000000000000..4ce3d920c952 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Teradata database. + */ +public class TeradataSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new TeradataSqlDialect(); + + public TeradataSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.TERADATA, databaseMetaData); + } + + private TeradataSqlDialect() { + super(DatabaseProduct.TERADATA, "\"", NullCollation.HIGH); + } +} + +// End TeradataSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java new file mode 100644 index 000000000000..cc7af3d4da15 --- /dev/null +++ b/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java @@ -0,0 +1,39 @@ +/* + * 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.sql.dialect; + +import org.apache.calcite.config.NullCollation; +import org.apache.calcite.sql.SqlDialect; + +import java.sql.DatabaseMetaData; + +/** + * A SqlDialect implementation for the Vertica database. + */ +public class VerticaSqlDialect extends SqlDialect { + public static final SqlDialect DEFAULT = new VerticaSqlDialect(); + + public VerticaSqlDialect(DatabaseMetaData databaseMetaData) { + super(DatabaseProduct.VERTICA, databaseMetaData); + } + + private VerticaSqlDialect() { + super(DatabaseProduct.VERTICA, "\"", NullCollation.HIGH); + } +} + +// End VerticaSqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java index dde8d285075a..0afd951dcaf1 100644 --- a/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java +++ b/core/src/main/java/org/apache/calcite/sql/pretty/SqlPrettyWriter.java @@ -20,6 +20,7 @@ import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.util.SqlBuilder; import org.apache.calcite.sql.util.SqlString; import org.apache.calcite.util.Unsafe; @@ -131,7 +132,7 @@ public class SqlPrettyWriter implements SqlWriter { * Bean holding the default property values. */ private static final Bean DEFAULT_BEAN = - new SqlPrettyWriter(SqlDialect.DUMMY).getBean(); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT).getBean(); protected static final String NL = System.getProperty("line.separator"); //~ Instance fields -------------------------------------------------------- diff --git a/core/src/main/java/org/apache/calcite/sql/type/IntervalSqlType.java b/core/src/main/java/org/apache/calcite/sql/type/IntervalSqlType.java index d4b2284c23df..4789c0619cac 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/IntervalSqlType.java +++ b/core/src/main/java/org/apache/calcite/sql/type/IntervalSqlType.java @@ -22,6 +22,7 @@ import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlIntervalQualifier; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.pretty.SqlPrettyWriter; import org.apache.calcite.sql.util.SqlString; @@ -56,7 +57,7 @@ public IntervalSqlType(RelDataTypeSystem typeSystem, protected void generateTypeString(StringBuilder sb, boolean withDetail) { sb.append("INTERVAL "); - final SqlDialect dialect = SqlDialect.DUMMY; + final SqlDialect dialect = AnsiSqlDialect.DEFAULT; final SqlPrettyWriter writer = new SqlPrettyWriter(dialect); writer.setAlwaysUseParentheses(false); writer.setSelectListItemsOnSeparateLines(false); diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index b72edfc9de10..d891e811357e 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -30,6 +30,7 @@ import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlDialect.DatabaseProduct; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql2rel.SqlToRelConverter; import org.apache.calcite.test.CalciteAssert; @@ -74,7 +75,7 @@ public class RelToSqlConverterTest { /** Initiates a test case with a given SQL query. */ private Sql sql(String sql) { return new Sql(CalciteAssert.SchemaSpec.JDBC_FOODMART, sql, - SqlDialect.CALCITE, DEFAULT_REL_CONFIG, + CalciteSqlDialect.DEFAULT, DEFAULT_REL_CONFIG, ImmutableList.>of()); } diff --git a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java index e91a76c5df72..3a467a9a8a37 100644 --- a/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java +++ b/core/src/test/java/org/apache/calcite/sql/parser/SqlParserTest.java @@ -18,10 +18,10 @@ import org.apache.calcite.avatica.util.Casing; import org.apache.calcite.avatica.util.Quoting; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlSetOption; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.parser.impl.SqlParserImpl; import org.apache.calcite.sql.pretty.SqlPrettyWriter; import org.apache.calcite.sql.validate.SqlConformance; @@ -7252,11 +7252,11 @@ public void subTestIntervalSecondFailsValidation() { SqlNode node = getSqlParser("alter system set schema = true").parseStmt(); SqlSetOption opt = (SqlSetOption) node; assertThat(opt.getScope(), equalTo("SYSTEM")); - SqlPrettyWriter writer = new SqlPrettyWriter(SqlDialect.CALCITE); + SqlPrettyWriter writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); assertThat(writer.format(opt.getName()), equalTo("\"SCHEMA\"")); - writer = new SqlPrettyWriter(SqlDialect.CALCITE); + writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); assertThat(writer.format(opt.getValue()), equalTo("TRUE")); - writer = new SqlPrettyWriter(SqlDialect.CALCITE); + writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); assertThat(writer.format(opt), equalTo("ALTER SYSTEM SET \"SCHEMA\" = TRUE")); @@ -7284,10 +7284,10 @@ public void subTestIntervalSecondFailsValidation() { node = getSqlParser("reset schema").parseStmt(); opt = (SqlSetOption) node; assertThat(opt.getScope(), equalTo(null)); - writer = new SqlPrettyWriter(SqlDialect.CALCITE); + writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); assertThat(writer.format(opt.getName()), equalTo("\"SCHEMA\"")); assertThat(opt.getValue(), equalTo(null)); - writer = new SqlPrettyWriter(SqlDialect.CALCITE); + writer = new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); assertThat(writer.format(opt), equalTo("RESET \"SCHEMA\"")); @@ -8178,7 +8178,7 @@ public class UnparsingTesterImpl extends TesterImpl { // Unparse again in Calcite dialect (which we can parse), and // minimal parentheses. final String sql1 = - sqlNode.toSqlString(SqlDialect.CALCITE, false).getSql(); + sqlNode.toSqlString(CalciteSqlDialect.DEFAULT, false).getSql(); // Parse and unparse again. SqlNode sqlNode2; @@ -8190,7 +8190,7 @@ public class UnparsingTesterImpl extends TesterImpl { quoting = q; } final String sql2 = - sqlNode2.toSqlString(SqlDialect.CALCITE, false).getSql(); + sqlNode2.toSqlString(CalciteSqlDialect.DEFAULT, false).getSql(); // Should be the same as we started with. assertEquals(sql1, sql2); @@ -8212,7 +8212,7 @@ public class UnparsingTesterImpl extends TesterImpl { // Unparse again in Calcite dialect (which we can parse), and // minimal parentheses. final String sql1 = - sqlNode.toSqlString(SqlDialect.CALCITE, false).getSql(); + sqlNode.toSqlString(CalciteSqlDialect.DEFAULT, false).getSql(); // Parse and unparse again. SqlNode sqlNode2; @@ -8224,7 +8224,7 @@ public class UnparsingTesterImpl extends TesterImpl { quoting = q; } final String sql2 = - sqlNode2.toSqlString(SqlDialect.CALCITE, false).getSql(); + sqlNode2.toSqlString(CalciteSqlDialect.DEFAULT, false).getSql(); // Should be the same as we started with. assertEquals(sql1, sql2); diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java index 15ddb1365653..7c0be3fbac97 100644 --- a/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java +++ b/core/src/test/java/org/apache/calcite/sql/test/SqlOperatorBaseTest.java @@ -26,7 +26,6 @@ import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCallBinding; import org.apache.calcite.sql.SqlDataTypeSpec; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlJdbcFunctionCall; import org.apache.calcite.sql.SqlLiteral; @@ -34,6 +33,8 @@ import org.apache.calcite.sql.SqlNodeList; import org.apache.calcite.sql.SqlOperandCountRange; import org.apache.calcite.sql.SqlOperator; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.fun.OracleSqlOperatorTable; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParserPos; @@ -6733,7 +6734,7 @@ protected void checkAggType(SqlTester tester, String expr, String type) { SqlLiteral literal = type.getSqlTypeName().createLiteral(o, SqlParserPos.ZERO); SqlString literalString = - literal.toSqlString(SqlDialect.DUMMY); + literal.toSqlString(AnsiSqlDialect.DEFAULT); final String expr = "CAST(" + literalString + " AS " + type + ")"; @@ -6783,7 +6784,7 @@ protected void checkAggType(SqlTester tester, String expr, String type) { SqlLiteral literal = type.getSqlTypeName().createLiteral(o, SqlParserPos.ZERO); SqlString literalString = - literal.toSqlString(SqlDialect.DUMMY); + literal.toSqlString(AnsiSqlDialect.DEFAULT); if ((type.getSqlTypeName() == SqlTypeName.BIGINT) || ((type.getSqlTypeName() == SqlTypeName.DECIMAL) @@ -6900,7 +6901,7 @@ protected void checkAggType(SqlTester tester, String expr, String type) { continue; } final SqlPrettyWriter writer = - new SqlPrettyWriter(SqlDialect.CALCITE); + new SqlPrettyWriter(CalciteSqlDialect.DEFAULT); op.unparse(writer, call, 0, 0); final String s = writer.toSqlString().toString(); if (s.startsWith("OVERLAY(") diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java index 83d5a7efd964..ce7a806a484c 100644 --- a/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java +++ b/core/src/test/java/org/apache/calcite/sql/test/SqlPrettyWriterTest.java @@ -17,9 +17,9 @@ package org.apache.calcite.sql.test; import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlWriter; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParser; import org.apache.calcite.sql.pretty.SqlPrettyWriter; @@ -78,7 +78,7 @@ protected void assertPrintsTo( String expected) { final SqlNode node = parseQuery(sql); final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setAlwaysUseParentheses(false); if (newlines) { prettyWriter.setCaseClausesOnNewLines(true); @@ -101,7 +101,7 @@ protected void assertExprPrintsTo( final SqlCall rowCall = valuesCall.operand(0); final SqlNode node = rowCall.operand(0); final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setAlwaysUseParentheses(false); if (newlines) { prettyWriter.setCaseClausesOnNewLines(true); @@ -153,34 +153,34 @@ protected void checkSimple( @Test public void testDefault() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testIndent8() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setIndentation(8); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testClausesNotOnNewLine() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setClauseStartsLine(false); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testSelectListItemsOnSeparateLines() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setSelectListItemsOnSeparateLines(true); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testSelectListExtraIndentFlag() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setSelectListItemsOnSeparateLines(true); prettyWriter.setSelectListExtraIndentFlag(false); checkSimple(prettyWriter, "${desc}", "${formatted}"); @@ -188,21 +188,21 @@ protected void checkSimple( @Test public void testKeywordsLowerCase() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setKeywordsLowerCase(true); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testParenthesizeAllExprs() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setAlwaysUseParentheses(true); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @Test public void testOnlyQuoteIdentifiersWhichNeedIt() throws Exception { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setQuoteAllIdentifiers(false); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @@ -211,7 +211,7 @@ protected void checkSimple( // Note that ( is at the indent, SELECT is on the same line, and ) is // below it. final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setSubQueryStyle(SqlWriter.SubQueryStyle.BLACK); checkSimple(prettyWriter, "${desc}", "${formatted}"); } @@ -330,7 +330,7 @@ protected void checkSimple( private void checkPrettySeparateLines(String sql) { final SqlPrettyWriter prettyWriter = - new SqlPrettyWriter(SqlDialect.DUMMY); + new SqlPrettyWriter(AnsiSqlDialect.DEFAULT); prettyWriter.setSelectListItemsOnSeparateLines(true); prettyWriter.setSelectListExtraIndentFlag(false); diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlTesterImpl.java b/core/src/test/java/org/apache/calcite/sql/test/SqlTesterImpl.java index f4b2fbd7bc48..c96c4e871d62 100644 --- a/core/src/test/java/org/apache/calcite/sql/test/SqlTesterImpl.java +++ b/core/src/test/java/org/apache/calcite/sql/test/SqlTesterImpl.java @@ -24,13 +24,13 @@ import org.apache.calcite.runtime.Utilities; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlCollation; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlIntervalLiteral; import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlOperatorTable; import org.apache.calcite.sql.SqlSelect; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParseException; import org.apache.calcite.sql.parser.SqlParser; @@ -475,7 +475,7 @@ public void checkRewrite( String expectedRewrite) { SqlNode rewrittenNode = parseAndValidate(validator, query); String actualRewrite = - rewrittenNode.toSqlString(SqlDialect.DUMMY, false).getSql(); + rewrittenNode.toSqlString(AnsiSqlDialect.DEFAULT, false).getSql(); TestUtil.assertEqualsVerbose(expectedRewrite, Util.toLinux(actualRewrite)); } diff --git a/core/src/test/java/org/apache/calcite/test/SqlLimitsTest.java b/core/src/test/java/org/apache/calcite/test/SqlLimitsTest.java index 86c55f02c5b1..1bb26d4b1e27 100644 --- a/core/src/test/java/org/apache/calcite/test/SqlLimitsTest.java +++ b/core/src/test/java/org/apache/calcite/test/SqlLimitsTest.java @@ -21,8 +21,8 @@ import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.rel.type.RelDataTypeFactory; import org.apache.calcite.rel.type.RelDataTypeSystem; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlLiteral; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.BasicSqlType; import org.apache.calcite.sql.type.SqlTypeName; @@ -204,7 +204,7 @@ private void printLimit( SqlLiteral literal = type.getSqlTypeName().createLiteral(o, SqlParserPos.ZERO); pw.print("; as SQL: "); - pw.print(literal.toSqlString(SqlDialect.DUMMY)); + pw.print(literal.toSqlString(AnsiSqlDialect.DEFAULT)); pw.println(); } diff --git a/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java b/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java index 617056368353..6de282e3f55f 100644 --- a/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java +++ b/core/src/test/java/org/apache/calcite/tools/FrameworksTest.java @@ -39,10 +39,10 @@ import org.apache.calcite.schema.Table; import org.apache.calcite.schema.impl.AbstractTable; import org.apache.calcite.server.CalciteServerStatement; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlExplainFormat; import org.apache.calcite.sql.SqlExplainLevel; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.SqlTypeName; import org.apache.calcite.test.CalciteAssert; @@ -186,7 +186,7 @@ private void checkTypeSystem(final int expected, FrameworkConfig config) { SqlNode val = planner.validate(parse); String valStr = - val.toSqlString(SqlDialect.DUMMY, false).getSql(); + val.toSqlString(AnsiSqlDialect.DEFAULT, false).getSql(); String expandedStr = "SELECT `emps`.`empid`, `emps`.`deptno`, `emps`.`name`, `emps`.`salary`, `emps`.`commission`\n" diff --git a/core/src/test/java/org/apache/calcite/util/Smalls.java b/core/src/test/java/org/apache/calcite/util/Smalls.java index 6ea55bf098d0..1b8824affeaa 100644 --- a/core/src/test/java/org/apache/calcite/util/Smalls.java +++ b/core/src/test/java/org/apache/calcite/util/Smalls.java @@ -47,8 +47,8 @@ import org.apache.calcite.schema.impl.AbstractTable; import org.apache.calcite.schema.impl.ViewTable; import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.type.SqlTypeName; import com.google.common.collect.ImmutableList; @@ -357,7 +357,7 @@ public RelDataType apply(RelDataTypeFactory typeFactory) { return typeFactory.builder().add("c", SqlTypeName.VARCHAR, 100) .build(); } - }, "values (" + SqlDialect.CALCITE.quoteStringLiteral(s) + ")", + }, "values (" + CalciteSqlDialect.DEFAULT.quoteStringLiteral(s) + ")", ImmutableList.of(), Arrays.asList("view")); } @@ -371,8 +371,8 @@ public RelDataType apply(RelDataTypeFactory typeFactory) { .build(); } }, - "values " + SqlDialect.CALCITE.quoteStringLiteral(o.toString()) - + ", " + SqlDialect.CALCITE.quoteStringLiteral(p.toString()), + "values " + CalciteSqlDialect.DEFAULT.quoteStringLiteral(o.toString()) + + ", " + CalciteSqlDialect.DEFAULT.quoteStringLiteral(p.toString()), ImmutableList.of(), Arrays.asList("view")); } diff --git a/core/src/test/java/org/apache/calcite/util/UtilTest.java b/core/src/test/java/org/apache/calcite/util/UtilTest.java index 080ad4cd56b8..83353422bb8b 100644 --- a/core/src/test/java/org/apache/calcite/util/UtilTest.java +++ b/core/src/test/java/org/apache/calcite/util/UtilTest.java @@ -30,7 +30,7 @@ import org.apache.calcite.runtime.Resources; import org.apache.calcite.runtime.SqlFunctions; import org.apache.calcite.runtime.Utilities; -import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.dialect.CalciteSqlDialect; import org.apache.calcite.sql.util.SqlBuilder; import org.apache.calcite.sql.util.SqlString; import org.apache.calcite.test.DiffTestCase; @@ -652,7 +652,7 @@ private List makeConsList(int start, int end) { * Tests SQL builders. */ @Test public void testSqlBuilder() { - final SqlBuilder buf = new SqlBuilder(SqlDialect.CALCITE); + final SqlBuilder buf = new SqlBuilder(CalciteSqlDialect.DEFAULT); assertEquals(0, buf.length()); buf.append("select "); assertEquals("select ", buf.getSql()); @@ -665,7 +665,7 @@ private List makeConsList(int start, int end) { assertEquals("select \"x\", \"y\".\"a b\"", buf.getSql()); final SqlString sqlString = buf.toSqlString(); - assertEquals(SqlDialect.CALCITE, sqlString.getDialect()); + assertEquals(CalciteSqlDialect.DEFAULT, sqlString.getDialect()); assertEquals(buf.getSql(), sqlString.getSql()); assertTrue(buf.getSql().length() > 0); From 0c7418a4ab504cb765b4a1a272425715b353c537 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Mon, 18 Sep 2017 08:26:08 +0200 Subject: [PATCH 2/2] Applied requested changes --- .../calcite/adapter/jdbc/JdbcSchema.java | 9 +- .../calcite/adapter/jdbc/JdbcUtils.java | 1 + .../apache/calcite/model/ModelHandler.java | 9 +- .../rel/rel2sql/RelToSqlConverter.java | 4 +- .../calcite/rel/rel2sql/SqlImplementor.java | 4 +- .../org/apache/calcite/sql/SqlDialect.java | 117 ++-------------- .../calcite/sql/SqlDialectFactoryImpl.java | 109 +++++++++++---- .../calcite/sql/dialect/AccessSqlDialect.java | 10 +- .../calcite/sql/dialect/AnsiSqlDialect.java | 11 +- .../sql/dialect/CalciteSqlDialect.java | 2 +- .../calcite/sql/dialect/Db2SqlDialect.java | 11 +- .../calcite/sql/dialect/DerbySqlDialect.java | 10 +- .../sql/dialect/FirebirdSqlDialect.java | 10 +- .../calcite/sql/dialect/H2SqlDialect.java | 11 +- .../calcite/sql/dialect/HiveSqlDialect.java | 10 +- .../calcite/sql/dialect/HsqldbHandler.java | 83 ----------- .../calcite/sql/dialect/HsqldbSqlDialect.java | 11 +- .../sql/dialect/InfobrightSqlDialect.java | 10 +- .../sql/dialect/InformixSqlDialect.java | 10 +- .../sql/dialect/IngressSqlDialect.java | 10 +- .../sql/dialect/InterbaseSqlDialect.java | 10 +- .../calcite/sql/dialect/LucidbSqlDialect.java | 10 +- .../calcite/sql/dialect/MssqlHandler.java | 129 ------------------ .../calcite/sql/dialect/MssqlSqlDialect.java | 11 +- .../calcite/sql/dialect/MysqlHandler.java | 109 --------------- .../calcite/sql/dialect/MysqlSqlDialect.java | 21 +-- .../sql/dialect/NeoviewSqlDialect.java | 10 +- .../sql/dialect/NetezzaSqlDialect.java | 10 +- .../calcite/sql/dialect/OracleHandler.java | 68 --------- .../calcite/sql/dialect/OracleSqlDialect.java | 11 +- .../sql/dialect/ParaccelSqlDialect.java | 10 +- .../sql/dialect/PhoenixSqlDialect.java | 11 +- .../sql/dialect/PostgresqlHandler.java | 60 -------- .../sql/dialect/PostgresqlSqlDialect.java | 11 +- .../sql/dialect/RedshiftSqlDialect.java | 11 +- .../calcite/sql/dialect/SybaseSqlDialect.java | 10 +- .../sql/dialect/TeradataSqlDialect.java | 10 +- .../sql/dialect/VerticaSqlDialect.java | 10 +- 38 files changed, 247 insertions(+), 727 deletions(-) delete mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java delete mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java delete mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java delete mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java delete mode 100644 core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java index bc783183e277..e08ad3f4b8ea 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcSchema.java @@ -158,13 +158,8 @@ public static JdbcSchema create( return JdbcSchema.create( parentSchema, name, dataSource, jdbcCatalog, jdbcSchema); } else { - SqlDialectFactory factory; - try { - factory = (SqlDialectFactory) Class.forName(sqlDialectFactory).newInstance(); - } catch (Exception ex) { - throw new RuntimeException("Could not instantiate SqlDialectFactory: " - + sqlDialectFactory, ex); - } + SqlDialectFactory factory = AvaticaUtils.instantiatePlugin( + SqlDialectFactory.class, sqlDialectFactory); return JdbcSchema.create( parentSchema, name, dataSource, factory, jdbcCatalog, jdbcSchema); } diff --git a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java index 15d479f981be..0fe1761a4575 100644 --- a/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java +++ b/core/src/main/java/org/apache/calcite/adapter/jdbc/JdbcUtils.java @@ -64,6 +64,7 @@ static class DialectPool { public static final DialectPool INSTANCE = new DialectPool(); + // TODO: Discuss why we need a pool. If we do, I'd like to improve performance synchronized SqlDialect get(SqlDialectFactory dialectFactory, DataSource dataSource) { Map dialectMap = map0.get(dataSource); if (dialectMap != null) { diff --git a/core/src/main/java/org/apache/calcite/model/ModelHandler.java b/core/src/main/java/org/apache/calcite/model/ModelHandler.java index 4397f6933b52..2f2419d5fbbd 100644 --- a/core/src/main/java/org/apache/calcite/model/ModelHandler.java +++ b/core/src/main/java/org/apache/calcite/model/ModelHandler.java @@ -327,13 +327,8 @@ public void visit(JsonJdbcSchema jsonSchema) { JdbcSchema.create(parentSchema, jsonSchema.name, dataSource, jsonSchema.jdbcCatalog, jsonSchema.jdbcSchema); } else { - SqlDialectFactory factory; - try { - factory = (SqlDialectFactory) Class.forName(jsonSchema.sqlDialectFactory).newInstance(); - } catch (Exception ex) { - throw new RuntimeException("Could not instantiate SqlDialectFactory: " - + jsonSchema.sqlDialectFactory, ex); - } + SqlDialectFactory factory = AvaticaUtils.instantiatePlugin( + SqlDialectFactory.class, jsonSchema.sqlDialectFactory); schema = JdbcSchema.create(parentSchema, jsonSchema.name, dataSource, factory, jsonSchema.jdbcCatalog, jsonSchema.jdbcSchema); diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java index be3dc00328b5..45ec2f792b9e 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/RelToSqlConverter.java @@ -398,7 +398,9 @@ public Result visit(Match e) { if (e.getOrderKeys() != null) { for (RelFieldCollation fc : e.getOrderKeys().getFieldCollations()) { if (fc.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) { - SqlNode nullDirectionNode = dialect.emulateNullDirection(context, fc); + boolean first = fc.nullDirection == RelFieldCollation.NullDirection.FIRST; + SqlNode nullDirectionNode = dialect.emulateNullDirection( + context.field(fc.getFieldIndex()), first); if (nullDirectionNode != null) { orderBySqlList.add(nullDirectionNode); fc = new RelFieldCollation(fc.getFieldIndex(), fc.getDirection(), diff --git a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java index bb5e3845012d..fd4b8ec129d2 100644 --- a/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java +++ b/core/src/main/java/org/apache/calcite/rel/rel2sql/SqlImplementor.java @@ -1088,7 +1088,9 @@ public void setOffset(SqlNode offset) { public void addOrderItem(List orderByList, RelFieldCollation field) { if (field.nullDirection != RelFieldCollation.NullDirection.UNSPECIFIED) { - SqlNode nullDirectionNode = dialect.emulateNullDirection(context, field); + boolean first = field.nullDirection == RelFieldCollation.NullDirection.FIRST; + SqlNode nullDirectionNode = dialect.emulateNullDirection( + context.field(field.getFieldIndex()), first); if (nullDirectionNode != null) { orderByList.add(nullDirectionNode); field = new RelFieldCollation(field.getFieldIndex(), diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java index 3ea36c279413..dd16cd1042b4 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialect.java @@ -20,15 +20,9 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.linq4j.function.Experimental; import org.apache.calcite.rel.RelFieldCollation; -import org.apache.calcite.rel.rel2sql.SqlImplementor; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.dialect.CalciteSqlDialect; -import org.apache.calcite.sql.dialect.HsqldbHandler; -import org.apache.calcite.sql.dialect.MssqlHandler; -import org.apache.calcite.sql.dialect.MysqlHandler; -import org.apache.calcite.sql.dialect.OracleHandler; -import org.apache.calcite.sql.dialect.PostgresqlHandler; import org.apache.calcite.sql.parser.SqlParserPos; import org.apache.calcite.sql.type.BasicSqlType; import org.apache.calcite.sql.type.SqlTypeUtil; @@ -40,7 +34,6 @@ import java.sql.DatabaseMetaData; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.List; @@ -56,7 +49,6 @@ public class SqlDialect { //~ Static fields/initializers --------------------------------------------- - private static final Handler DEFAULT_HANDLER = new BaseHandler(); protected static final Logger LOGGER = LoggerFactory.getLogger(SqlDialect.class); @@ -87,8 +79,6 @@ public class SqlDialect { @Deprecated // to be removed before 2.0 private final DatabaseProduct databaseProduct; private final NullCollation nullCollation; - @Deprecated // to be removed before 2.0 - private final Handler handler; //~ Constructors ----------------------------------------------------------- @@ -108,61 +98,19 @@ public static SqlDialect create(DatabaseMetaData databaseMetaData) { return new SqlDialectFactoryImpl().create(databaseMetaData); } - protected static NullCollation getNullCollation(DatabaseMetaData databaseMetaData) { - try { - if (databaseMetaData.nullsAreSortedAtEnd()) { - return NullCollation.LAST; - } else if (databaseMetaData.nullsAreSortedAtStart()) { - return NullCollation.FIRST; - } else if (databaseMetaData.nullsAreSortedLow()) { - return NullCollation.LOW; - } else if (databaseMetaData.nullsAreSortedHigh()) { - return NullCollation.HIGH; - } else { - throw new IllegalArgumentException("cannot deduce null collation"); - } - } catch (SQLException e) { - throw new IllegalArgumentException("cannot deduce null collation", e); - } - } - - protected static String getIdentifierQuoteString(DatabaseMetaData databaseMetaData) { - try { - return databaseMetaData.getIdentifierQuoteString(); - } catch (SQLException e) { - throw new IllegalArgumentException("cannot deduce identifier quote string", e); - } - } - @Deprecated // to be removed before 2.0 public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString) { this(databaseProduct, databaseProductName, identifierQuoteString, - NullCollation.HIGH, DEFAULT_HANDLER); + NullCollation.HIGH); } /** Creates a SqlDialect with the default handler. */ - public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, - String identifierQuoteString, NullCollation nullCollation) { - this(databaseProduct, databaseProductName, identifierQuoteString, - nullCollation, DEFAULT_HANDLER); - } - - @Deprecated // to be removed before 2.0, replace with constructor without DatabaseProduct - protected SqlDialect(DatabaseProduct databaseProduct, DatabaseMetaData databaseMetaData) { - this( - databaseProduct, - getIdentifierQuoteString(databaseMetaData), - getNullCollation(databaseMetaData) - ); - } - @Deprecated // to be removed before 2.0, replace with constructor without DatabaseProduct protected SqlDialect(DatabaseProduct databaseProduct, String identifierQuoteString, NullCollation nullCollation) { this.nullCollation = Preconditions.checkNotNull(nullCollation); this.databaseProduct = Preconditions.checkNotNull(databaseProduct); - this.handler = null; if (identifierQuoteString != null) { identifierQuoteString = identifierQuoteString.trim(); if (identifierQuoteString.equals("")) { @@ -182,6 +130,12 @@ protected SqlDialect(DatabaseProduct databaseProduct, String identifierQuoteStri : this.identifierEndQuoteString + this.identifierEndQuoteString; } + // This will be our new constructor in 2.0 + @SuppressWarnings("deprecation") public SqlDialect(String databaseProductName, + String identifierQuoteString, NullCollation nullCollation) { + this(null, databaseProductName, identifierQuoteString, nullCollation); + } + /** * Creates a SqlDialect. * @@ -191,17 +145,14 @@ protected SqlDialect(DatabaseProduct databaseProduct, String identifierQuoteStri * is not supported. If "[", close quote is * deemed to be "]". * @param nullCollation Whether NULL values appear first or last - * @param handler Handler for un-parsing */ @Deprecated // to be removed before 2.0 - @Experimental + @Experimental // Keep around until we remove DatabaseProduct public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, - String identifierQuoteString, NullCollation nullCollation, - Handler handler) { + String identifierQuoteString, NullCollation nullCollation) { this.nullCollation = Preconditions.checkNotNull(nullCollation); Preconditions.checkNotNull(databaseProductName); this.databaseProduct = Preconditions.checkNotNull(databaseProduct); - this.handler = Preconditions.checkNotNull(handler); if (identifierQuoteString != null) { identifierQuoteString = identifierQuoteString.trim(); if (identifierQuoteString.equals("")) { @@ -295,24 +246,6 @@ public static DatabaseProduct getProduct( } } - /** Chooses the best handler for a given database product. */ - private static Handler chooseHandler(DatabaseProduct databaseProduct) { - switch (databaseProduct) { - case HSQLDB: - return HsqldbHandler.INSTANCE; - case MSSQL: - return MssqlHandler.INSTANCE; - case MYSQL: - return MysqlHandler.INSTANCE; - case ORACLE: - return OracleHandler.INSTANCE; - case POSTGRESQL: - return PostgresqlHandler.INSTANCE; - default: - return DEFAULT_HANDLER; - } - } - /** * Encloses an identifier in quotation marks appropriate for the current SQL * dialect. @@ -607,11 +540,11 @@ public SqlNode rewriteSingleValueExpr(SqlNode aggCall) { * Returns the SqlNode for emulating the null direction for the given field * or null if no emulation needs to be done. * - * @param context The translation context - * @param field The field for which to emulate null direction + * @param node The SqlNode representing the expression + * @param nullsFirst true if nulls should come first, false otherwise * @return A SqlNode for null direction emulation or null if not required */ - public SqlNode emulateNullDirection(SqlImplementor.Context context, RelFieldCollation field) { + public SqlNode emulateNullDirection(SqlNode node, boolean nullsFirst) { return null; } @@ -788,37 +721,13 @@ public enum DatabaseProduct { */ public SqlDialect getDialect() { if (dialect == null) { - final Handler handler = chooseHandler(this); dialect = new SqlDialect(this, databaseProductName, quoteString, - nullCollation, handler); + nullCollation); } return dialect; } } - - /** - * A handler for converting {@link SqlNode} into SQL text of a particular - * dialect. - * - *

    Instances are stateless and therefore immutable. - */ - @Deprecated // to be removed before 2.0 - @Experimental - public interface Handler { - void unparseCall(SqlWriter writer, SqlCall call, int leftPrec, - int rightPrec); - } - - /** Base class for dialect handlers. */ - @Deprecated // to be removed before 2.0 - @Experimental - public static class BaseHandler implements Handler { - public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - call.getOperator().unparse(writer, call, leftPrec, rightPrec); - } - } } // End SqlDialect.java diff --git a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java index bd9e01a47af4..c05095d04200 100644 --- a/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java +++ b/core/src/main/java/org/apache/calcite/sql/SqlDialectFactoryImpl.java @@ -16,6 +16,7 @@ */ package org.apache.calcite.sql; +import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.dialect.AccessSqlDialect; import org.apache.calcite.sql.dialect.AnsiSqlDialect; import org.apache.calcite.sql.dialect.Db2SqlDialect; @@ -56,72 +57,128 @@ public class SqlDialectFactoryImpl implements SqlDialectFactory { */ public SqlDialect create(DatabaseMetaData databaseMetaData) { String databaseProductName; + String databaseVersion; try { databaseProductName = databaseMetaData.getDatabaseProductName(); + databaseVersion = databaseMetaData.getDatabaseProductVersion(); } catch (SQLException e) { throw new RuntimeException("while detecting database product", e); } final String upperProductName = databaseProductName.toUpperCase(Locale.ROOT).trim(); + String quoteString = getIdentifierQuoteString(databaseMetaData); + NullCollation nullCollation = getNullCollation(databaseMetaData); switch (upperProductName) { case "ACCESS": - return new AccessSqlDialect(databaseMetaData); + return new AccessSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "APACHE DERBY": - return new DerbySqlDialect(databaseMetaData); + return new DerbySqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "DBMS:CLOUDSCAPE": - return new DerbySqlDialect(databaseMetaData); + return new DerbySqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "HIVE": - return new HiveSqlDialect(databaseMetaData); + return new HiveSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "INGRES": - return new IngressSqlDialect(databaseMetaData); + return new IngressSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "INTERBASE": - return new InterbaseSqlDialect(databaseMetaData); + return new InterbaseSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "LUCIDDB": - return new LucidbSqlDialect(databaseMetaData); + return new LucidbSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "ORACLE": - return new OracleSqlDialect(databaseMetaData); + return new OracleSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "PHOENIX": - return new PhoenixSqlDialect(databaseMetaData); + return new PhoenixSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "MYSQL (INFOBRIGHT)": - return new InfobrightSqlDialect(databaseMetaData); + return new InfobrightSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "MYSQL": - return new MysqlSqlDialect(databaseMetaData); + return new MysqlSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); case "REDSHIFT": - return new RedshiftSqlDialect(databaseMetaData); + return new RedshiftSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } // Now the fuzzy matches. if (databaseProductName.startsWith("DB2")) { - return new Db2SqlDialect(databaseMetaData); + return new Db2SqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("FIREBIRD")) { - return new FirebirdSqlDialect(databaseMetaData); + return new FirebirdSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (databaseProductName.startsWith("Informix")) { - return new InformixSqlDialect(databaseMetaData); + return new InformixSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("NETEZZA")) { - return new NetezzaSqlDialect(databaseMetaData); + return new NetezzaSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("PARACCEL")) { - return new ParaccelSqlDialect(databaseMetaData); + return new ParaccelSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (databaseProductName.startsWith("HP Neoview")) { - return new NeoviewSqlDialect(databaseMetaData); + return new NeoviewSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("POSTGRE")) { - return new PostgresqlSqlDialect(databaseMetaData); + return new PostgresqlSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("SQL SERVER")) { - return new MssqlSqlDialect(databaseMetaData); + return new MssqlSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("SYBASE")) { - return new SybaseSqlDialect(databaseMetaData); + return new SybaseSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("TERADATA")) { - return new TeradataSqlDialect(databaseMetaData); + return new TeradataSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("HSQL")) { - return new HsqldbSqlDialect(databaseMetaData); + return new HsqldbSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("H2")) { - return new H2SqlDialect(databaseMetaData); + return new H2SqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else if (upperProductName.contains("VERTICA")) { - return new VerticaSqlDialect(databaseMetaData); + return new VerticaSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } else { - return new AnsiSqlDialect(databaseMetaData); + return new AnsiSqlDialect(databaseProductName, databaseVersion, + quoteString, nullCollation); } } + protected static NullCollation getNullCollation(DatabaseMetaData databaseMetaData) { + try { + if (databaseMetaData.nullsAreSortedAtEnd()) { + return NullCollation.LAST; + } else if (databaseMetaData.nullsAreSortedAtStart()) { + return NullCollation.FIRST; + } else if (databaseMetaData.nullsAreSortedLow()) { + return NullCollation.LOW; + } else if (databaseMetaData.nullsAreSortedHigh()) { + return NullCollation.HIGH; + } else { + throw new IllegalArgumentException("cannot deduce null collation"); + } + } catch (SQLException e) { + throw new IllegalArgumentException("cannot deduce null collation", e); + } + } + + protected static String getIdentifierQuoteString(DatabaseMetaData databaseMetaData) { + try { + return databaseMetaData.getIdentifierQuoteString(); + } catch (SQLException e) { + throw new IllegalArgumentException("cannot deduce identifier quote string", e); + } + } + } // End SqlDialectFactoryImpl.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java index 02914a885821..a150cfa8818e 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/AccessSqlDialect.java @@ -19,8 +19,6 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Access database. */ @@ -28,11 +26,13 @@ public class AccessSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new AccessSqlDialect(); - public AccessSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.ACCESS, databaseMetaData); + @SuppressWarnings("deprecation") public AccessSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.ACCESS, identifierQuoteString, nullCollation); } - private AccessSqlDialect() { + @SuppressWarnings("deprecation") private AccessSqlDialect() { super(DatabaseProduct.ACCESS, "\"", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java index 65985b05351a..cd4ad848f598 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/AnsiSqlDialect.java @@ -19,8 +19,6 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for an unknown ANSI compatible database. */ @@ -32,14 +30,17 @@ public class AnsiSqlDialect extends SqlDialect { */ public static final SqlDialect DEFAULT = new AnsiSqlDialect(); - public AnsiSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public AnsiSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.UNKNOWN, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private AnsiSqlDialect() { + @SuppressWarnings("deprecation") private AnsiSqlDialect() { super( DatabaseProduct.UNKNOWN, "`", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java index 927ba189f7bc..0cb13d89bcf2 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/CalciteSqlDialect.java @@ -25,7 +25,7 @@ public class CalciteSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new CalciteSqlDialect(); - private CalciteSqlDialect() { + @SuppressWarnings("deprecation") private CalciteSqlDialect() { super( DatabaseProduct.CALCITE, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java index 6312a350ae88..1f9ec1423249 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/Db2SqlDialect.java @@ -19,22 +19,23 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Db2 database. */ public class Db2SqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new Db2SqlDialect(); - public Db2SqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public Db2SqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.DB2, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private Db2SqlDialect() { + @SuppressWarnings("deprecation") private Db2SqlDialect() { super( DatabaseProduct.DB2, null, diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java index 9afaec77b12d..445c0d51591d 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/DerbySqlDialect.java @@ -19,8 +19,6 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Derby database. */ @@ -28,11 +26,13 @@ public class DerbySqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new DerbySqlDialect(); - public DerbySqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.DERBY, databaseMetaData); + @SuppressWarnings("deprecation") public DerbySqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.DERBY, identifierQuoteString, nullCollation); } - private DerbySqlDialect() { + @SuppressWarnings("deprecation") private DerbySqlDialect() { super(DatabaseProduct.DERBY, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java index 10d12b3cfc55..b53d59f15c4f 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/FirebirdSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Firebird database. */ public class FirebirdSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new FirebirdSqlDialect(); - public FirebirdSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.FIREBIRD, databaseMetaData); + @SuppressWarnings("deprecation") public FirebirdSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.FIREBIRD, identifierQuoteString, nullCollation); } - private FirebirdSqlDialect() { + @SuppressWarnings("deprecation") private FirebirdSqlDialect() { super(DatabaseProduct.FIREBIRD, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java index 9c9b647d4d51..0949e8e93a1a 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/H2SqlDialect.java @@ -19,22 +19,23 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the H2 database. */ public class H2SqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new H2SqlDialect(); - public H2SqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public H2SqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.H2, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private H2SqlDialect() { + @SuppressWarnings("deprecation") private H2SqlDialect() { super( DatabaseProduct.H2, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java index 6291666a1d35..8fe3c5d6d850 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/HiveSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Hive database. */ public class HiveSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new HiveSqlDialect(); - public HiveSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.HIVE, databaseMetaData); + @SuppressWarnings("deprecation") public HiveSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.HIVE, identifierQuoteString, nullCollation); } - private HiveSqlDialect() { + @SuppressWarnings("deprecation") private HiveSqlDialect() { super(DatabaseProduct.HIVE, null, NullCollation.HIGH); } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java deleted file mode 100644 index 5d12a58604ad..000000000000 --- a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbHandler.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.sql.dialect; - -import org.apache.calcite.avatica.util.TimeUnitRange; -import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.fun.SqlFloorFunction; - -/** - * Defines how a SQL parse tree should be unparsed to SQL - * for execution against an HSQLDB database. - * - *

    It reverts to the unparse method of the operator - * if this database's implementation is standard. - */ -@Deprecated // to be removed before 2.0 -public class HsqldbHandler extends SqlDialect.BaseHandler { - public static final HsqldbHandler INSTANCE = new HsqldbHandler(); - - @Override public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - switch (call.getKind()) { - case FLOOR: - if (call.operandCount() != 2) { - super.unparseCall(writer, call, leftPrec, rightPrec); - return; - } - - final SqlLiteral timeUnitNode = call.operand(1); - final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); - - final String translatedLit = convertTimeUnit(timeUnit); - SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, translatedLit, - timeUnitNode.getParserPosition()); - SqlFloorFunction.unparseDatetimeFunction(writer, call2, "TRUNC", true); - break; - - default: - super.unparseCall(writer, call, leftPrec, rightPrec); - } - } - - private static String convertTimeUnit(TimeUnitRange unit) { - switch (unit) { - case YEAR: - return "YYYY"; - case MONTH: - return "MM"; - case DAY: - return "DD"; - case WEEK: - return "WW"; - case HOUR: - return "HH24"; - case MINUTE: - return "MI"; - case SECOND: - return "SS"; - default: - throw new AssertionError("could not convert time unit to HSQLDB equivalent: " - + unit); - } - } -} - -// End HsqldbHandler.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java index 98d968298221..d4f4b97b487e 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/HsqldbSqlDialect.java @@ -30,22 +30,23 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.parser.SqlParserPos; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Hsqldb database. */ public class HsqldbSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new HsqldbSqlDialect(); - public HsqldbSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public HsqldbSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.HSQLDB, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private HsqldbSqlDialect() { + @SuppressWarnings("deprecation") private HsqldbSqlDialect() { super( DatabaseProduct.HSQLDB, null, diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java index f2fa3b271fd6..87ee4cc49048 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InfobrightSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Infobright database. */ public class InfobrightSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new InfobrightSqlDialect(); - public InfobrightSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.INFOBRIGHT, databaseMetaData); + @SuppressWarnings("deprecation") public InfobrightSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.INFOBRIGHT, identifierQuoteString, nullCollation); } - private InfobrightSqlDialect() { + @SuppressWarnings("deprecation") private InfobrightSqlDialect() { super(DatabaseProduct.INFOBRIGHT, "`", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java index 5a40bf2ad6aa..eb788b993ac0 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InformixSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Informix database. */ public class InformixSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new InformixSqlDialect(); - public InformixSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.INFORMIX, databaseMetaData); + @SuppressWarnings("deprecation") public InformixSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.INFORMIX, identifierQuoteString, nullCollation); } - private InformixSqlDialect() { + @SuppressWarnings("deprecation") private InformixSqlDialect() { super(DatabaseProduct.INFORMIX, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java index 3b14f39ae767..e067b5de6394 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/IngressSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Ingress database. */ public class IngressSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new IngressSqlDialect(); - public IngressSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.INGRES, databaseMetaData); + @SuppressWarnings("deprecation") public IngressSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.INGRES, identifierQuoteString, nullCollation); } - private IngressSqlDialect() { + @SuppressWarnings("deprecation") private IngressSqlDialect() { super(DatabaseProduct.INGRES, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java index 46be34465f3a..2a9a5eb1c921 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/InterbaseSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Interbase database. */ public class InterbaseSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new InterbaseSqlDialect(); - public InterbaseSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.INTERBASE, databaseMetaData); + @SuppressWarnings("deprecation") public InterbaseSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.INTERBASE, identifierQuoteString, nullCollation); } - private InterbaseSqlDialect() { + @SuppressWarnings("deprecation") private InterbaseSqlDialect() { super(DatabaseProduct.INTERBASE, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java index 92ba67e6a419..9aa0bcb9efbd 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/LucidbSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Lucidb database. */ public class LucidbSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new LucidbSqlDialect(); - public LucidbSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.LUCIDDB, databaseMetaData); + @SuppressWarnings("deprecation") public LucidbSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.LUCIDDB, identifierQuoteString, nullCollation); } - private LucidbSqlDialect() { + @SuppressWarnings("deprecation") private LucidbSqlDialect() { super(DatabaseProduct.LUCIDDB, "\"", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java deleted file mode 100644 index 0f313458f84c..000000000000 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlHandler.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * 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.sql.dialect; - -import org.apache.calcite.avatica.util.TimeUnitRange; -import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlFunction; -import org.apache.calcite.sql.SqlFunctionCategory; -import org.apache.calcite.sql.SqlKind; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlUtil; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import org.apache.calcite.sql.type.ReturnTypes; - -/** - * Defines how a SQL parse tree should be unparsed to SQL - * for execution against a Microsoft SQL Server database. - * - *

    It reverts to the unparse method of the operator - * if this database's implementation is standard. - */ -@Deprecated // to be removed before 2.0 -public class MssqlHandler extends SqlDialect.BaseHandler { - public static final MssqlHandler INSTANCE = new MssqlHandler(); - public static final SqlFunction MSSQL_SUBSTRING = - new SqlFunction("SUBSTRING", SqlKind.OTHER_FUNCTION, - ReturnTypes.ARG0_NULLABLE_VARYING, null, null, - SqlFunctionCategory.STRING); - - @Override public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - if (call.getOperator() == SqlStdOperatorTable.SUBSTRING) { - if (call.operandCount() != 3) { - throw new IllegalArgumentException("MSSQL SUBSTRING requires FROM and FOR arguments"); - } - SqlUtil.unparseFunctionSyntax(MSSQL_SUBSTRING, writer, call); - - } else { - switch (call.getKind()) { - case FLOOR: - if (call.operandCount() != 2) { - super.unparseCall(writer, call, leftPrec, rightPrec); - return; - } - unparseFloor(writer, call); - break; - - default: - super.unparseCall(writer, call, leftPrec, rightPrec); - } - } - } - - /** - * Unparses datetime floor for Microsoft SQL Server. - * There is no TRUNC function, so simulate this using calls to CONVERT. - * - * @param writer Writer - * @param call Call - */ - private void unparseFloor(SqlWriter writer, SqlCall call) { - SqlLiteral node = call.operand(1); - TimeUnitRange unit = (TimeUnitRange) node.getValue(); - - switch (unit) { - case YEAR: - unparseFloorWithUnit(writer, call, 4, "-01-01"); - break; - case MONTH: - unparseFloorWithUnit(writer, call, 7, "-01"); - break; - case WEEK: - writer.print("CONVERT(DATETIME, CONVERT(VARCHAR(10), " - + "DATEADD(day, - (6 + DATEPART(weekday, "); - call.operand(0).unparse(writer, 0, 0); - writer.print(")) % 7, "); - call.operand(0).unparse(writer, 0, 0); - writer.print("), 126))"); - break; - case DAY: - unparseFloorWithUnit(writer, call, 10, ""); - break; - case HOUR: - unparseFloorWithUnit(writer, call, 13, ":00:00"); - break; - case MINUTE: - unparseFloorWithUnit(writer, call, 16, ":00"); - break; - case SECOND: - unparseFloorWithUnit(writer, call, 19, ":00"); - break; - default: - throw new IllegalArgumentException("MSSQL does not support FLOOR for time unit: " - + unit); - } - } - - private void unparseFloorWithUnit(SqlWriter writer, SqlCall call, int charLen, - String offset) { - writer.print("CONVERT"); - SqlWriter.Frame frame = writer.startList("(", ")"); - writer.print("DATETIME, CONVERT(VARCHAR(" + charLen + "), "); - call.operand(0).unparse(writer, 0, 0); - writer.print(", 126)"); - - if (offset.length() > 0) { - writer.print("+'" + offset + "'"); - } - writer.endList(frame); - } -} - -// End MssqlHandler.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java index d8bafbd2fea8..8e75c85637aa 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java @@ -30,8 +30,6 @@ import org.apache.calcite.sql.fun.SqlStdOperatorTable; import org.apache.calcite.sql.type.ReturnTypes; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Mssql database. */ @@ -43,14 +41,17 @@ public class MssqlSqlDialect extends SqlDialect { ReturnTypes.ARG0_NULLABLE_VARYING, null, null, SqlFunctionCategory.STRING); - public MssqlSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public MssqlSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.MSSQL, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private MssqlSqlDialect() { + @SuppressWarnings("deprecation") private MssqlSqlDialect() { super( DatabaseProduct.MSSQL, "[", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java deleted file mode 100644 index 55bb860b2a35..000000000000 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlHandler.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * 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.sql.dialect; - -import org.apache.calcite.avatica.util.TimeUnitRange; -import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlWriter; - -/** - * Defines how a SQL parse tree should be unparsed to SQL - * for execution against a MySQL database. - * - *

    It reverts to the unparse method of the operator - * if this database's implementation is standard. - */ -@Deprecated // to be removed before 2.0 -public class MysqlHandler extends SqlDialect.BaseHandler { - public static final MysqlHandler INSTANCE = new MysqlHandler(); - - @Override public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - switch (call.getKind()) { - case FLOOR: - if (call.operandCount() != 2) { - super.unparseCall(writer, call, leftPrec, rightPrec); - return; - } - - unparseFloor(writer, call); - break; - - default: - super.unparseCall(writer, call, leftPrec, rightPrec); - } - } - - /** - * Unparses datetime floor for MySQL. There is no TRUNC function, so simulate - * this using calls to DATE_FORMAT. - * - * @param writer Writer - * @param call Call - */ - private void unparseFloor(SqlWriter writer, SqlCall call) { - SqlLiteral node = call.operand(1); - TimeUnitRange unit = (TimeUnitRange) node.getValue(); - - if (unit == TimeUnitRange.WEEK) { - writer.print("STR_TO_DATE"); - SqlWriter.Frame frame = writer.startList("(", ")"); - - writer.print("DATE_FORMAT("); - call.operand(0).unparse(writer, 0, 0); - writer.print(", '%x%v-1'), '%x%v-%w'"); - writer.endList(frame); - return; - } - - String format; - switch (unit) { - case YEAR: - format = "%Y-01-01"; - break; - case MONTH: - format = "%Y-%m-01"; - break; - case DAY: - format = "%Y-%m-%d"; - break; - case HOUR: - format = "%Y-%m-%d %k:00:00"; - break; - case MINUTE: - format = "%Y-%m-%d %k:%i:00"; - break; - case SECOND: - format = "%Y-%m-%d %k:%i:%s"; - break; - default: - throw new AssertionError("MYSQL does not support FLOOR for time unit: " - + unit); - } - - writer.print("DATE_FORMAT"); - SqlWriter.Frame frame = writer.startList("(", ")"); - call.operand(0).unparse(writer, 0, 0); - writer.sep(",", true); - writer.print("'" + format + "'"); - writer.endList(frame); - } -} - -// End MysqlHandler.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java index 8833b221c7d7..781358790c52 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MysqlSqlDialect.java @@ -18,8 +18,6 @@ import org.apache.calcite.avatica.util.TimeUnitRange; import org.apache.calcite.config.NullCollation; -import org.apache.calcite.rel.RelFieldCollation; -import org.apache.calcite.rel.rel2sql.SqlImplementor; import org.apache.calcite.rel.type.RelDataType; import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlCall; @@ -41,8 +39,6 @@ import org.apache.calcite.sql.type.OperandTypes; import org.apache.calcite.sql.type.ReturnTypes; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Mysql database. */ @@ -55,11 +51,13 @@ public class MysqlSqlDialect extends SqlDialect { ReturnTypes.BOOLEAN, InferTypes.FIRST_KNOWN, OperandTypes.ANY, SqlFunctionCategory.SYSTEM); - public MysqlSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.MYSQL, databaseMetaData); + @SuppressWarnings("deprecation") public MysqlSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.MYSQL, identifierQuoteString, nullCollation); } - private MysqlSqlDialect() { + @SuppressWarnings("deprecation") private MysqlSqlDialect() { super(DatabaseProduct.MYSQL, "`", NullCollation.HIGH); } @@ -71,9 +69,12 @@ private MysqlSqlDialect() { return false; } - @Override public SqlNode emulateNullDirection(SqlImplementor.Context context, - RelFieldCollation field) { - return ISNULL_FUNCTION.createCall(SqlParserPos.ZERO, context.field(field.getFieldIndex())); + @Override public SqlNode emulateNullDirection(SqlNode node, boolean nullsFirst) { + node = ISNULL_FUNCTION.createCall(SqlParserPos.ZERO, node); + if (nullsFirst) { + node = SqlStdOperatorTable.DESC.createCall(SqlParserPos.ZERO, node); + } + return node; } @Override public boolean supportsAggregateFunction(SqlKind kind) { diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java index 43c5a979a5f4..22fd7d5bed4a 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/NeoviewSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Neoview database. */ public class NeoviewSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new NeoviewSqlDialect(); - public NeoviewSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.NEOVIEW, databaseMetaData); + @SuppressWarnings("deprecation") public NeoviewSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.NEOVIEW, identifierQuoteString, nullCollation); } - private NeoviewSqlDialect() { + @SuppressWarnings("deprecation") private NeoviewSqlDialect() { super(DatabaseProduct.NEOVIEW, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java index ec324f2490dc..2bded09a6f9c 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/NetezzaSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Netezza database. */ public class NetezzaSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new NetezzaSqlDialect(); - public NetezzaSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.NETEZZA, databaseMetaData); + @SuppressWarnings("deprecation") public NetezzaSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.NETEZZA, identifierQuoteString, nullCollation); } - private NetezzaSqlDialect() { + @SuppressWarnings("deprecation") private NetezzaSqlDialect() { super(DatabaseProduct.NETEZZA, "\"", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java deleted file mode 100644 index 53d56ec08db8..000000000000 --- a/core/src/main/java/org/apache/calcite/sql/dialect/OracleHandler.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.sql.dialect; - -import org.apache.calcite.avatica.util.TimeUnitRange; -import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlUtil; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.fun.OracleSqlOperatorTable; -import org.apache.calcite.sql.fun.SqlFloorFunction; -import org.apache.calcite.sql.fun.SqlStdOperatorTable; - -/** - * Defines how a SQL parse tree should be unparsed to SQL - * for execution against an Oracle database. - * - *

    It reverts to the unparse method of the operator - * if this database's implementation is standard. - */ -@Deprecated // to be removed before 2.0 -public class OracleHandler extends SqlDialect.BaseHandler { - public static final OracleHandler INSTANCE = new OracleHandler(); - - @Override public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - if (call.getOperator() == SqlStdOperatorTable.SUBSTRING) { - SqlUtil.unparseFunctionSyntax(OracleSqlOperatorTable.SUBSTR, writer, call); - - } else { - switch (call.getKind()) { - case FLOOR: - if (call.operandCount() != 2) { - super.unparseCall(writer, call, leftPrec, rightPrec); - return; - } - - final SqlLiteral timeUnitNode = call.operand(1); - final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); - - SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), - timeUnitNode.getParserPosition()); - SqlFloorFunction.unparseDatetimeFunction(writer, call2, "TRUNC", true); - break; - - default: - super.unparseCall(writer, call, leftPrec, rightPrec); - } - } - } -} - -// End OracleHandler.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java index 4f3a4aef38fd..3204c3be51c4 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/OracleSqlDialect.java @@ -27,20 +27,19 @@ import org.apache.calcite.sql.fun.SqlFloorFunction; import org.apache.calcite.sql.fun.SqlStdOperatorTable; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Oracle database. */ public class OracleSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new OracleSqlDialect(); - public OracleSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.ORACLE, databaseMetaData - ); + @SuppressWarnings("deprecation") public OracleSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.ORACLE, identifierQuoteString, nullCollation); } - private OracleSqlDialect() { + @SuppressWarnings("deprecation") private OracleSqlDialect() { super( DatabaseProduct.ORACLE, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java index 28290221a5d3..79c4da6eb3c8 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/ParaccelSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Paraccel database. */ public class ParaccelSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new ParaccelSqlDialect(); - public ParaccelSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.PARACCEL, databaseMetaData); + @SuppressWarnings("deprecation") public ParaccelSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.PARACCEL, identifierQuoteString, nullCollation); } - private ParaccelSqlDialect() { + @SuppressWarnings("deprecation") private ParaccelSqlDialect() { super(DatabaseProduct.PARACCEL, "\"", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java index c7d6fc823523..5e426cf336c3 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PhoenixSqlDialect.java @@ -19,22 +19,23 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Phoenix database. */ public class PhoenixSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new PhoenixSqlDialect(); - public PhoenixSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public PhoenixSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.PHOENIX, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private PhoenixSqlDialect() { + @SuppressWarnings("deprecation") private PhoenixSqlDialect() { super( DatabaseProduct.PHOENIX, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java deleted file mode 100644 index aeb629da16ce..000000000000 --- a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlHandler.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.sql.dialect; - -import org.apache.calcite.avatica.util.TimeUnitRange; -import org.apache.calcite.sql.SqlCall; -import org.apache.calcite.sql.SqlDialect; -import org.apache.calcite.sql.SqlLiteral; -import org.apache.calcite.sql.SqlWriter; -import org.apache.calcite.sql.fun.SqlFloorFunction; - -/** - * Defines how a SQL parse tree should be unparsed to SQL - * for execution against a Postgresql database. - * - *

    It reverts to the unparse method of the operator - * if this database's implementation is standard. - */ -@Deprecated // to be removed before 2.0 -public class PostgresqlHandler extends SqlDialect.BaseHandler { - public static final PostgresqlHandler INSTANCE = new PostgresqlHandler(); - - @Override public void unparseCall(SqlWriter writer, SqlCall call, - int leftPrec, int rightPrec) { - switch (call.getKind()) { - case FLOOR: - if (call.operandCount() != 2) { - super.unparseCall(writer, call, leftPrec, rightPrec); - return; - } - - final SqlLiteral timeUnitNode = call.operand(1); - final TimeUnitRange timeUnit = timeUnitNode.getValueAs(TimeUnitRange.class); - - SqlCall call2 = SqlFloorFunction.replaceTimeUnitOperand(call, timeUnit.name(), - timeUnitNode.getParserPosition()); - SqlFloorFunction.unparseDatetimeFunction(writer, call2, "DATE_TRUNC", false); - break; - - default: - super.unparseCall(writer, call, leftPrec, rightPrec); - } - } -} - -// End PostgresqlHandler.java diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java index c0cd220a9307..49513db4d143 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/PostgresqlSqlDialect.java @@ -24,22 +24,23 @@ import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.fun.SqlFloorFunction; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Postgresql database. */ public class PostgresqlSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new PostgresqlSqlDialect(); - public PostgresqlSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public PostgresqlSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.POSTGRESQL, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private PostgresqlSqlDialect() { + @SuppressWarnings("deprecation") private PostgresqlSqlDialect() { super( DatabaseProduct.POSTGRESQL, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java index 9b8d578f99cf..edc452e3da5b 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/RedshiftSqlDialect.java @@ -19,22 +19,23 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Redshift database. */ public class RedshiftSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new RedshiftSqlDialect(); - public RedshiftSqlDialect(DatabaseMetaData databaseMetaData) { + @SuppressWarnings("deprecation") public RedshiftSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { super( DatabaseProduct.REDSHIFT, - databaseMetaData + identifierQuoteString, + nullCollation ); } - private RedshiftSqlDialect() { + @SuppressWarnings("deprecation") private RedshiftSqlDialect() { super( DatabaseProduct.REDSHIFT, "\"", diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java index 23c3b768093a..6df3113266b1 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/SybaseSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Sybase database. */ public class SybaseSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new SybaseSqlDialect(); - public SybaseSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.SYBASE, databaseMetaData); + @SuppressWarnings("deprecation") public SybaseSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.SYBASE, identifierQuoteString, nullCollation); } - private SybaseSqlDialect() { + @SuppressWarnings("deprecation") private SybaseSqlDialect() { super(DatabaseProduct.SYBASE, null, NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java index 4ce3d920c952..78b17aa2b550 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/TeradataSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Teradata database. */ public class TeradataSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new TeradataSqlDialect(); - public TeradataSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.TERADATA, databaseMetaData); + @SuppressWarnings("deprecation") public TeradataSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.TERADATA, identifierQuoteString, nullCollation); } - private TeradataSqlDialect() { + @SuppressWarnings("deprecation") private TeradataSqlDialect() { super(DatabaseProduct.TERADATA, "\"", NullCollation.HIGH); } } diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java index cc7af3d4da15..1bd189a493d9 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/VerticaSqlDialect.java @@ -19,19 +19,19 @@ import org.apache.calcite.config.NullCollation; import org.apache.calcite.sql.SqlDialect; -import java.sql.DatabaseMetaData; - /** * A SqlDialect implementation for the Vertica database. */ public class VerticaSqlDialect extends SqlDialect { public static final SqlDialect DEFAULT = new VerticaSqlDialect(); - public VerticaSqlDialect(DatabaseMetaData databaseMetaData) { - super(DatabaseProduct.VERTICA, databaseMetaData); + @SuppressWarnings("deprecation") public VerticaSqlDialect( + String databaseProduct, String databaseVersion, + String identifierQuoteString, NullCollation nullCollation) { + super(DatabaseProduct.VERTICA, identifierQuoteString, nullCollation); } - private VerticaSqlDialect() { + @SuppressWarnings("deprecation") private VerticaSqlDialect() { super(DatabaseProduct.VERTICA, "\"", NullCollation.HIGH); } }