Class SqlDialect
- Direct Known Subclasses:
AccessSqlDialect
,AnsiSqlDialect
,BigQuerySqlDialect
,CalciteSqlDialect
,ClickHouseSqlDialect
,Db2SqlDialect
,DerbySqlDialect
,FirebirdSqlDialect
,H2SqlDialect
,HiveSqlDialect
,HsqldbSqlDialect
,InfobrightSqlDialect
,InformixSqlDialect
,IngresSqlDialect
,InterbaseSqlDialect
,JethroDataSqlDialect
,LucidDbSqlDialect
,MssqlSqlDialect
,MysqlSqlDialect
,NeoviewSqlDialect
,NetezzaSqlDialect
,OracleSqlDialect
,ParaccelSqlDialect
,PhoenixSqlDialect
,PostgresqlSqlDialect
,PrestoSqlDialect
,RedshiftSqlDialect
,SnowflakeSqlDialect
,SparkSqlDialect
,SybaseSqlDialect
,TeradataSqlDialect
,VerticaSqlDialect
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:
- DEFAULT_CONTEXT: a default
SqlDialect.Context
instance, which can be used to customize or extending the dialect if the DEFAULT instance does not meet the requests - DEFAULT: the default
SqlDialect
instance with context properties defined withDEFAULT_CONTEXT
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
SqlDialect.CalendarPolicy
Whether this JDBC driver needs you to pass a Calendar object to methods such asResultSet.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. -
Field Summary
Fields Modifier and Type Field 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 String
identifierEndQuoteString
protected String
identifierEscapedQuote
protected String
identifierQuoteString
protected String
literalEndQuoteString
protected String
literalEscapedQuote
protected String
literalQuoteString
protected static org.slf4j.Logger
LOGGER
protected NullCollation
nullCollation
-
Constructor Summary
Constructors Constructor 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. -
Method Summary
Modifier and Type Method 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 bySqlDialectFactory
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()
SqlNode
emulateNullDirection(SqlNode node, boolean nullsFirst, boolean desc)
Returns the SqlNode for emulating the null direction for the given field ornull
if no emulation needs to be done.protected SqlNode
emulateNullDirectionWithIsNull(SqlNode node, boolean nullsFirst, boolean desc)
SqlDialect.CalendarPolicy
getCalendarPolicy()
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 theSqlConformance
that matches this dialect.SqlDialect.DatabaseProduct
getDatabaseProduct()
Deprecated.To be removed without replacementNullCollation
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 org.apache.calcite.avatica.util.Quoting
getQuoting()
Returns the quoting scheme, or null if the combination ofidentifierQuoteString
andidentifierEndQuoteString
does not correspond to any known quoting scheme.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, String val)
Encloses an identifier in quotation marks appropriate for the current SQL dialect, writing the result to aStringBuilder
.StringBuilder
quoteIdentifier(StringBuilder buf, List<String> identifiers)
Quotes a multi-part identifier.String
quoteStringLiteral(String val)
Converts a string into a string literal.void
quoteStringLiteral(StringBuilder buf, 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
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 instanceVARCHAR(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
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
supportsNestedAggregations()
Returns whether the dialect supports nested aggregations, for instanceSELECT SUM(SUM(1))
.boolean
supportsOffsetFetch()
Deprecated.This method is no longer used.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.protected void
unparseLimit(SqlWriter writer, SqlNode fetch)
protected void
unparseOffset(SqlWriter writer, SqlNode offset)
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.void
unparseTopN(SqlWriter writer, SqlNode offset, SqlNode fetch)
Converts a fetch into a "SELECT TOP(fetch)".String
unquoteStringLiteral(String val)
Converts a string literal back into a string.
-
Field Details
-
LOGGER
protected static final org.slf4j.Logger LOGGER -
EMPTY_CONTEXT
Empty context. -
BUILT_IN_OPERATORS_LIST
Built-in scalar functions and operators common for every dialect. -
identifierQuoteString
-
identifierEndQuoteString
-
identifierEscapedQuote
-
literalQuoteString
-
literalEndQuoteString
-
literalEscapedQuote
-
nullCollation
-
-
Constructor Details
-
SqlDialect
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString)Deprecated. -
SqlDialect
@Deprecated public SqlDialect(SqlDialect.DatabaseProduct databaseProduct, String databaseProductName, String identifierQuoteString, NullCollation nullCollation)Deprecated.Creates a SqlDialect.- Parameters:
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 last
-
SqlDialect
Creates a SqlDialect.- Parameters:
context
- All the information necessary to create a dialect
-
-
Method Details
-
create
Deprecated.Replaced bySqlDialectFactory
Creates aSqlDialect
from a DatabaseMetaData.Does not maintain a reference to the DatabaseMetaData -- or, more importantly, to its
Connection
-- after this call has returned.- Parameters:
databaseMetaData
- used to determine which dialect of SQL to generate
-
getProduct
@Deprecated public static SqlDialect.DatabaseProduct getProduct(String productName, String productVersion)Deprecated.Converts a product name and version (per the JDBC driver) into a product enumeration.- Parameters:
productName
- Product nameproductVersion
- Product version- Returns:
- database product
-
getTypeSystem
Returns the type system implementation for this dialect. -
quoteIdentifier
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.- Parameters:
val
- Identifier to quote- Returns:
- Quoted identifier
-
quoteIdentifier
Encloses an identifier in quotation marks appropriate for the current SQL dialect, writing the result to aStringBuilder
.For example,
quoteIdentifier("emp")
yields a string containing"emp"
in Oracle, and a string containing[emp]
in Access.- Parameters:
buf
- Bufferval
- Identifier to quote- Returns:
- The buffer
-
quoteIdentifier
Quotes a multi-part identifier.- Parameters:
buf
- Bufferidentifiers
- List of parts of the identifier to quote- Returns:
- The buffer
-
identifierNeedsQuote
Returns whether to quote an identifier. By default, all identifiers are quoted. -
quoteStringLiteral
Converts a string into a string literal.For example,
"can't run"
becomes"'can''t run'"
. -
quoteStringLiteral
Appends a string literal to a buffer.- Parameters:
buf
- BuffercharsetName
- Character set name, e.g. "utf16", or nullval
- String value
-
unparseCall
-
unparseDateTimeLiteral
public void unparseDateTimeLiteral(SqlWriter writer, SqlAbstractDateTimeLiteral literal, int leftPrec, int rightPrec) -
unparseSqlDatetimeArithmetic
-
unparseSqlIntervalQualifier
public void unparseSqlIntervalQualifier(SqlWriter writer, SqlIntervalQualifier qualifier, RelDataTypeSystem typeSystem)Converts an interval qualifier to a SQL string. The default implementation returns strings such asINTERVAL '1 2:3:4' DAY(4) TO SECOND(4)
. -
unparseSqlIntervalLiteral
public void unparseSqlIntervalLiteral(SqlWriter writer, SqlIntervalLiteral literal, int leftPrec, int rightPrec)Converts an interval literal to a SQL string. The default implementation returns strings such asINTERVAL '1 2:3:4' DAY(4) TO SECOND(4)
. -
containsNonAscii
Returns whether the string contains any characters outside the comfortable 7-bit ASCII range (32 through 127, plus linefeed (10) and carriage return (13)).Such characters can be used unquoted in SQL character literals.
- Parameters:
s
- String- Returns:
- Whether string contains any non-7-bit-ASCII characters
-
quoteStringLiteralUnicode
Converts a string into a unicode string literal. For example,can't{tab}run\
becomesu'can''t\0009run\\'
. -
unquoteStringLiteral
Converts a string literal back into a string. For example,'can''t run'
becomescan't run
. -
allowsAs
protected boolean allowsAs() -
requiresAliasForFromItems
public boolean requiresAliasForFromItems()Whether a sub-query in the FROM clause must have an alias.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.
-
hasImplicitTableAlias
public boolean hasImplicitTableAlias()Returns whether a qualified table in the FROM clause has an implicit alias which consists of just the table name.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 writeSELECT sales.emp.empno FROM sales.emp
Returns true for all databases except DB2.
-
quoteTimestampLiteral
Converts a timestamp to a SQL timestamp literal, e.g.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.- Parameters:
timestamp
- Timestamp- Returns:
- SQL timestamp literal
-
getDatabaseProduct
Deprecated.To be removed without replacementReturns the database this dialect belongs to,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.
- Returns:
- Database product
-
supportsCharSet
public boolean supportsCharSet()Returns whether the dialect supports character set names as part of a data type, for instanceVARCHAR(30) CHARACTER SET `ISO-8859-1`
. -
supportsAggregateFunction
-
supportsWindowFunctions
public boolean supportsWindowFunctions()Returns whether this dialect supports window functions (OVER clause). -
supportsFunction
public boolean supportsFunction(SqlOperator operator, RelDataType type, List<RelDataType> paramTypes)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. -
getCalendarPolicy
-
supportsDataType
Returns whether this dialect supports a given type. -
getCastSpec
Returns SqlNode for type in "cast(column as type)", which might be different between databases by type name, precision etc.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 asNULL
. -
rewriteSingleValueExpr
Rewrite SINGLE_VALUE into expression based on database variants E.g. HSQLDB, MYSQL, ORACLE, etc -
emulateNullDirection
Returns the SqlNode for emulating the null direction for the given field ornull
if no emulation needs to be done.- Parameters:
node
- The SqlNode representing the expressionnullsFirst
- Whether nulls should come firstdesc
- Whether the sort direction isRelFieldCollation.Direction.DESCENDING
orRelFieldCollation.Direction.STRICTLY_DESCENDING
- Returns:
- A SqlNode for null direction emulation or
null
if not required
-
emulateJoinTypeForCrossJoin
-
emulateNullDirectionWithIsNull
-
supportsOffsetFetch
Deprecated.This method is no longer used. To change how the dialect unparses offset/fetch, override theunparseOffsetFetch(org.apache.calcite.sql.SqlWriter, org.apache.calcite.sql.SqlNode, org.apache.calcite.sql.SqlNode)
method.Returns whether the dialect supports OFFSET/FETCH clauses introduced by SQL:2008, for instanceOFFSET 10 ROWS FETCH NEXT 20 ROWS ONLY
. If false, we assume that the dialect supports the alternative syntaxLIMIT 20 OFFSET 10
. -
unparseOffsetFetch
Converts an offset and fetch into SQL.At least one of
offset
andfetch
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)
- Parameters:
writer
- Writeroffset
- Number of rows to skip before emitting, or nullfetch
- Number of rows to fetch, or null- See Also:
unparseFetchUsingAnsi(SqlWriter, SqlNode, SqlNode)
,unparseFetchUsingLimit(SqlWriter, SqlNode, SqlNode)
-
unparseTopN
Converts a fetch into a "SELECT TOP(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.
- Parameters:
writer
- Writeroffset
- Number of rows to skip before emitting, or nullfetch
- Number of rows to fetch, or null
-
unparseFetchUsingAnsi
Unparses offset/fetch using ANSI standard "OFFSET offset ROWS FETCH NEXT fetch ROWS ONLY" syntax. -
unparseFetchUsingLimit
Unparses offset/fetch using "LIMIT fetch OFFSET offset" syntax. -
unparseLimit
-
unparseOffset
-
supportsNestedAggregations
public boolean supportsNestedAggregations()Returns whether the dialect supports nested aggregations, for instanceSELECT SUM(SUM(1))
. -
supportsGroupByWithRollup
public boolean supportsGroupByWithRollup()Returns whether this dialect supports "WITH ROLLUP" in the "GROUP BY" clause.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 toSqlKind.ROLLUP
, which returns true in MySQL 8 and higher. -
supportsGroupByWithCube
public boolean supportsGroupByWithCube()Returns whether this dialect supports "WITH CUBE" in "GROUP BY" clause. -
getNullCollation
Returns how NULL values are sorted if an ORDER BY item does not contain NULLS ASCENDING or NULLS DESCENDING. -
defaultNullDirection
@Nonnull public 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. -
supportsAliasedValues
public boolean supportsAliasedValues()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.
-
supportsImplicitTypeCoercion
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
RexCall
s, see SqlImplementor#stripCastFromString for details.- Parameters:
call
- the call to make decision
-
getSingleRowTableName
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
VALUES 1
, Oracle returns ["DUAL"] and we generate "SELECT 1 FROM DUAL"; MySQL returns null and we generate "SELECT 1". -
configureParser
Copies settings from this dialect into a parser configuration.SqlDialect
,SqlParser.Config
andSqlConformance
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:
- Parameters:
config
- Parser configuration builder- Returns:
- The configuration builder
-
configureParser
@Deprecated @Nonnull public SqlParser.ConfigBuilder configureParser(SqlParser.ConfigBuilder configBuilder)Deprecated. -
getConformance
Returns theSqlConformance
that matches this dialect.The base implementation returns its best guess, based upon
databaseProduct
; sub-classes may override. -
getQuoting
protected org.apache.calcite.avatica.util.Quoting getQuoting()Returns the quoting scheme, or null if the combination ofidentifierQuoteString
andidentifierEndQuoteString
does not correspond to any known quoting scheme. -
getUnquotedCasing
public org.apache.calcite.avatica.util.Casing getUnquotedCasing()Returns how unquoted identifiers are stored. -
getQuotedCasing
public org.apache.calcite.avatica.util.Casing getQuotedCasing()Returns how quoted identifiers are stored. -
isCaseSensitive
public boolean isCaseSensitive()Returns whether matching of identifiers is case-sensitive.
-