public class SqlDialect
extends java.lang.Object
SqlDialect
encapsulates the differences between dialects of SQL.
It is used by classes such as SqlWriter
and
SqlBuilder
.
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.
|
private static class |
SqlDialect.ContextImpl
Implementation of Context.
|
static class |
SqlDialect.DatabaseProduct
Rough list of flavors of database.
|
static class |
SqlDialect.FakeUtil
A few utility functions copied from org.apache.calcite.util.Util.
|
Modifier and Type | Field and Description |
---|---|
protected static java.util.Set<SqlOperator> |
BUILT_IN_OPERATORS_LIST
Built-in scalar functions and operators common for every dialect.
|
static SqlDialect |
CALCITE
Deprecated.
Use
CalciteSqlDialect.DEFAULT instead. |
private boolean |
caseSensitive |
private SqlDialect.DatabaseProduct |
databaseProduct |
private RelDataTypeSystem |
dataTypeSystem |
static SqlDialect |
DUMMY
Deprecated.
Use
AnsiSqlDialect.DEFAULT instead. |
static SqlDialect.Context |
EMPTY_CONTEXT
Empty context.
|
private static char[] |
HEXITS |
private java.lang.String |
identifierEndQuoteString |
private java.lang.String |
identifierEscapedQuote |
private java.lang.String |
identifierQuoteString |
protected static org.slf4j.Logger |
LOGGER |
protected NullCollation |
nullCollation |
private org.apache.calcite.avatica.util.Casing |
quotedCasing |
private org.apache.calcite.avatica.util.Casing |
unquotedCasing |
Constructor and Description |
---|
SqlDialect(SqlDialect.Context context)
Creates a SqlDialect.
|
SqlDialect(SqlDialect.DatabaseProduct databaseProduct,
java.lang.String databaseProductName,
java.lang.String identifierQuoteString)
Deprecated.
|
SqlDialect(SqlDialect.DatabaseProduct databaseProduct,
java.lang.String databaseProductName,
java.lang.String identifierQuoteString,
NullCollation nullCollation)
Deprecated.
|
Modifier and Type | Method and Description |
---|---|
protected boolean |
allowsAs() |
SqlParser.ConfigBuilder |
configureParser(SqlParser.ConfigBuilder configBuilder)
Copies settings from this dialect into a parser configuration.
|
private static boolean |
containsNonAscii(java.lang.String s)
Returns whether the string contains any characters outside the
comfortable 7-bit ASCII range (32 through 127).
|
static SqlDialect |
create(java.sql.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.
|
protected static SqlDialect.Context |
emptyContext()
Creates an empty context.
|
JoinType |
emulateJoinTypeForCrossJoin() |
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 SqlNode |
emulateNullDirectionWithIsNull(SqlNode node,
boolean nullsFirst,
boolean desc) |
SqlDialect.CalendarPolicy |
getCalendarPolicy() |
SqlNode |
getCastSpec(RelDataType type) |
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(java.lang.String productName,
java.lang.String productVersion)
Deprecated.
|
org.apache.calcite.avatica.util.Casing |
getQuotedCasing()
Returns how quoted identifiers are stored.
|
protected 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. |
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.
|
boolean |
isCaseSensitive()
Returns whether matching of identifiers is case-sensitive.
|
java.lang.String |
quoteIdentifier(java.lang.String val)
Encloses an identifier in quotation marks appropriate for the current SQL
dialect.
|
java.lang.StringBuilder |
quoteIdentifier(java.lang.StringBuilder buf,
java.util.List<java.lang.String> identifiers)
Quotes a multi-part identifier.
|
java.lang.StringBuilder |
quoteIdentifier(java.lang.StringBuilder buf,
java.lang.String val)
Encloses an identifier in quotation marks appropriate for the current SQL
dialect, writing the result to a
StringBuilder . |
java.lang.String |
quoteStringLiteral(java.lang.String val)
Converts a string into a string literal.
|
void |
quoteStringLiteralUnicode(java.lang.StringBuilder buf,
java.lang.String val)
Converts a string into a unicode string literal.
|
java.lang.String |
quoteTimestampLiteral(java.sql.Timestamp timestamp)
Converts a timestamp to a SQL timestamp literal, e.g.
|
protected boolean |
requiresAliasForFromItems() |
SqlNode |
rewriteSingleValueExpr(SqlNode aggCall)
Rewrite SINGLE_VALUE into expression based on database variants
E.g.
|
boolean |
supportsAggregateFunction(SqlKind kind) |
boolean |
supportsAliasedValues()
Returns whether the dialect supports VALUES in a sub-query with
and an "AS t(column, ...)" values to define column names.
|
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 |
supportsFunction(SqlOperator operator,
RelDataType type,
java.util.List<RelDataType> paramTypes)
Returns whether this dialect supports a given function or operator.
|
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 |
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 void |
unparseFetchUsingAnsi(SqlWriter writer,
SqlNode offset,
SqlNode fetch)
Unparses offset/fetch using ANSI standard "OFFSET offset ROWS FETCH NEXT
fetch ROWS ONLY" syntax.
|
protected void |
unparseFetchUsingLimit(SqlWriter writer,
SqlNode offset,
SqlNode fetch)
Unparses offset/fetch using "LIMIT fetch OFFSET offset" syntax.
|
void |
unparseOffsetFetch(SqlWriter writer,
SqlNode offset,
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.
|
java.lang.String |
unquoteStringLiteral(java.lang.String val)
Converts a string literal back into a string.
|
protected static final org.slf4j.Logger LOGGER
public static final SqlDialect.Context EMPTY_CONTEXT
@Deprecated public static final SqlDialect DUMMY
AnsiSqlDialect.DEFAULT
instead.@Deprecated public static final SqlDialect CALCITE
CalciteSqlDialect.DEFAULT
instead.protected static final java.util.Set<SqlOperator> BUILT_IN_OPERATORS_LIST
private final java.lang.String identifierQuoteString
private final java.lang.String identifierEndQuoteString
private final java.lang.String identifierEscapedQuote
private final SqlDialect.DatabaseProduct databaseProduct
protected final NullCollation nullCollation
private final RelDataTypeSystem dataTypeSystem
private final org.apache.calcite.avatica.util.Casing unquotedCasing
private final org.apache.calcite.avatica.util.Casing quotedCasing
private final boolean caseSensitive
private static final char[] HEXITS
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, java.lang.String databaseProductName, java.lang.String identifierQuoteString)
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, java.lang.String databaseProductName, java.lang.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(java.sql.DatabaseMetaData databaseMetaData)
SqlDialectFactory
SqlDialect
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 generateprotected static SqlDialect.Context emptyContext()
EMPTY_CONTEXT
if possible.@Deprecated public static SqlDialect.DatabaseProduct getProduct(java.lang.String productName, java.lang.String productVersion)
productName
- Product nameproductVersion
- Product versionpublic RelDataTypeSystem getTypeSystem()
public java.lang.String quoteIdentifier(java.lang.String val)
For example, quoteIdentifier("emp")
yields a string
containing "emp"
in Oracle, and a string containing
[emp]
in Access.
val
- Identifier to quotepublic java.lang.StringBuilder quoteIdentifier(java.lang.StringBuilder buf, java.lang.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 java.lang.StringBuilder quoteIdentifier(java.lang.StringBuilder buf, java.util.List<java.lang.String> identifiers)
buf
- Bufferidentifiers
- List of parts of the identifier to quotepublic java.lang.String quoteStringLiteral(java.lang.String val)
can't
run
becomes 'can''t run'
.public 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)
.private static boolean containsNonAscii(java.lang.String s)
s
- Stringpublic void quoteStringLiteralUnicode(java.lang.StringBuilder buf, java.lang.String val)
can't{tab}run\
becomes u'can''t\0009run\\'
.public java.lang.String unquoteStringLiteral(java.lang.String val)
'can''t
run'
becomes can't run
.protected boolean allowsAs()
protected boolean requiresAliasForFromItems()
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 java.lang.String quoteTimestampLiteral(java.sql.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.
public boolean supportsCharSet()
VARCHAR(30) CHARACTER SET `ISO-8859-1`
.public boolean supportsAggregateFunction(SqlKind kind)
public boolean supportsWindowFunctions()
public boolean supportsFunction(SqlOperator operator, RelDataType type, java.util.List<RelDataType> paramTypes)
public SqlDialect.CalendarPolicy getCalendarPolicy()
public SqlNode getCastSpec(RelDataType type)
public SqlNode rewriteSingleValueExpr(SqlNode aggCall)
public 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_DESCENDING
null
if not requiredpublic JoinType emulateJoinTypeForCrossJoin()
protected 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, SqlNode offset, 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)
protected final void unparseFetchUsingAnsi(SqlWriter writer, SqlNode offset, SqlNode fetch)
protected final void unparseFetchUsingLimit(SqlWriter writer, SqlNode offset, 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 NullCollation getNullCollation()
@Nonnull 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.
@Nonnull public SqlParser.ConfigBuilder configureParser(SqlParser.ConfigBuilder configBuilder)
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:
configBuilder
- Parser configuration builder@Nonnull public SqlConformance getConformance()
SqlConformance
that matches this dialect.
The base implementation returns its best guess, based upon
databaseProduct
; sub-classes may override.
protected 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–2019 The Apache Software Foundation. All rights reserved.