diff --git a/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java b/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java
index 15c1e4a30d..43438cb658 100644
--- a/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java
+++ b/core/core-backend/src/main/java/io/dataease/datasource/provider/CalciteProvider.java
@@ -16,7 +16,6 @@ import io.dataease.datasource.request.DatasourceRequest;
import io.dataease.datasource.server.EngineServer;
import io.dataease.datasource.type.*;
import io.dataease.engine.constant.SQLConstants;
-import io.dataease.engine.func.scalar.ScalarFunctions;
import io.dataease.exception.DEException;
import io.dataease.i18n.Translator;
import io.dataease.utils.BeanUtils;
@@ -26,6 +25,7 @@ import io.dataease.utils.LogUtil;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.apache.calcite.adapter.jdbc.JdbcSchema;
+import org.apache.calcite.func.scalar.ScalarFunctions;
import org.apache.calcite.jdbc.CalciteConnection;
import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
diff --git a/core/core-backend/src/main/java/io/dataease/engine/func/scalar/ScalarFunctions.java b/core/core-backend/src/main/java/io/dataease/engine/func/scalar/ScalarFunctions.java
deleted file mode 100644
index 8b89ab1cfe..0000000000
--- a/core/core-backend/src/main/java/io/dataease/engine/func/scalar/ScalarFunctions.java
+++ /dev/null
@@ -1,194 +0,0 @@
-package io.dataease.engine.func.scalar;
-
-import io.dataease.engine.utils.Utils;
-import org.apache.commons.lang3.ObjectUtils;
-import org.apache.commons.lang3.StringUtils;
-
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-public class ScalarFunctions {
- public static String format = "yyyy-MM-dd HH:mm:ss";
- public static String minuteFormat = "yyyy-MM-dd HH:mm";
- public static String hourFormat = "yyyy-MM-dd HH";
- public static String dateOnly = "yyyy-MM-dd";
- public static String monthOnly = "yyyy-MM";
- public static String yearOnly = "yyyy";
- public static String timeOnly = "HH:mm:ss";
-
- public static String date_format(String date, String format) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- format = get_date_format(date);
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
- Date parse = simpleDateFormat.parse(date);
- return simpleDateFormat.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String de_date_format(String date, String format) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
- Date parse = simpleDateFormat.parse(date);
- return simpleDateFormat.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String str_to_date(String date, String format) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- format = get_date_format(date);
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
- Date parse = simpleDateFormat.parse(date);
- return simpleDateFormat.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String de_str_to_date(String date, String format) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
- Date parse = simpleDateFormat.parse(date);
- return simpleDateFormat.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String cast_date_format(String date, String sourceFormat, String targetFormat) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- sourceFormat = get_date_format(date);
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sourceFormat);
- Date parse = simpleDateFormat.parse(date);
-
- SimpleDateFormat s = new SimpleDateFormat(targetFormat);
- return s.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String de_cast_date_format(String date, String sourceFormat, String targetFormat) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(sourceFormat);
- Date parse = simpleDateFormat.parse(date);
-
- SimpleDateFormat s = new SimpleDateFormat(targetFormat);
- return s.format(parse);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static Long unix_timestamp(String date) {
- try {
- if (StringUtils.isEmpty(date)) {
- return null;
- }
- return Utils.allDateFormat2Long(date);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String get_date_format(String date) {
- // check date split '-' or '/'
- String format1 = format;
- String minuteFormat1 = minuteFormat;
- String hourFormat1 = hourFormat;
- String timeOnly1 = timeOnly;
- String dateOnly1 = dateOnly;
- String monthOnly1 = monthOnly;
- String yearOnly1 = yearOnly;
- if (date != null && date.contains("/")) {
- format1 = format1.replaceAll("-", "/");
- minuteFormat1 = minuteFormat1.replaceAll("-", "/");
- hourFormat1 = hourFormat1.replaceAll("-", "/");
- timeOnly1 = timeOnly1.replaceAll("-", "/");
- dateOnly1 = dateOnly1.replaceAll("-", "/");
- monthOnly1 = monthOnly1.replaceAll("-", "/");
- yearOnly1 = yearOnly1.replaceAll("-", "/");
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format1);
- simpleDateFormat.parse(date);
- return format1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(minuteFormat1);
- simpleDateFormat.parse(date);
- return minuteFormat1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(hourFormat1);
- simpleDateFormat.parse(date);
- return hourFormat1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(timeOnly1);
- simpleDateFormat.parse(date);
- return timeOnly1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dateOnly1);
- simpleDateFormat.parse(date);
- return dateOnly1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(monthOnly1);
- simpleDateFormat.parse(date);
- return monthOnly1;
- } catch (Exception e) {
- }
- try {
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(yearOnly1);
- simpleDateFormat.parse(date);
- return yearOnly1;
- } catch (Exception e) {
- }
- return format1;
- }
-
- public static String from_unixtime(Long timestamp, String format) {
- try {
- if (ObjectUtils.isEmpty(timestamp)) {
- return null;
- }
- SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
- Date date = new Date(timestamp);
- return simpleDateFormat.format(date);
- } catch (Exception e) {
- return null;
- }
- }
-
- public static String concat(String str1, String str2) {
- return str1 + str2;
- }
-}
diff --git a/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java b/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java
index 725581e5e6..642be9c3d6 100644
--- a/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java
+++ b/core/core-backend/src/main/java/io/dataease/engine/trans/CustomWhere2Str.java
@@ -6,8 +6,8 @@ import io.dataease.api.dataset.union.model.SQLMeta;
import io.dataease.api.dataset.union.model.SQLObj;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.dataease.engine.constant.SQLConstants;
-import io.dataease.engine.func.scalar.ScalarFunctions;
import io.dataease.engine.utils.Utils;
+import org.apache.calcite.func.scalar.ScalarFunctions;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/core-backend/src/main/java/io/dataease/engine/trans/ExtWhere2Str.java b/core/core-backend/src/main/java/io/dataease/engine/trans/ExtWhere2Str.java
index d96cdaa96e..a05deff48d 100644
--- a/core/core-backend/src/main/java/io/dataease/engine/trans/ExtWhere2Str.java
+++ b/core/core-backend/src/main/java/io/dataease/engine/trans/ExtWhere2Str.java
@@ -5,8 +5,8 @@ import io.dataease.api.dataset.union.model.SQLMeta;
import io.dataease.api.dataset.union.model.SQLObj;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.dataease.engine.constant.SQLConstants;
-import io.dataease.engine.func.scalar.ScalarFunctions;
import io.dataease.engine.utils.Utils;
+import org.apache.calcite.func.scalar.ScalarFunctions;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/core-backend/src/main/java/io/dataease/engine/trans/WhereTree2Str.java b/core/core-backend/src/main/java/io/dataease/engine/trans/WhereTree2Str.java
index 47bd9d9f7b..5087a44a7b 100644
--- a/core/core-backend/src/main/java/io/dataease/engine/trans/WhereTree2Str.java
+++ b/core/core-backend/src/main/java/io/dataease/engine/trans/WhereTree2Str.java
@@ -8,8 +8,8 @@ import io.dataease.api.permissions.dataset.dto.DatasetRowPermissionsTreeObj;
import io.dataease.dto.dataset.DatasetTableFieldDTO;
import io.dataease.engine.constant.ExtFieldConstant;
import io.dataease.engine.constant.SQLConstants;
-import io.dataease.engine.func.scalar.ScalarFunctions;
import io.dataease.engine.utils.Utils;
+import org.apache.calcite.func.scalar.ScalarFunctions;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
diff --git a/core/core-backend/src/main/java/org/apache/calcite/sql/SqlDialect.java b/core/core-backend/src/main/java/org/apache/calcite/sql/SqlDialect.java
deleted file mode 100644
index 2f6cf25ba9..0000000000
--- a/core/core-backend/src/main/java/org/apache/calcite/sql/SqlDialect.java
+++ /dev/null
@@ -1,1811 +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;
-
-import com.google.common.base.Preconditions;
-import com.google.common.base.Suppliers;
-import com.google.common.collect.ImmutableSet;
-import org.apache.calcite.avatica.util.Casing;
-import org.apache.calcite.avatica.util.Quoting;
-import org.apache.calcite.avatica.util.TimeUnit;
-import org.apache.calcite.config.CharLiteralStyle;
-import org.apache.calcite.config.NullCollation;
-import org.apache.calcite.linq4j.function.Experimental;
-import org.apache.calcite.rel.RelFieldCollation;
-import org.apache.calcite.rel.core.JoinRelType;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rel.type.RelDataTypeSystem;
-import org.apache.calcite.rel.type.RelDataTypeSystemImpl;
-import org.apache.calcite.rex.RexCall;
-import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.dialect.JethroDataSqlDialect;
-import org.apache.calcite.sql.fun.SqlInternalOperators;
-import org.apache.calcite.sql.fun.SqlStdOperatorTable;
-import org.apache.calcite.sql.parser.SqlParser;
-import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.type.AbstractSqlType;
-import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.calcite.sql.validate.SqlConformance;
-import org.apache.calcite.sql.validate.SqlConformanceEnum;
-import org.apache.calcite.util.format.FormatModel;
-import org.apache.calcite.util.format.FormatModels;
-import org.checkerframework.checker.nullness.qual.Nullable;
-import org.checkerframework.dataflow.qual.Pure;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.List;
-import java.util.Locale;
-import java.util.Set;
-import java.util.function.Supplier;
-
-import static java.util.Objects.requireNonNull;
-import static org.apache.calcite.util.DateTimeStringUtils.getDateFormatter;
-
-/**
- * SqlDialect
encapsulates the differences between dialects of SQL.
- *
- *
It is used by classes such as {@link SqlWriter} and - * {@link org.apache.calcite.sql.util.SqlBuilder}. - * - *
To add a new {@link SqlDialect} sub-class, extends this class to hold 2 public final - * static member: - *
DEFAULT_CONTEXT
SqlDialect
from a DatabaseMetaData.
- *
- * Does not maintain a reference to the DatabaseMetaData -- or, more - * importantly, to its {@link java.sql.Connection} -- after this call has - * returned. - * - * @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) { - return new SqlDialectFactoryImpl().create(databaseMetaData); - } - - @Deprecated // to be removed before 2.0 - public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, - String identifierQuoteString) { - this(EMPTY_CONTEXT - .withDatabaseProduct(databaseProduct) - .withDatabaseProductName(databaseProductName) - .withIdentifierQuoteString(identifierQuoteString)); - } - - /** - * Creates a SqlDialect. - * - * @param databaseProduct Database product; may be UNKNOWN, never null - * @param databaseProductName Database product name from JDBC driver - * @param identifierQuoteString String to quote identifiers. Null if quoting - * is not supported. If "[", close quote is - * deemed to be "]". - * @param nullCollation Whether NULL values appear first or last - * @deprecated Use {@link #SqlDialect(Context)} - */ - @Deprecated // to be removed before 2.0 - public SqlDialect(DatabaseProduct databaseProduct, String databaseProductName, - String identifierQuoteString, NullCollation nullCollation) { - this(EMPTY_CONTEXT - .withDatabaseProduct(databaseProduct) - .withDatabaseProductName(databaseProductName) - .withIdentifierQuoteString(identifierQuoteString) - .withNullCollation(nullCollation)); - } - - /** - * Creates a SqlDialect. - * - * @param context All the information necessary to create a dialect - */ - public SqlDialect(Context context) { - this.nullCollation = requireNonNull(context.nullCollation()); - this.dataTypeSystem = requireNonNull(context.dataTypeSystem()); - this.databaseProduct = requireNonNull(context.databaseProduct()); - this.literalQuoteString = requireNonNull(context.literalQuoteString()); - this.literalEndQuoteString = requireNonNull(context.literalQuoteString()); - this.literalEscapedQuote = - requireNonNull(context.literalEscapedQuoteString()); - String identifierQuoteString = context.identifierQuoteString(); - if (identifierQuoteString != null) { - identifierQuoteString = identifierQuoteString.trim(); - if (identifierQuoteString.equals("")) { - identifierQuoteString = null; - } - } - this.identifierQuoteString = identifierQuoteString; - this.identifierEndQuoteString = - identifierQuoteString == null ? null - : identifierQuoteString.equals("[") ? "]" - : identifierQuoteString; - this.identifierEscapedQuote = - context.identifierEscapedQuoteString() == null - ? identifierQuoteString == null - ? null - : this.identifierEndQuoteString + this.identifierEndQuoteString - : context.identifierEscapedQuoteString(); - this.unquotedCasing = requireNonNull(context.unquotedCasing()); - this.quotedCasing = requireNonNull(context.quotedCasing()); - this.caseSensitive = context.caseSensitive(); - } - - //~ Methods ---------------------------------------------------------------- - - /** - * Creates an empty context. Use {@link #EMPTY_CONTEXT} to reference the instance. - */ - private static Context emptyContext() { - return new ContextImpl(DatabaseProduct.UNKNOWN, null, null, -1, -1, - "'", "''", null, null, - Casing.UNCHANGED, Casing.TO_UPPER, true, SqlConformanceEnum.DEFAULT, - NullCollation.HIGH, RelDataTypeSystemImpl.DEFAULT, - JethroDataSqlDialect.JethroInfo.EMPTY); - } - - /** - * Converts a product name and version (per the JDBC driver) into a product - * enumeration. - * - * @param productName Product name - * @param productVersion Product version - * @return database product - */ - @Deprecated // to be removed before 2.0 - public static DatabaseProduct getProduct( - String productName, - String productVersion) { - final String upperProductName = - productName.toUpperCase(Locale.ROOT).trim(); - switch (upperProductName) { - case "ACCESS": - return DatabaseProduct.ACCESS; - case "APACHE DERBY": - return DatabaseProduct.DERBY; - case "CLICKHOUSE": - return DatabaseProduct.CLICKHOUSE; - case "DBMS:CLOUDSCAPE": - return DatabaseProduct.DERBY; - case "EXASOL": - return DatabaseProduct.EXASOL; - case "FIREBOLT": - return DatabaseProduct.FIREBOLT; - case "HIVE": - return DatabaseProduct.HIVE; - case "INGRES": - return DatabaseProduct.INGRES; - case "INTERBASE": - return DatabaseProduct.INTERBASE; - case "LUCIDDB": - return DatabaseProduct.LUCIDDB; - case "ORACLE": - return DatabaseProduct.ORACLE; - case "PHOENIX": - return DatabaseProduct.PHOENIX; - case "PRESTO": - case "AWS.ATHENA": - return DatabaseProduct.PRESTO; - case "MYSQL (INFOBRIGHT)": - return DatabaseProduct.INFOBRIGHT; - case "MYSQL": - return DatabaseProduct.MYSQL; - case "REDSHIFT": - return DatabaseProduct.REDSHIFT; - default: - break; - } - // Now the fuzzy matches. - if (productName.startsWith("DB2")) { - return DatabaseProduct.DB2; - } else if (upperProductName.contains("FIREBIRD")) { - return DatabaseProduct.FIREBIRD; - } else if (productName.startsWith("Informix")) { - return DatabaseProduct.INFORMIX; - } else if (upperProductName.contains("NETEZZA")) { - return DatabaseProduct.NETEZZA; - } else if (upperProductName.contains("PARACCEL")) { - return DatabaseProduct.PARACCEL; - } else if (productName.startsWith("HP Neoview")) { - return DatabaseProduct.NEOVIEW; - } else if (upperProductName.contains("POSTGRE")) { - return DatabaseProduct.POSTGRESQL; - } else if (upperProductName.contains("SQL SERVER")) { - return DatabaseProduct.MSSQL; - } else if (upperProductName.contains("SYBASE")) { - return DatabaseProduct.SYBASE; - } else if (upperProductName.contains("TERADATA")) { - return DatabaseProduct.TERADATA; - } else if (upperProductName.contains("HSQL")) { - return DatabaseProduct.HSQLDB; - } else if (upperProductName.contains("H2")) { - return DatabaseProduct.H2; - } else if (upperProductName.contains("VERTICA")) { - return DatabaseProduct.VERTICA; - } else if (upperProductName.contains("GOOGLE BIGQUERY") - || upperProductName.contains("GOOGLE BIG QUERY")) { - return DatabaseProduct.BIG_QUERY; - } else { - return DatabaseProduct.UNKNOWN; - } - } - - /** - * Returns the type system implementation for this dialect. - */ - public RelDataTypeSystem getTypeSystem() { - return dataTypeSystem; - } - - /** - * Encloses an identifier in quotation marks appropriate for the current SQL - * dialect. - * - *
For example, quoteIdentifier("emp")
yields a string
- * containing "emp"
in Oracle, and a string containing
- * [emp]
in Access.
- *
- * @param val Identifier to quote
- * @return Quoted identifier
- */
- public String quoteIdentifier(String val) {
- return quoteIdentifier(new StringBuilder(), val).toString();
- }
-
- /**
- * Encloses an identifier in quotation marks appropriate for the current SQL
- * dialect, writing the result to a {@link StringBuilder}.
- *
- *
For example, For example, {@code "can't run"} becomes {@code "'can''t run'"}.
- */
- public final String quoteStringLiteral(String val) {
- final StringBuilder buf = new StringBuilder();
- quoteStringLiteral(buf, null, val);
- return buf.toString();
- }
-
- /**
- * Appends a string literal to a buffer.
- *
- * @param buf Buffer
- * @param charsetName Character set name, e.g. "utf16", or null
- * @param val String value
- */
- public void quoteStringLiteral(StringBuilder buf, @Nullable String charsetName,
- String val) {
- buf.append(literalQuoteString);
- buf.append(val.replace(literalEndQuoteString, literalEscapedQuote));
- buf.append(literalEndQuoteString);
- }
-
- public void unparseCall(SqlWriter writer, SqlCall call, int leftPrec,
- int rightPrec) {
- SqlOperator operator = call.getOperator();
- switch (call.getKind()) {
- case ROW:
- // Remove the ROW keyword if the dialect does not allow that.
- if (!getConformance().allowExplicitRowValueConstructor()) {
- if (writer.isAlwaysUseParentheses()) {
- // If writer always uses parentheses, it will have started parentheses
- // that we now regret. Use a special variant of the operator that does
- // not print parentheses, so that we can use the ones already started.
- operator = SqlInternalOperators.ANONYMOUS_ROW_NO_PARENTHESES;
- } else {
- // Use an operator that prints "(a, b, c)" rather than
- // "ROW (a, b, c)".
- operator = SqlInternalOperators.ANONYMOUS_ROW;
- }
- }
- // fall through
- default:
- operator.unparse(writer, call, leftPrec, rightPrec);
- }
- }
-
- public void unparseDateTimeLiteral(SqlWriter writer,
- SqlAbstractDateTimeLiteral literal, int leftPrec, int rightPrec) {
- writer.literal(literal.toString());
- }
-
- public void unparseSqlDatetimeArithmetic(SqlWriter writer,
- SqlCall call, SqlKind sqlKind, int leftPrec, int rightPrec) {
- final SqlWriter.Frame frame = writer.startList("(", ")");
- call.operand(0).unparse(writer, leftPrec, rightPrec);
- writer.sep((SqlKind.PLUS == sqlKind) ? "+" : "-");
- call.operand(1).unparse(writer, leftPrec, rightPrec);
- writer.endList(frame);
- // Only two parameters are present normally.
- // Checking parameter count to prevent errors.
- if (call.getOperandList().size() > 2) {
- call.operand(2).unparse(writer, leftPrec, rightPrec);
- }
- }
-
- /**
- * Converts an interval qualifier to a SQL string. The default implementation
- * returns strings such as
- * Such characters can be used unquoted in SQL character literals.
- *
- * @param s String
- * @return Whether string contains any non-7-bit-ASCII characters
- */
- protected static boolean containsNonAscii(String s) {
- for (int i = 0; i < s.length(); i++) {
- char c = s.charAt(i);
- if (c < 32 && c != 10 && c != 13 || c >= 128) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Converts a string into a unicode string literal. For example,
- * For example, in PostgreSQL, this query is legal:
- *
- * but remove the alias {@code e} and it is not:
- *
- * In Oracle, both queries are legal.
- */
- public boolean requiresAliasForFromItems() {
- return false;
- }
-
- /**
- * Returns whether a qualified table in the FROM clause has an implicit alias
- * which consists of just the table name.
- *
- * For example, in {@link DatabaseProduct#ORACLE}
- *
- * is equivalent to
- *
- * and therefore
- *
- * is valid. But {@link DatabaseProduct#DB2} does not have an implicit
- * alias, so the previous query it not valid; you need to write
- *
- * Returns true for all databases except DB2.
- */
- public boolean hasImplicitTableAlias() {
- return true;
- }
-
- /**
- * Converts a timestamp to a SQL timestamp literal, e.g.
- * {@code TIMESTAMP '2009-12-17 12:34:56'}.
- *
- * Timestamp values do not have a time zone. We therefore interpret them
- * as the number of milliseconds after the UTC epoch, and the formatted
- * value is that time in UTC.
- *
- * In particular,
- *
- * returns {@code TIMESTAMP '1970-01-01 00:00:00'}, regardless of the JVM's
- * time zone.
- *
- * @param timestamp Timestamp
- * @return SQL timestamp literal
- */
- public String quoteTimestampLiteral(Timestamp timestamp) {
- final SimpleDateFormat format = getDateFormatter("'TIMESTAMP' ''yyyy-MM-dd HH:mm:ss''");
- return format.format(timestamp);
- }
-
- /**
- * Returns the database this dialect belongs to,
- * {@link SqlDialect.DatabaseProduct#UNKNOWN} if not known, never null.
- *
- * Please be judicious in how you use this method. If you wish to determine
- * whether a dialect has a particular capability or behavior, it is usually
- * better to add a method to SqlDialect and override that method in particular
- * sub-classes of SqlDialect.
- *
- * @return Database product
- * @deprecated To be removed without replacement
- */
- @Deprecated // to be removed before 2.0
- public DatabaseProduct getDatabaseProduct() {
- return databaseProduct;
- }
-
- /**
- * Returns whether the dialect supports character set names as part of a
- * data type, for instance {@code VARCHAR(30) CHARACTER SET `ISO-8859-1`}.
- */
- @Pure
- public boolean supportsCharSet() {
- return true;
- }
-
- /**
- * Returns whether the dialect supports GROUP BY literals.
- *
- * For instance, in {@link DatabaseProduct#REDSHIFT}, the following queries
- * are illegal:
- *
- * If this method returns null, the cast will be omitted. In the default
- * implementation, this is the case for the NULL type, and therefore
- * {@code CAST(NULL AS At least one of {@code offset} and {@code fetch} must be provided.
- *
- * Common options:
- * A dialect that uses "TOP" syntax should override this method to print
- * "TOP(fetch)", and override {@link #unparseOffsetFetch} to no-op.
- *
- * The default implementation of this method is no-op.
- *
- * @param writer Writer
- * @param offset Number of rows to skip before emitting, or null
- * @param fetch Number of rows to fetch, or null
- */
- public void unparseTopN(SqlWriter writer, @Nullable SqlNode offset, @Nullable SqlNode fetch) {
- }
-
- /**
- * Unparses offset/fetch using ANSI standard "OFFSET offset ROWS FETCH NEXT
- * fetch ROWS ONLY" syntax.
- */
- protected static void unparseFetchUsingAnsi(SqlWriter writer, @Nullable SqlNode offset,
- @Nullable SqlNode fetch) {
- Preconditions.checkArgument(fetch != null || offset != null);
- if (offset != null) {
- writer.newlineAndIndent();
- final SqlWriter.Frame offsetFrame =
- writer.startList(SqlWriter.FrameTypeEnum.OFFSET);
- writer.keyword("OFFSET");
- offset.unparse(writer, -1, -1);
- writer.keyword("ROWS");
- writer.endList(offsetFrame);
- }
- if (fetch != null) {
- writer.newlineAndIndent();
- final SqlWriter.Frame fetchFrame =
- writer.startList(SqlWriter.FrameTypeEnum.FETCH);
- writer.keyword("FETCH");
- writer.keyword("NEXT");
- fetch.unparse(writer, -1, -1);
- writer.keyword("ROWS");
- writer.keyword("ONLY");
- writer.endList(fetchFrame);
- }
- }
-
- /**
- * Unparses offset/fetch using "LIMIT fetch OFFSET offset" syntax.
- */
- protected static void unparseFetchUsingLimit(SqlWriter writer, @Nullable SqlNode offset,
- @Nullable SqlNode fetch) {
- Preconditions.checkArgument(fetch != null || offset != null);
- unparseLimit(writer, fetch);
- unparseOffset(writer, offset);
- }
-
- protected static void unparseLimit(SqlWriter writer, @Nullable SqlNode fetch) {
- if (fetch != null) {
- writer.newlineAndIndent();
- final SqlWriter.Frame fetchFrame =
- writer.startList(SqlWriter.FrameTypeEnum.FETCH);
- writer.keyword("LIMIT");
- fetch.unparse(writer, -1, -1);
- writer.endList(fetchFrame);
- }
- }
-
- protected static void unparseOffset(SqlWriter writer, @Nullable SqlNode offset) {
- if (offset != null) {
- writer.newlineAndIndent();
- final SqlWriter.Frame offsetFrame =
- writer.startList(SqlWriter.FrameTypeEnum.OFFSET);
- writer.keyword("OFFSET");
- offset.unparse(writer, -1, -1);
- writer.endList(offsetFrame);
- }
- }
-
- /**
- * Returns a description of the format string used by functions in this
- * dialect.
- *
- * Dialects may need to override this element mapping if they differ from
- *
- * Oracle's format elements. By default, this returns {@link FormatModels#DEFAULT}.
- */
- public FormatModel getFormatModel() {
- return FormatModels.DEFAULT;
- }
-
- /**
- * Returns whether the dialect supports nested aggregations, for instance
- * {@code SELECT SUM(SUM(1)) }.
- */
- public boolean supportsNestedAggregations() {
- return true;
- }
-
- /**
- * Returns whether this dialect supports "WITH ROLLUP" in the "GROUP BY"
- * clause.
- *
- * For instance, in MySQL version 5,
- *
- * is equivalent to standard SQL
- *
- * The "WITH ROLLUP" clause was introduced in MySQL and is not standard
- * SQL.
- *
- * See also {@link #supportsAggregateFunction(SqlKind)} applied to
- * {@link SqlKind#ROLLUP}, which returns true in MySQL 8 and higher.
- */
- public boolean supportsGroupByWithRollup() {
- return false;
- }
-
- /**
- * Returns whether this dialect supports "WITH CUBE" in "GROUP BY" clause.
- */
- public boolean supportsGroupByWithCube() {
- return false;
- }
-
- /**
- * Returns whether this dialect support the specified type of join.
- */
- public boolean supportsJoinType(JoinRelType joinType) {
- return true;
- }
-
- /**
- * Returns how NULL values are sorted if an ORDER BY item does not contain
- * NULLS ASCENDING or NULLS DESCENDING.
- */
- public NullCollation getNullCollation() {
- return nullCollation;
- }
-
- /**
- * Returns whether NULL values are sorted first or last, in this dialect,
- * in an ORDER BY item of a given direction.
- */
- public RelFieldCollation.NullDirection defaultNullDirection(
- RelFieldCollation.Direction direction) {
- switch (direction) {
- case ASCENDING:
- case STRICTLY_ASCENDING:
- return getNullCollation().last(false)
- ? RelFieldCollation.NullDirection.LAST
- : RelFieldCollation.NullDirection.FIRST;
- case DESCENDING:
- case STRICTLY_DESCENDING:
- return getNullCollation().last(true)
- ? RelFieldCollation.NullDirection.LAST
- : RelFieldCollation.NullDirection.FIRST;
- default:
- return RelFieldCollation.NullDirection.UNSPECIFIED;
- }
- }
-
- /**
- * Returns whether the dialect supports VALUES in a sub-query with
- * and an "AS t(column, ...)" values to define column names.
- *
- * Currently, only Oracle does not. For this, we generate "SELECT v0 AS c0,
- * v1 AS c1 ... UNION ALL ...". We may need to refactor this method when we
- * support VALUES for other dialects.
- */
- @Experimental
- public boolean supportsAliasedValues() {
- return true;
- }
-
- /**
- * Returns whether the dialect supports implicit type coercion.
- *
- * Most of the sql dialects support implicit type coercion, so we make this method
- * default return true. For instance, "cast('10' as integer) > 5"
- * can be simplified to "'10' > 5" if the dialect supports implicit type coercion
- * for VARCHAR and INTEGER comparison.
- *
- * For sql dialect that does not support implicit type coercion, such as the BigQuery,
- * we can not convert '10' into INT64 implicitly.
- *
- * Now this method is used for some auxiliary decision when translating some {@link RexCall}s,
- * see SqlImplementor#stripCastFromString for details.
- *
- * @param call the call to make decision
- */
- public boolean supportsImplicitTypeCoercion(RexCall call) {
- final RexNode operand0 = call.getOperands().get(0);
- return SqlTypeUtil.isCharacter(operand0.getType());
- }
-
- /**
- * Returns the name of the system table that has precisely one row.
- * If there is no such table, returns null, and we will generate SELECT with
- * no FROM clause.
- *
- * For {@code VALUES 1},
- * Oracle returns ["DUAL"] and we generate "SELECT 1 FROM DUAL";
- * MySQL returns null and we generate "SELECT 1".
- */
- @Experimental
- public @Nullable List {@code SqlDialect}, {@link SqlParser.Config} and {@link SqlConformance}
- * cover different aspects of the same thing - the dialect of SQL spoken by a
- * database - and this method helps to bridge between them. (The aspects are,
- * respectively, generating SQL to send to a source database, parsing SQL
- * sent to Calcite, and validating queries sent to Calcite. It makes sense to
- * keep them as separate interfaces because they are used by different
- * modules.)
- *
- * The settings copied may differ among dialects, and may change over time,
- * but currently include the following:
- *
- * The base implementation returns its best guess, based upon
- * {@link #databaseProduct}; sub-classes may override.
- */
- public SqlConformance getConformance() {
- switch (databaseProduct) {
- case UNKNOWN:
- case CALCITE:
- return SqlConformanceEnum.DEFAULT;
- case BIG_QUERY:
- return SqlConformanceEnum.BIG_QUERY;
- case MYSQL:
- return SqlConformanceEnum.MYSQL_5;
- case ORACLE:
- return SqlConformanceEnum.ORACLE_10;
- case MSSQL:
- return SqlConformanceEnum.SQL_SERVER_2008;
- default:
- return SqlConformanceEnum.PRAGMATIC_2003;
- }
- }
-
- /**
- * Returns the quoting scheme, or null if the combination of
- * {@link #identifierQuoteString} and {@link #identifierEndQuoteString}
- * does not correspond to any known quoting scheme.
- */
- protected @Nullable Quoting getQuoting() {
- if ("\"".equals(identifierQuoteString)
- && "\"".equals(identifierEndQuoteString)) {
- return Quoting.DOUBLE_QUOTE;
- } else if ("`".equals(identifierQuoteString)
- && "`".equals(identifierEndQuoteString)) {
- return Quoting.BACK_TICK;
- } else if ("[".equals(identifierQuoteString)
- && "]".equals(identifierEndQuoteString)) {
- return Quoting.BRACKET;
- } else {
- return null;
- }
- }
-
- /**
- * Returns how unquoted identifiers are stored.
- */
- public Casing getUnquotedCasing() {
- return unquotedCasing;
- }
-
- /**
- * Returns how quoted identifiers are stored.
- */
- public Casing getQuotedCasing() {
- return quotedCasing;
- }
-
- /**
- * Returns whether matching of identifiers is case-sensitive.
- */
- public boolean isCaseSensitive() {
- return caseSensitive;
- }
-
- /**
- * A few utility functions copied from org.apache.calcite.util.Util. We have
- * copied them because we wish to keep SqlDialect's dependencies to a
- * minimum.
- */
- @Deprecated // to be removed before 2.0
- public static class FakeUtil {
- public static Error newInternal(Throwable e, String s) {
- String message = "Internal error: \u0000" + s;
- AssertionError ae = new AssertionError(message);
- ae.initCause(e);
- return ae;
- }
-
- /**
- * Replaces every occurrence of These values cannot help you distinguish between features that exist
- * in different versions or ports of a database, but they are sufficient
- * to drive a {@code switch} statement if behavior is broadly different
- * between say, MySQL and Oracle.
- *
- * If possible, you should not refer to particular database at all; write
- * extend the dialect to describe the particular capability, for example,
- * whether the database allows expressions to appear in the GROUP BY clause.
- */
- public enum DatabaseProduct {
- ACCESS("Access", "\"", NullCollation.HIGH),
- BIG_QUERY("Google BigQuery", "`", NullCollation.LOW),
- CALCITE("Apache Calcite", "\"", NullCollation.HIGH),
- CLICKHOUSE("ClickHouse", "`", NullCollation.LOW),
- MSSQL("Microsoft SQL Server", "[", NullCollation.HIGH),
- MYSQL("MySQL", "`", NullCollation.LOW),
- ORACLE("Oracle", "\"", NullCollation.HIGH),
- DERBY("Apache Derby", null, NullCollation.HIGH),
- DB2("IBM DB2", null, NullCollation.HIGH),
- EXASOL("Exasol", "\"", NullCollation.LOW),
- FIREBIRD("Firebird", null, NullCollation.HIGH),
- FIREBOLT("Firebolt", "\"", NullCollation.LOW),
- H2("H2", "\"", NullCollation.HIGH),
- HIVE("Apache Hive", null, NullCollation.LOW),
- INFORMIX("Informix", null, NullCollation.HIGH),
- INGRES("Ingres", null, NullCollation.HIGH),
- JETHRO("JethroData", "\"", NullCollation.LOW),
- LUCIDDB("LucidDB", "\"", NullCollation.HIGH),
- INTERBASE("Interbase", null, NullCollation.HIGH),
- PHOENIX("Phoenix", "\"", NullCollation.HIGH),
- POSTGRESQL("PostgreSQL", "\"", NullCollation.HIGH),
- PRESTO("Presto", "\"", NullCollation.LOW),
- NETEZZA("Netezza", "\"", NullCollation.HIGH),
- INFOBRIGHT("Infobright", "`", NullCollation.HIGH),
- NEOVIEW("Neoview", null, NullCollation.HIGH),
- SYBASE("Sybase", null, NullCollation.HIGH),
- TERADATA("Teradata", "\"", NullCollation.HIGH),
- HSQLDB("Hsqldb", null, NullCollation.HIGH),
- VERTICA("Vertica", "\"", NullCollation.HIGH),
- SQLSTREAM("SQLstream", "\"", NullCollation.HIGH),
- SPARK("Spark", null, NullCollation.LOW),
-
- /**
- * Paraccel, now called Actian Matrix. Redshift is based on this, so
- * presumably the dialect capabilities are similar.
- */
- PARACCEL("Paraccel", "\"", NullCollation.HIGH),
- REDSHIFT("Redshift", "\"", NullCollation.HIGH),
- SNOWFLAKE("Snowflake", "\"", NullCollation.HIGH),
-
- /**
- * Placeholder for the unknown database.
- *
- * Its dialect is 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.
- */
- UNKNOWN("Unknown", "`", NullCollation.HIGH);
-
- @SuppressWarnings("ImmutableEnumChecker")
- private final Supplier Since databases have many versions and flavors, this dummy dialect
- * is at best an approximation. If you want exact information, better to
- * use a dialect created from an actual connection's metadata
- * (see {@link SqlDialectFactory#create(java.sql.DatabaseMetaData)}).
- *
- * @return Dialect representing lowest-common-denominator behavior for
- * all versions of this database
- */
- public SqlDialect getDialect() {
- return dialect.get();
- }
- }
-
- /**
- * Information for creating a dialect.
- *
- * It is immutable; to "set" a property, call one of the "with" methods,
- * which returns a new context with the desired property value.
- */
- public interface Context {
- DatabaseProduct databaseProduct();
-
- Context withDatabaseProduct(DatabaseProduct databaseProduct);
-
- @Nullable String databaseProductName();
-
- Context withDatabaseProductName(String databaseProductName);
-
- @Nullable String databaseVersion();
-
- Context withDatabaseVersion(String databaseVersion);
-
- int databaseMajorVersion();
-
- Context withDatabaseMajorVersion(int databaseMajorVersion);
-
- int databaseMinorVersion();
-
- Context withDatabaseMinorVersion(int databaseMinorVersion);
-
- String literalQuoteString();
-
- Context withLiteralQuoteString(String literalQuoteString);
-
- String literalEscapedQuoteString();
-
- Context withLiteralEscapedQuoteString(
- String literalEscapedQuoteString);
-
- @Nullable String identifierQuoteString();
-
- Context withIdentifierQuoteString(@Nullable String identifierQuoteString);
-
- @Nullable String identifierEscapedQuoteString();
-
- Context withIdentifierEscapedQuoteString(
- @Nullable String identifierEscapedQuoteString);
-
- Casing unquotedCasing();
-
- Context withUnquotedCasing(Casing unquotedCasing);
-
- Casing quotedCasing();
-
- Context withQuotedCasing(Casing unquotedCasing);
-
- boolean caseSensitive();
-
- Context withCaseSensitive(boolean caseSensitive);
-
- SqlConformance conformance();
-
- Context withConformance(SqlConformance conformance);
-
- NullCollation nullCollation();
-
- Context withNullCollation(NullCollation nullCollation);
-
- RelDataTypeSystem dataTypeSystem();
-
- Context withDataTypeSystem(RelDataTypeSystem dataTypeSystem);
-
- JethroDataSqlDialect.JethroInfo jethroInfo();
-
- Context withJethroInfo(JethroDataSqlDialect.JethroInfo jethroInfo);
- }
-
- /**
- * Implementation of Context.
- */
- private static class ContextImpl implements Context {
- private final DatabaseProduct databaseProduct;
- private final @Nullable String databaseProductName;
- private final @Nullable String databaseVersion;
- private final int databaseMajorVersion;
- private final int databaseMinorVersion;
- private final String literalQuoteString;
- private final String literalEscapedQuoteString;
- private final @Nullable String identifierQuoteString;
- private final @Nullable String identifierEscapedQuoteString;
- private final Casing unquotedCasing;
- private final Casing quotedCasing;
- private final boolean caseSensitive;
- private final SqlConformance conformance;
- private final NullCollation nullCollation;
- private final RelDataTypeSystem dataTypeSystem;
- private final JethroDataSqlDialect.JethroInfo jethroInfo;
-
- private ContextImpl(DatabaseProduct databaseProduct,
- @Nullable String databaseProductName, @Nullable String databaseVersion,
- int databaseMajorVersion, int databaseMinorVersion,
- String literalQuoteString, String literalEscapedQuoteString,
- @Nullable String identifierQuoteString,
- @Nullable String identifierEscapedQuoteString,
- Casing quotedCasing, Casing unquotedCasing, boolean caseSensitive,
- SqlConformance conformance, NullCollation nullCollation,
- RelDataTypeSystem dataTypeSystem,
- JethroDataSqlDialect.JethroInfo jethroInfo) {
- this.databaseProduct = requireNonNull(databaseProduct, "databaseProduct");
- this.databaseProductName = databaseProductName;
- this.databaseVersion = databaseVersion;
- this.databaseMajorVersion = databaseMajorVersion;
- this.databaseMinorVersion = databaseMinorVersion;
- this.literalQuoteString = literalQuoteString;
- this.literalEscapedQuoteString = literalEscapedQuoteString;
- this.identifierQuoteString = identifierQuoteString;
- this.identifierEscapedQuoteString = identifierEscapedQuoteString;
- this.quotedCasing = requireNonNull(quotedCasing, "quotedCasing");
- this.unquotedCasing = requireNonNull(unquotedCasing, "unquotedCasing");
- this.caseSensitive = caseSensitive;
- this.conformance = requireNonNull(conformance, "conformance");
- this.nullCollation = requireNonNull(nullCollation, "nullCollation");
- this.dataTypeSystem = requireNonNull(dataTypeSystem, "dataTypeSystem");
- this.jethroInfo = requireNonNull(jethroInfo, "jethroInfo");
- }
-
- @Override
- public DatabaseProduct databaseProduct() {
- return databaseProduct;
- }
-
- @Override
- public Context withDatabaseProduct(
- DatabaseProduct databaseProduct) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public @Nullable String databaseProductName() {
- return databaseProductName;
- }
-
- @Override
- public Context withDatabaseProductName(String databaseProductName) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public @Nullable String databaseVersion() {
- return databaseVersion;
- }
-
- @Override
- public Context withDatabaseVersion(String databaseVersion) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public int databaseMajorVersion() {
- return databaseMajorVersion;
- }
-
- @Override
- public Context withDatabaseMajorVersion(int databaseMajorVersion) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public int databaseMinorVersion() {
- return databaseMinorVersion;
- }
-
- @Override
- public Context withDatabaseMinorVersion(int databaseMinorVersion) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public String literalQuoteString() {
- return literalQuoteString;
- }
-
- @Override
- public Context withLiteralQuoteString(String literalQuoteString) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public String literalEscapedQuoteString() {
- return literalEscapedQuoteString;
- }
-
- @Override
- public Context withLiteralEscapedQuoteString(
- String literalEscapedQuoteString) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public @Nullable String identifierQuoteString() {
- return identifierQuoteString;
- }
-
- @Override
- public Context withIdentifierQuoteString(
- @Nullable String identifierQuoteString) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public @Nullable String identifierEscapedQuoteString() {
- return identifierEscapedQuoteString;
- }
-
- @Override
- public Context withIdentifierEscapedQuoteString(
- @Nullable String identifierEscapedQuoteString) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public Casing unquotedCasing() {
- return unquotedCasing;
- }
-
- @Override
- public Context withUnquotedCasing(Casing unquotedCasing) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public Casing quotedCasing() {
- return quotedCasing;
- }
-
- @Override
- public Context withQuotedCasing(Casing quotedCasing) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public boolean caseSensitive() {
- return caseSensitive;
- }
-
- @Override
- public Context withCaseSensitive(boolean caseSensitive) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public SqlConformance conformance() {
- return conformance;
- }
-
- @Override
- public Context withConformance(SqlConformance conformance) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public NullCollation nullCollation() {
- return nullCollation;
- }
-
- @Override
- public Context withNullCollation(
- NullCollation nullCollation) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public RelDataTypeSystem dataTypeSystem() {
- return dataTypeSystem;
- }
-
- @Override
- public Context withDataTypeSystem(RelDataTypeSystem dataTypeSystem) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
-
- @Override
- public JethroDataSqlDialect.JethroInfo jethroInfo() {
- return jethroInfo;
- }
-
- @Override
- public Context withJethroInfo(JethroDataSqlDialect.JethroInfo jethroInfo) {
- return new ContextImpl(databaseProduct, databaseProductName,
- databaseVersion, databaseMajorVersion, databaseMinorVersion,
- literalQuoteString, literalEscapedQuoteString,
- identifierQuoteString, identifierEscapedQuoteString,
- quotedCasing, unquotedCasing, caseSensitive,
- conformance, nullCollation, dataTypeSystem, jethroInfo);
- }
- }
-}
diff --git a/pom.xml b/pom.xml
index 25a84d89b3..c856156989 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
quoteIdentifier("emp")
yields a string
- * containing "emp"
in Oracle, and a string containing
- * [emp]
in Access.
- *
- * @param buf Buffer
- * @param val Identifier to quote
- * @return The buffer
- */
- public StringBuilder quoteIdentifier(
- StringBuilder buf,
- String val) {
- if (identifierQuoteString == null // quoting is not supported
- || identifierEndQuoteString == null
- || identifierEscapedQuote == null
- || !identifierNeedsQuote(val)) {
- buf.append(val);
- } else {
- buf.append(identifierQuoteString);
- buf.append(val.replace(identifierEndQuoteString, identifierEscapedQuote));
- buf.append(identifierEndQuoteString);
- }
- return buf;
- }
-
- /**
- * Quotes a multi-part identifier.
- *
- * @param buf Buffer
- * @param identifiers List of parts of the identifier to quote
- * @return The buffer
- */
- public StringBuilder quoteIdentifier(
- StringBuilder buf,
- ListINTERVAL '1 2:3:4' DAY(4) TO SECOND(4)
.
- */
- public void unparseSqlIntervalQualifier(SqlWriter writer,
- SqlIntervalQualifier qualifier, RelDataTypeSystem typeSystem) {
- final String start = qualifier.timeUnitRange.startUnit.name();
- final int fractionalSecondPrecision =
- qualifier.getFractionalSecondPrecision(typeSystem);
- final int startPrecision = qualifier.getStartPrecision(typeSystem);
- if (qualifier.timeUnitRange.startUnit == TimeUnit.SECOND) {
- if (!qualifier.useDefaultFractionalSecondPrecision()) {
- final SqlWriter.Frame frame = writer.startFunCall(start);
- writer.print(startPrecision);
- writer.sep(",", true);
- writer.print(qualifier.getFractionalSecondPrecision(typeSystem));
- writer.endList(frame);
- } else if (!qualifier.useDefaultStartPrecision()) {
- final SqlWriter.Frame frame = writer.startFunCall(start);
- writer.print(startPrecision);
- writer.endList(frame);
- } else {
- writer.keyword(start);
- }
- } else {
- if (!qualifier.useDefaultStartPrecision()) {
- final SqlWriter.Frame frame = writer.startFunCall(start);
- writer.print(startPrecision);
- writer.endList(frame);
- } else {
- writer.keyword(start);
- }
-
- if (null != qualifier.timeUnitRange.endUnit) {
- writer.keyword("TO");
- final String end = qualifier.timeUnitRange.endUnit.name();
- if ((TimeUnit.SECOND == qualifier.timeUnitRange.endUnit)
- && !qualifier.useDefaultFractionalSecondPrecision()) {
- final SqlWriter.Frame frame = writer.startFunCall(end);
- writer.print(fractionalSecondPrecision);
- writer.endList(frame);
- } else {
- writer.keyword(end);
- }
- }
- }
- }
-
- /**
- * Converts an interval literal to a SQL string. The default implementation
- * returns strings such as
- * INTERVAL '1 2:3:4' DAY(4) TO SECOND(4)
.
- */
- public void unparseSqlIntervalLiteral(SqlWriter writer,
- SqlIntervalLiteral literal, int leftPrec, int rightPrec) {
- SqlIntervalLiteral.IntervalValue interval =
- literal.getValueAs(SqlIntervalLiteral.IntervalValue.class);
- writer.keyword("INTERVAL");
- if (interval.getSign() == -1) {
- writer.print("-");
- }
- writer.literal("'" + interval.getIntervalLiteral() + "'");
- unparseSqlIntervalQualifier(writer, interval.getIntervalQualifier(),
- RelDataTypeSystem.DEFAULT);
- }
-
- /**
- * Converts table scan hints. The default implementation suppresses all hints.
- */
- public void unparseTableScanHints(SqlWriter writer,
- SqlNodeList hints, int leftPrec, int rightPrec) {
- }
-
- /**
- * Returns whether the string contains any characters outside the
- * comfortable 7-bit ASCII range (32 through 127, plus linefeed (10) and
- * carriage return (13)).
- *
- * can't{tab}run\
becomes u'can''t\0009run\\'
.
- */
- public void quoteStringLiteralUnicode(StringBuilder buf, String val) {
- buf.append("u&'");
- for (int i = 0; i < val.length(); i++) {
- char c = val.charAt(i);
- if (c < 32 || c >= 128) {
- buf.append('\\');
- buf.append(HEXITS[(c >> 12) & 0xf]);
- buf.append(HEXITS[(c >> 8) & 0xf]);
- buf.append(HEXITS[(c >> 4) & 0xf]);
- buf.append(HEXITS[c & 0xf]);
- } else if (c == '\'' || c == '\\') {
- buf.append(c);
- buf.append(c);
- } else {
- buf.append(c);
- }
- }
- buf.append("'");
- }
-
- private static final char[] HEXITS = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
- };
-
- /**
- * Converts a string literal back into a string. For example, 'can''t
- * run'
becomes can't run
.
- */
- public @Nullable String unquoteStringLiteral(@Nullable String val) {
- if (val != null
- && val.startsWith(literalQuoteString)
- && val.endsWith(literalEndQuoteString)) {
- final String stripped =
- val.substring(literalQuoteString.length(),
- val.length() - literalEndQuoteString.length());
- return stripped.replace(literalEscapedQuote, literalEndQuoteString);
- }
- return val;
- }
-
- protected boolean allowsAs() {
- return true;
- }
-
- // -- behaviors --
-
- /**
- * Whether a sub-query in the FROM clause must have an alias.
- *
- * {@code SELECT * FROM (SELECT * FROM Emp) As e}
- *
- * {@code SELECT * FROM (SELECT * FROM Emp)}
- *
- * SELECT * FROM sales.emp
- *
- * SELECT * FROM sales.emp AS emp
- *
- * SELECT emp.empno FROM sales.emp
- *
- * SELECT sales.emp.empno FROM sales.emp
- *
- *
- *
- * quoteTimestampLiteral(new Timestamp(0));
- *
- */
- public boolean supportsGroupByLiteral() {
- return true;
- }
-
- public boolean supportsAggregateFunction(SqlKind kind) {
- switch (kind) {
- case COUNT:
- case SUM:
- case SUM0:
- case MIN:
- case MAX:
- return true;
- default:
- break;
- }
- return false;
- }
-
- /**
- * Returns whether this dialect supports APPROX_COUNT_DISTINCT functions.
- */
- public boolean supportsApproxCountDistinct() {
- return false;
- }
-
- /**
- * Returns whether this dialect supports the use of FILTER clauses for
- * aggregate functions. e.g. {@code COUNT(*) FILTER (WHERE a = 2)}.
- */
- public boolean supportsAggregateFunctionFilter() {
- return true;
- }
-
- /**
- * Returns whether this dialect supports window functions (OVER clause).
- */
- public boolean supportsWindowFunctions() {
- return true;
- }
-
- /**
- * Returns whether this dialect supports a given function or operator.
- * It only applies to built-in scalar functions and operators, since
- * user-defined functions and procedures should be read by JdbcSchema.
- */
- public boolean supportsFunction(SqlOperator operator, RelDataType type,
- List{@code
- * select avg(salary)
- * from emp
- * group by true
- *
- * select avg(salary)
- * from emp
- * group by 'a', DATE '2022-01-01'
- * }
null
if no emulation needs to be done.
- *
- * @param node The SqlNode representing the expression
- * @param nullsFirst Whether nulls should come first
- * @param desc Whether the sort direction is
- * {@link RelFieldCollation.Direction#DESCENDING} or
- * {@link RelFieldCollation.Direction#STRICTLY_DESCENDING}
- * @return A SqlNode for null direction emulation or null
if not required
- */
- public @Nullable SqlNode emulateNullDirection(SqlNode node, boolean nullsFirst,
- boolean desc) {
- return null;
- }
-
- public JoinType emulateJoinTypeForCrossJoin() {
- return JoinType.COMMA;
- }
-
- protected @Nullable SqlNode emulateNullDirectionWithIsNull(SqlNode node,
- boolean nullsFirst, boolean desc) {
- // No need for emulation if the nulls will anyways come out the way we want
- // them based on "nullsFirst" and "desc".
- if (nullCollation.isDefaultOrder(nullsFirst, desc)) {
- return null;
- }
-
- node = SqlStdOperatorTable.IS_NULL.createCall(SqlParserPos.ZERO, node);
- if (nullsFirst) {
- node = SqlStdOperatorTable.DESC.createCall(SqlParserPos.ZERO, node);
- }
- return node;
- }
-
- /**
- * Returns whether the dialect supports OFFSET/FETCH clauses
- * introduced by SQL:2008, for instance
- * {@code OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY}.
- * If false, we assume that the dialect supports the alternative syntax
- * {@code LIMIT 20 OFFSET 10}.
- *
- * @deprecated This method is no longer used. To change how the dialect
- * unparses offset/fetch, override the {@link #unparseOffsetFetch} method.
- */
- @Deprecated
- public boolean supportsOffsetFetch() {
- return true;
- }
-
- /**
- * Converts an offset and fetch into SQL.
- *
- *
- *
- *
- * @param writer Writer
- * @param offset Number of rows to skip before emitting, or null
- * @param fetch Number of rows to fetch, or null
- * @see #unparseFetchUsingAnsi(SqlWriter, SqlNode, SqlNode)
- * @see #unparseFetchUsingLimit(SqlWriter, SqlNode, SqlNode)
- */
- public void unparseOffsetFetch(SqlWriter writer, @Nullable SqlNode offset,
- @Nullable SqlNode fetch) {
- unparseFetchUsingAnsi(writer, offset, fetch);
- }
-
- /**
- * Converts a fetch into a "SELECT TOP(fetch)".
- *
- *
- *
- *
- *
- * SELECT deptno, job, COUNT(*) AS c
- * FROM emp
- * GROUP BY deptno, job WITH ROLLUP
- *
- *
- *
- *
- *
- * SELECT deptno, job, COUNT(*) AS c
- * FROM emp
- * GROUP BY ROLLUP(deptno, job)
- * ORDER BY deptno, job
- *
- *
- *
- *
- * @param config Parser configuration builder
- * @return The configuration builder
- */
- public SqlParser.Config configureParser(SqlParser.Config config) {
- final Quoting quoting = getQuoting();
- if (quoting != null) {
- config = config.withQuoting(quoting);
- }
- return config.withQuotedCasing(getQuotedCasing())
- .withUnquotedCasing(getUnquotedCasing())
- .withCaseSensitive(isCaseSensitive())
- .withConformance(getConformance())
- .withCharLiteralStyles(ImmutableSet.of(CharLiteralStyle.STANDARD));
- }
-
- @Deprecated // to be removed before 2.0
- public SqlParser.ConfigBuilder configureParser(
- SqlParser.ConfigBuilder configBuilder) {
- return SqlParser.configBuilder(
- configureParser(configBuilder.build()));
- }
-
- /**
- * Returns the {@link SqlConformance} that matches this dialect.
- *
- * find
in s
with
- * replace
.
- */
- public static String replace(
- String s,
- String find,
- String replace) {
- // let's be optimistic
- int found = s.indexOf(find);
- if (found == -1) {
- return s;
- }
- StringBuilder sb = new StringBuilder(s.length());
- int start = 0;
- for (; ; ) {
- for (; start < found; start++) {
- sb.append(s.charAt(start));
- }
- if (found == s.length()) {
- break;
- }
- sb.append(replace);
- start += find.length();
- found = s.indexOf(find, start);
- if (found == -1) {
- found = s.length();
- }
- }
- return sb.toString();
- }
- }
-
-
- /**
- * 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.
- *
- *