public class SqlDialect extends Object
SqlDialect encapsulates the differences between dialects of SQL.
It is used by classes such as SqlWriter and
SqlBuilder.
To add a new SqlDialect sub-class, extends this class to hold 2 public final
static member:
SqlDialect.Context instance, which can be used to customize
or extending the dialect if the DEFAULT instance does not meet the requestsSqlDialect instance with context properties defined with
DEFAULT_CONTEXT| Modifier and Type | Class and Description |
|---|---|
static class |
SqlDialect.CalendarPolicy
Whether this JDBC driver needs you to pass a Calendar object to methods
such as
ResultSet.getTimestamp(int, java.util.Calendar). |
static interface |
SqlDialect.Context
Information for creating a dialect.
|
static class |
SqlDialect.DatabaseProduct
Rough list of flavors of database.
|
static class |
SqlDialect.FakeUtil
Deprecated.
|
| Modifier and Type | Field and Description |
|---|---|
protected static Set<SqlOperator> |
BUILT_IN_OPERATORS_LIST
Built-in scalar functions and operators common for every dialect.
|
static SqlDialect.Context |
EMPTY_CONTEXT
Empty context.
|
protected @Nullable String |
identifierEndQuoteString |
protected @Nullable String |
identifierEscapedQuote |
protected @Nullable String |
identifierQuoteString |
protected String |
literalEndQuoteString |
protected String |
literalEscapedQuote |
protected String |
literalQuoteString |
protected static org.slf4j.Logger |
LOGGER |
protected NullCollation |
nullCollation |
| Constructor and Description |
|---|
SqlDialect(SqlDialect.Context context)
Creates a SqlDialect.
|
SqlDialect(SqlDialect.DatabaseProduct databaseProduct,
String databaseProductName,
String identifierQuoteString)
Deprecated.
|
SqlDialect(SqlDialect.DatabaseProduct databaseProduct,
String databaseProductName,
String identifierQuoteString,
NullCollation nullCollation)
Deprecated.
|
| Modifier and Type | Method and Description |
|---|---|
protected boolean |
allowsAs() |
SqlParser.Config |
configureParser(SqlParser.Config config)
Copies settings from this dialect into a parser configuration.
|
SqlParser.ConfigBuilder |
configureParser(SqlParser.ConfigBuilder configBuilder)
Deprecated.
|
protected static boolean |
containsNonAscii(String s)
Returns whether the string contains any characters outside the
comfortable 7-bit ASCII range (32 through 127, plus linefeed (10) and
carriage return (13)).
|
static SqlDialect |
create(DatabaseMetaData databaseMetaData)
Deprecated.
Replaced by
SqlDialectFactory |
RelFieldCollation.NullDirection |
defaultNullDirection(RelFieldCollation.Direction direction)
Returns whether NULL values are sorted first or last, in this dialect,
in an ORDER BY item of a given direction.
|
JoinType |
emulateJoinTypeForCrossJoin() |
@Nullable SqlNode |
emulateNullDirection(SqlNode node,
boolean nullsFirst,
boolean desc)
Returns the SqlNode for emulating the null direction for the given field
or
null if no emulation needs to be done. |
protected @Nullable SqlNode |
emulateNullDirectionWithIsNull(SqlNode node,
boolean nullsFirst,
boolean desc) |
SqlDialect.CalendarPolicy |
getCalendarPolicy() |
@Nullable SqlNode |
getCastSpec(RelDataType type)
Returns SqlNode for type in "cast(column as type)", which might be
different between databases by type name, precision etc.
|
SqlConformance |
getConformance()
Returns the
SqlConformance that matches this dialect. |
SqlDialect.DatabaseProduct |
getDatabaseProduct()
Deprecated.
To be removed without replacement
|
NullCollation |
getNullCollation()
Returns how NULL values are sorted if an ORDER BY item does not contain
NULLS ASCENDING or NULLS DESCENDING.
|
static SqlDialect.DatabaseProduct |
getProduct(String productName,
String productVersion)
Deprecated.
|
org.apache.calcite.avatica.util.Casing |
getQuotedCasing()
Returns how quoted identifiers are stored.
|
protected @Nullable org.apache.calcite.avatica.util.Quoting |
getQuoting()
Returns the quoting scheme, or null if the combination of
identifierQuoteString and identifierEndQuoteString
does not correspond to any known quoting scheme. |
@Nullable List<String> |
getSingleRowTableName()
Returns the name of the system table that has precisely one row.
|
RelDataTypeSystem |
getTypeSystem()
Returns the type system implementation for this dialect.
|
org.apache.calcite.avatica.util.Casing |
getUnquotedCasing()
Returns how unquoted identifiers are stored.
|
boolean |
hasImplicitTableAlias()
Returns whether a qualified table in the FROM clause has an implicit alias
which consists of just the table name.
|
protected boolean |
identifierNeedsQuote(String val)
Returns whether to quote an identifier.
|
boolean |
isCaseSensitive()
Returns whether matching of identifiers is case-sensitive.
|
String |
quoteIdentifier(String val)
Encloses an identifier in quotation marks appropriate for the current SQL
dialect.
|
StringBuilder |
quoteIdentifier(StringBuilder buf,
List<String> identifiers)
Quotes a multi-part identifier.
|
StringBuilder |
quoteIdentifier(StringBuilder buf,
String val)
Encloses an identifier in quotation marks appropriate for the current SQL
dialect, writing the result to a
StringBuilder. |
String |
quoteStringLiteral(String val)
Converts a string into a string literal.
|
void |
quoteStringLiteral(StringBuilder buf,
@Nullable String charsetName,
String val)
Appends a string literal to a buffer.
|
void |
quoteStringLiteralUnicode(StringBuilder buf,
String val)
Converts a string into a unicode string literal.
|
String |
quoteTimestampLiteral(Timestamp timestamp)
Converts a timestamp to a SQL timestamp literal, e.g.
|
boolean |
requiresAliasForFromItems()
Whether a sub-query in the FROM clause must have an alias.
|
SqlNode |
rewriteSingleValueExpr(SqlNode aggCall)
Rewrite SINGLE_VALUE into expression based on database variants
E.g.
|
boolean |
supportsAggregateFunction(SqlKind kind) |
boolean |
supportsAggregateFunctionFilter()
Returns whether this dialect supports the use of FILTER clauses for
aggregate functions.
|
boolean |
supportsAliasedValues()
Returns whether the dialect supports VALUES in a sub-query with
and an "AS t(column, ...)" values to define column names.
|
boolean |
supportsApproxCountDistinct()
Returns whether this dialect supports APPROX_COUNT_DISTINCT functions.
|
boolean |
supportsCharSet()
Returns whether the dialect supports character set names as part of a
data type, for instance
VARCHAR(30) CHARACTER SET `ISO-8859-1`. |
boolean |
supportsDataType(RelDataType type)
Returns whether this dialect supports a given type.
|
boolean |
supportsFunction(SqlOperator operator,
RelDataType type,
List<RelDataType> paramTypes)
Returns whether this dialect supports a given function or operator.
|
boolean |
supportsGroupByLiteral()
Returns whether the dialect supports GROUP BY literals.
|
boolean |
supportsGroupByWithCube()
Returns whether this dialect supports "WITH CUBE" in "GROUP BY" clause.
|
boolean |
supportsGroupByWithRollup()
Returns whether this dialect supports "WITH ROLLUP" in the "GROUP BY"
clause.
|
boolean |
supportsImplicitTypeCoercion(RexCall call)
Returns whether the dialect supports implicit type coercion.
|
boolean |
supportsJoinType(JoinRelType joinType)
Returns whether this dialect support the specified type of join.
|
boolean |
supportsNestedAggregations()
Returns whether the dialect supports nested aggregations, for instance
SELECT SUM(SUM(1)) . |
boolean |
supportsOffsetFetch()
Deprecated.
This method is no longer used. To change how the dialect
unparses offset/fetch, override the
unparseOffsetFetch(org.apache.calcite.sql.SqlWriter, org.apache.calcite.sql.SqlNode, org.apache.calcite.sql.SqlNode) method. |
boolean |
supportsWindowFunctions()
Returns whether this dialect supports window functions (OVER clause).
|
void |
unparseCall(SqlWriter writer,
SqlCall call,
int leftPrec,
int rightPrec) |
void |
unparseDateTimeLiteral(SqlWriter writer,
SqlAbstractDateTimeLiteral literal,
int leftPrec,
int rightPrec) |
protected static void |
unparseFetchUsingAnsi(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 |
unparseFetchUsingLimit(SqlWriter writer,
@Nullable SqlNode offset,
@Nullable SqlNode fetch)
Unparses offset/fetch using "LIMIT fetch OFFSET offset" syntax.
|
protected static void |
unparseLimit(SqlWriter writer,
@Nullable SqlNode fetch) |
protected static void |
unparseOffset(SqlWriter writer,
@Nullable SqlNode offset) |
void |
unparseOffsetFetch(SqlWriter writer,
@Nullable SqlNode offset,
@Nullable SqlNode fetch)
Converts an offset and fetch into SQL.
|
void |
unparseSqlDatetimeArithmetic(SqlWriter writer,
SqlCall call,
SqlKind sqlKind,
int leftPrec,
int rightPrec) |
void |
unparseSqlIntervalLiteral(SqlWriter writer,
SqlIntervalLiteral literal,
int leftPrec,
int rightPrec)
Converts an interval literal to a SQL string.
|
void |
unparseSqlIntervalQualifier(SqlWriter writer,
SqlIntervalQualifier qualifier,
RelDataTypeSystem typeSystem)
Converts an interval qualifier to a SQL string.
|
void |
unparseTableScanHints(SqlWriter writer,
SqlNodeList hints,
int leftPrec,
int rightPrec)
Converts table scan hints.
|
void |
unparseTopN(SqlWriter writer,
@Nullable SqlNode offset,
@Nullable SqlNode fetch)
Converts a fetch into a "SELECT TOP(fetch)".
|
@Nullable String |
unquoteStringLiteral(@Nullable String val)
Converts a string literal back into a string.
|
protected static final org.slf4j.Logger LOGGER
public static final SqlDialect.Context EMPTY_CONTEXT
protected static final Set<SqlOperator> BUILT_IN_OPERATORS_LIST
protected final @Nullable String identifierQuoteString
protected final @Nullable String identifierEndQuoteString
protected final @Nullable String identifierEscapedQuote
protected final String literalQuoteString
protected final String literalEndQuoteString
protected final String literalEscapedQuote
protected final NullCollation nullCollation
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString)
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString, NullCollation nullCollation)
SqlDialect(Context)databaseProduct - Database product; may be UNKNOWN, never nulldatabaseProductName - Database product name from JDBC driveridentifierQuoteString - String to quote identifiers. Null if quoting
is not supported. If "[", close quote is
deemed to be "]".nullCollation - Whether NULL values appear first or lastpublic SqlDialect(SqlDialect.Context context)
context - All the information necessary to create a dialect@Deprecated public static SqlDialect create(DatabaseMetaData databaseMetaData)
SqlDialectFactorySqlDialect from a DatabaseMetaData.
Does not maintain a reference to the DatabaseMetaData -- or, more
importantly, to its Connection -- after this call has
returned.
databaseMetaData - used to determine which dialect of SQL to generate@Deprecated public static SqlDialect.DatabaseProduct getProduct(String productName, String productVersion)
productName - Product nameproductVersion - Product versionpublic RelDataTypeSystem getTypeSystem()
public String quoteIdentifier(String val)
For example, quoteIdentifier("emp") yields a string
containing "emp" in Oracle, and a string containing
[emp] in Access.
val - Identifier to quotepublic StringBuilder quoteIdentifier(StringBuilder buf, String val)
StringBuilder.
For example, quoteIdentifier("emp") yields a string
containing "emp" in Oracle, and a string containing
[emp] in Access.
buf - Bufferval - Identifier to quotepublic StringBuilder quoteIdentifier(StringBuilder buf, List<String> identifiers)
buf - Bufferidentifiers - List of parts of the identifier to quoteprotected boolean identifierNeedsQuote(String val)
public final String quoteStringLiteral(String val)
For example, "can't run" becomes "'can''t run'".
public void quoteStringLiteral(StringBuilder buf, @Nullable String charsetName, String val)
buf - BuffercharsetName - Character set name, e.g. "utf16", or nullval - String valuepublic void unparseDateTimeLiteral(SqlWriter writer, SqlAbstractDateTimeLiteral literal, int leftPrec, int rightPrec)
public void unparseSqlDatetimeArithmetic(SqlWriter writer, SqlCall call, SqlKind sqlKind, int leftPrec, int rightPrec)
public void unparseSqlIntervalQualifier(SqlWriter writer, SqlIntervalQualifier qualifier, RelDataTypeSystem typeSystem)
INTERVAL '1 2:3:4' DAY(4) TO SECOND(4).public void unparseSqlIntervalLiteral(SqlWriter writer, SqlIntervalLiteral literal, int leftPrec, int rightPrec)
INTERVAL '1 2:3:4' DAY(4) TO SECOND(4).public void unparseTableScanHints(SqlWriter writer, SqlNodeList hints, int leftPrec, int rightPrec)
protected static boolean containsNonAscii(String s)
Such characters can be used unquoted in SQL character literals.
s - Stringpublic void quoteStringLiteralUnicode(StringBuilder buf, String val)
can't{tab}run\ becomes u'can''t\0009run\\'.public @Nullable String unquoteStringLiteral(@Nullable String val)
'can''t
run' becomes can't run.protected boolean allowsAs()
public boolean requiresAliasForFromItems()
For example, in PostgreSQL, this query is legal:
SELECT * FROM (SELECT * FROM Emp) As e
but remove the alias e and it is not:
SELECT * FROM (SELECT * FROM Emp)
In Oracle, both queries are legal.
public boolean hasImplicitTableAlias()
For example, in SqlDialect.DatabaseProduct.ORACLE
SELECT * FROM sales.emp
is equivalent to
SELECT * FROM sales.emp AS emp
and therefore
SELECT emp.empno FROM sales.emp
is valid. But SqlDialect.DatabaseProduct.DB2 does not have an implicit
alias, so the previous query it not valid; you need to write
SELECT sales.emp.empno FROM sales.emp
Returns true for all databases except DB2.
public String quoteTimestampLiteral(Timestamp timestamp)
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,
quoteTimestampLiteral(new Timestamp(0));
returns TIMESTAMP '1970-01-01 00:00:00', regardless of the JVM's
time zone.
timestamp - Timestamp@Deprecated public SqlDialect.DatabaseProduct getDatabaseProduct()
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.
@Pure public boolean supportsCharSet()
VARCHAR(30) CHARACTER SET `ISO-8859-1`.public boolean supportsGroupByLiteral()
For instance, in SqlDialect.DatabaseProduct.REDSHIFT, the following queries are illegal.
select avg(salary)
from emp
group by true
select avg(salary)
from emp
group by 'a', DATE '2022-01-01'
public boolean supportsAggregateFunction(SqlKind kind)
public boolean supportsApproxCountDistinct()
public boolean supportsAggregateFunctionFilter()
COUNT(*) FILTER (WHERE a = 2).public boolean supportsWindowFunctions()
public boolean supportsFunction(SqlOperator operator, RelDataType type, List<RelDataType> paramTypes)
public SqlDialect.CalendarPolicy getCalendarPolicy()
public boolean supportsDataType(RelDataType type)
public @Nullable SqlNode getCastSpec(RelDataType type)
If this method returns null, the cast will be omitted. In the default
implementation, this is the case for the NULL type, and therefore
CAST(NULL AS <nulltype>) is rendered as NULL.
public SqlNode rewriteSingleValueExpr(SqlNode aggCall)
public @Nullable SqlNode emulateNullDirection(SqlNode node, boolean nullsFirst, boolean desc)
null if no emulation needs to be done.node - The SqlNode representing the expressionnullsFirst - Whether nulls should come firstdesc - Whether the sort direction is
RelFieldCollation.Direction#DESCENDING or
RelFieldCollation.Direction#STRICTLY_DESCENDINGnull if not requiredpublic JoinType emulateJoinTypeForCrossJoin()
protected @Nullable SqlNode emulateNullDirectionWithIsNull(SqlNode node, boolean nullsFirst, boolean desc)
@Deprecated public boolean supportsOffsetFetch()
unparseOffsetFetch(org.apache.calcite.sql.SqlWriter, org.apache.calcite.sql.SqlNode, org.apache.calcite.sql.SqlNode) method.OFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY.
If false, we assume that the dialect supports the alternative syntax
LIMIT 20 OFFSET 10.public void unparseOffsetFetch(SqlWriter writer, @Nullable SqlNode offset, @Nullable SqlNode fetch)
At least one of offset and fetch must be provided.
Common options:
OFFSET offset ROWS FETCH NEXT fetch ROWS ONLY
(ANSI standard SQL, Oracle, PostgreSQL, and the default)
LIMIT fetch OFFSET offset (Apache Hive, MySQL, Redshift)
writer - Writeroffset - Number of rows to skip before emitting, or nullfetch - Number of rows to fetch, or nullunparseFetchUsingAnsi(SqlWriter, SqlNode, SqlNode),
unparseFetchUsingLimit(SqlWriter, SqlNode, SqlNode)public void unparseTopN(SqlWriter writer, @Nullable SqlNode offset, @Nullable SqlNode fetch)
A dialect that uses "TOP" syntax should override this method to print
"TOP(fetch)", and override unparseOffsetFetch(org.apache.calcite.sql.SqlWriter, org.apache.calcite.sql.SqlNode, org.apache.calcite.sql.SqlNode) to no-op.
The default implementation of this method is no-op.
writer - Writeroffset - Number of rows to skip before emitting, or nullfetch - Number of rows to fetch, or nullprotected static void unparseFetchUsingAnsi(SqlWriter writer, @Nullable SqlNode offset, @Nullable SqlNode fetch)
protected static void unparseFetchUsingLimit(SqlWriter writer, @Nullable SqlNode offset, @Nullable SqlNode fetch)
public boolean supportsNestedAggregations()
SELECT SUM(SUM(1)) .public boolean supportsGroupByWithRollup()
For instance, in MySQL version 5,
SELECT deptno, job, COUNT(*) AS c
FROM emp
GROUP BY deptno, job WITH ROLLUP
is equivalent to standard SQL
SELECT deptno, job, COUNT(*) AS c
FROM emp
GROUP BY ROLLUP(deptno, job)
ORDER BY deptno, job
The "WITH ROLLUP" clause was introduced in MySQL and is not standard SQL.
See also supportsAggregateFunction(SqlKind) applied to
SqlKind.ROLLUP, which returns true in MySQL 8 and higher.
public boolean supportsGroupByWithCube()
public boolean supportsJoinType(JoinRelType joinType)
public NullCollation getNullCollation()
public RelFieldCollation.NullDirection defaultNullDirection(RelFieldCollation.Direction direction)
public boolean supportsAliasedValues()
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.
public boolean supportsImplicitTypeCoercion(RexCall call)
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 RexCalls,
see SqlImplementor#stripCastFromString for details.
call - the call to make decisionpublic @Nullable List<String> getSingleRowTableName()
For VALUES 1,
Oracle returns ["DUAL"] and we generate "SELECT 1 FROM DUAL";
MySQL returns null and we generate "SELECT 1".
public SqlParser.Config configureParser(SqlParser.Config config)
SqlDialect, SqlParser.Config and 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:
config - Parser configuration builder@Deprecated public SqlParser.ConfigBuilder configureParser(SqlParser.ConfigBuilder configBuilder)
public SqlConformance getConformance()
SqlConformance that matches this dialect.
The base implementation returns its best guess, based upon
databaseProduct; sub-classes may override.
protected @Nullable org.apache.calcite.avatica.util.Quoting getQuoting()
identifierQuoteString and identifierEndQuoteString
does not correspond to any known quoting scheme.public org.apache.calcite.avatica.util.Casing getUnquotedCasing()
public org.apache.calcite.avatica.util.Casing getQuotedCasing()
public boolean isCaseSensitive()
Copyright © 2012-2022 Apache Software Foundation. All Rights Reserved.