/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Red Hat Inc.
 *
 * This copyrighted material is made available to anyone wishing to use, modify,
 * copy, or redistribute it subject to the terms and conditions of the GNU
 * Lesser General Public License, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this distribution; if not, write to:
 * Free Software Foundation, Inc.
 * 51 Franklin Street, Fifth Floor
 * Boston, MA  02110-1301  USA
 */
package org.hibernate.dialect;

import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NullPrecedence;
import org.hibernate.ScrollMode;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CastFunction;
import org.hibernate.dialect.function.SQLFunction;
import org.hibernate.dialect.function.SQLFunctionTemplate;
import org.hibernate.dialect.function.StandardAnsiSqlAggregationFunctions;
import org.hibernate.dialect.function.StandardSQLFunction;
import org.hibernate.dialect.lock.LockingStrategy;
import org.hibernate.dialect.lock.OptimisticForceIncrementLockingStrategy;
import org.hibernate.dialect.lock.OptimisticLockingStrategy;
import org.hibernate.dialect.lock.PessimisticForceIncrementLockingStrategy;
import org.hibernate.dialect.lock.PessimisticReadSelectLockingStrategy;
import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
import org.hibernate.dialect.lock.SelectLockingStrategy;
import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.exception.spi.ConversionContext;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtracter;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.id.TableHiLoGenerator;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.io.StreamCopier;
import org.hibernate.mapping.Column;
import org.hibernate.metamodel.spi.TypeContributions;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
import org.jboss.logging.Logger;

import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.CallableStatement;
import java.sql.Clob;
import java.sql.NClob;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

Represents a dialect of SQL implemented by a particular RDBMS. Subclasses implement Hibernate compatibility with different systems. Subclasses should provide a public default constructor that register a set of type mappings and default Hibernate properties. Subclasses should be immutable.
Author:Gavin King, David Channon
/** * Represents a dialect of SQL implemented by a particular RDBMS. Subclasses implement Hibernate compatibility * with different systems. Subclasses should provide a public default constructor that register a set of type * mappings and default Hibernate properties. Subclasses should be immutable. * * @author Gavin King, David Channon */
@SuppressWarnings("deprecation") public abstract class Dialect implements ConversionContext { private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, Dialect.class.getName() );
Defines a default batch size constant
/** * Defines a default batch size constant */
public static final String DEFAULT_BATCH_SIZE = "15";
Defines a "no batching" batch size constant
/** * Defines a "no batching" batch size constant */
public static final String NO_BATCH = "0";
Characters used as opening for quoting SQL identifiers
/** * Characters used as opening for quoting SQL identifiers */
public static final String QUOTE = "`\"[";
Characters used as closing for quoting SQL identifiers
/** * Characters used as closing for quoting SQL identifiers */
public static final String CLOSED_QUOTE = "`\"]"; private final TypeNames typeNames = new TypeNames(); private final TypeNames hibernateTypeNames = new TypeNames(); private final Properties properties = new Properties(); private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>(); private final Set<String> sqlKeywords = new HashSet<String>(); private final UniqueDelegate uniqueDelegate; // constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ protected Dialect() { LOG.usingDialect( this ); StandardAnsiSqlAggregationFunctions.primeFunctionMap( sqlFunctions ); // standard sql92 functions (can be overridden by subclasses) registerFunction( "substring", new SQLFunctionTemplate( StandardBasicTypes.STRING, "substring(?1, ?2, ?3)" ) ); registerFunction( "locate", new SQLFunctionTemplate( StandardBasicTypes.INTEGER, "locate(?1, ?2, ?3)" ) ); registerFunction( "trim", new SQLFunctionTemplate( StandardBasicTypes.STRING, "trim(?1 ?2 ?3 ?4)" ) ); registerFunction( "length", new StandardSQLFunction( "length", StandardBasicTypes.INTEGER ) ); registerFunction( "bit_length", new StandardSQLFunction( "bit_length", StandardBasicTypes.INTEGER ) ); registerFunction( "coalesce", new StandardSQLFunction( "coalesce" ) ); registerFunction( "nullif", new StandardSQLFunction( "nullif" ) ); registerFunction( "abs", new StandardSQLFunction( "abs" ) ); registerFunction( "mod", new StandardSQLFunction( "mod", StandardBasicTypes.INTEGER) ); registerFunction( "sqrt", new StandardSQLFunction( "sqrt", StandardBasicTypes.DOUBLE) ); registerFunction( "upper", new StandardSQLFunction("upper") ); registerFunction( "lower", new StandardSQLFunction("lower") ); registerFunction( "cast", new CastFunction() ); registerFunction( "extract", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(?1 ?2 ?3)") ); //map second/minute/hour/day/month/year to ANSI extract(), override on subclasses registerFunction( "second", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(second from ?1)") ); registerFunction( "minute", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(minute from ?1)") ); registerFunction( "hour", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(hour from ?1)") ); registerFunction( "day", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(day from ?1)") ); registerFunction( "month", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(month from ?1)") ); registerFunction( "year", new SQLFunctionTemplate(StandardBasicTypes.INTEGER, "extract(year from ?1)") ); registerFunction( "str", new SQLFunctionTemplate(StandardBasicTypes.STRING, "cast(?1 as char)") ); registerColumnType( Types.BIT, "bit" ); registerColumnType( Types.BOOLEAN, "boolean" ); registerColumnType( Types.TINYINT, "tinyint" ); registerColumnType( Types.SMALLINT, "smallint" ); registerColumnType( Types.INTEGER, "integer" ); registerColumnType( Types.BIGINT, "bigint" ); registerColumnType( Types.FLOAT, "float($p)" ); registerColumnType( Types.DOUBLE, "double precision" ); registerColumnType( Types.NUMERIC, "numeric($p,$s)" ); registerColumnType( Types.REAL, "real" ); registerColumnType( Types.DATE, "date" ); registerColumnType( Types.TIME, "time" ); registerColumnType( Types.TIMESTAMP, "timestamp" ); registerColumnType( Types.VARBINARY, "bit varying($l)" ); registerColumnType( Types.LONGVARBINARY, "bit varying($l)" ); registerColumnType( Types.BLOB, "blob" ); registerColumnType( Types.CHAR, "char($l)" ); registerColumnType( Types.VARCHAR, "varchar($l)" ); registerColumnType( Types.LONGVARCHAR, "varchar($l)" ); registerColumnType( Types.CLOB, "clob" ); registerColumnType( Types.NCHAR, "nchar($l)" ); registerColumnType( Types.NVARCHAR, "nvarchar($l)" ); registerColumnType( Types.LONGNVARCHAR, "nvarchar($l)" ); registerColumnType( Types.NCLOB, "nclob" ); // register hibernate types for default use in scalar sqlquery type auto detection registerHibernateType( Types.BIGINT, StandardBasicTypes.BIG_INTEGER.getName() ); registerHibernateType( Types.BINARY, StandardBasicTypes.BINARY.getName() ); registerHibernateType( Types.BIT, StandardBasicTypes.BOOLEAN.getName() ); registerHibernateType( Types.BOOLEAN, StandardBasicTypes.BOOLEAN.getName() ); registerHibernateType( Types.CHAR, StandardBasicTypes.CHARACTER.getName() ); registerHibernateType( Types.CHAR, 1, StandardBasicTypes.CHARACTER.getName() ); registerHibernateType( Types.CHAR, 255, StandardBasicTypes.STRING.getName() ); registerHibernateType( Types.DATE, StandardBasicTypes.DATE.getName() ); registerHibernateType( Types.DOUBLE, StandardBasicTypes.DOUBLE.getName() ); registerHibernateType( Types.FLOAT, StandardBasicTypes.FLOAT.getName() ); registerHibernateType( Types.INTEGER, StandardBasicTypes.INTEGER.getName() ); registerHibernateType( Types.SMALLINT, StandardBasicTypes.SHORT.getName() ); registerHibernateType( Types.TINYINT, StandardBasicTypes.BYTE.getName() ); registerHibernateType( Types.TIME, StandardBasicTypes.TIME.getName() ); registerHibernateType( Types.TIMESTAMP, StandardBasicTypes.TIMESTAMP.getName() ); registerHibernateType( Types.VARCHAR, StandardBasicTypes.STRING.getName() ); registerHibernateType( Types.VARBINARY, StandardBasicTypes.BINARY.getName() ); registerHibernateType( Types.LONGVARCHAR, StandardBasicTypes.TEXT.getName() ); registerHibernateType( Types.LONGVARBINARY, StandardBasicTypes.IMAGE.getName() ); registerHibernateType( Types.NUMERIC, StandardBasicTypes.BIG_DECIMAL.getName() ); registerHibernateType( Types.DECIMAL, StandardBasicTypes.BIG_DECIMAL.getName() ); registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() ); registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() ); registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() ); uniqueDelegate = new DefaultUniqueDelegate( this ); }
Get an instance of the dialect specified by the current System properties.
Throws:
Returns:The specified Dialect
/** * Get an instance of the dialect specified by the current <tt>System</tt> properties. * * @return The specified Dialect * @throws HibernateException If no dialect was specified, or if it could not be instantiated. */
public static Dialect getDialect() throws HibernateException { return instantiateDialect( Environment.getProperties().getProperty( Environment.DIALECT ) ); }
Get an instance of the dialect specified by the given properties or by the current System properties.
Params:
  • props – The properties to use for finding the dialect class to use.
Throws:
Returns:The specified Dialect
/** * Get an instance of the dialect specified by the given properties or by * the current <tt>System</tt> properties. * * @param props The properties to use for finding the dialect class to use. * @return The specified Dialect * @throws HibernateException If no dialect was specified, or if it could not be instantiated. */
public static Dialect getDialect(Properties props) throws HibernateException { final String dialectName = props.getProperty( Environment.DIALECT ); if ( dialectName == null ) { return getDialect(); } return instantiateDialect( dialectName ); } private static Dialect instantiateDialect(String dialectName) throws HibernateException { if ( dialectName == null ) { throw new HibernateException( "The dialect was not set. Set the property hibernate.dialect." ); } try { return (Dialect) ReflectHelper.classForName( dialectName ).newInstance(); } catch ( ClassNotFoundException cnfe ) { throw new HibernateException( "Dialect class not found: " + dialectName ); } catch ( Exception e ) { throw new HibernateException( "Could not instantiate given dialect class: " + dialectName, e ); } }
Retrieve a set of default Hibernate properties for this database.
Returns:a set of Hibernate properties
/** * Retrieve a set of default Hibernate properties for this database. * * @return a set of Hibernate properties */
public final Properties getDefaultProperties() { return properties; } @Override public String toString() { return getClass().getName(); } // database type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows the Dialect to contribute additional types
Params:
  • typeContributions – Callback to contribute the types
  • serviceRegistry – The service registry
/** * Allows the Dialect to contribute additional types * * @param typeContributions Callback to contribute the types * @param serviceRegistry The service registry */
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { // by default, nothing to do }
Get the name of the database type associated with the given Types typecode.
Params:
  • code – The Types typecode
Throws:
Returns:the database type name
/** * Get the name of the database type associated with the given * {@link java.sql.Types} typecode. * * @param code The {@link java.sql.Types} typecode * @return the database type name * @throws HibernateException If no mapping was specified for that type. */
public String getTypeName(int code) throws HibernateException { final String result = typeNames.get( code ); if ( result == null ) { throw new HibernateException( "No default type mapping for (java.sql.Types) " + code ); } return result; }
Get the name of the database type associated with the given Types typecode with the given storage specification parameters.
Params:
  • code – The Types typecode
  • length – The datatype length
  • precision – The datatype precision
  • scale – The datatype scale
Throws:
Returns:the database type name
/** * Get the name of the database type associated with the given * {@link java.sql.Types} typecode with the given storage specification * parameters. * * @param code The {@link java.sql.Types} typecode * @param length The datatype length * @param precision The datatype precision * @param scale The datatype scale * @return the database type name * @throws HibernateException If no mapping was specified for that type. */
public String getTypeName(int code, long length, int precision, int scale) throws HibernateException { final String result = typeNames.get( code, length, precision, scale ); if ( result == null ) { throw new HibernateException( String.format( "No type mapping for java.sql.Types code: %s, length: %s", code, length ) ); } return result; }
Get the name of the database type appropriate for casting operations (via the CAST() SQL function) for the given Types typecode.
Params:
  • code – The Types typecode
Returns:The database type name
/** * Get the name of the database type appropriate for casting operations * (via the CAST() SQL function) for the given {@link java.sql.Types} typecode. * * @param code The {@link java.sql.Types} typecode * @return The database type name */
public String getCastTypeName(int code) { return getTypeName( code, Column.DEFAULT_LENGTH, Column.DEFAULT_PRECISION, Column.DEFAULT_SCALE ); }
Return an expression casting the value to the specified type
Params:
  • value – The value to cast
  • jdbcTypeCode – The JDBC type code to cast to
  • length – The type length
  • precision – The type precision
  • scale – The type scale
Returns:The cast expression
/** * Return an expression casting the value to the specified type * * @param value The value to cast * @param jdbcTypeCode The JDBC type code to cast to * @param length The type length * @param precision The type precision * @param scale The type scale * * @return The cast expression */
public String cast(String value, int jdbcTypeCode, int length, int precision, int scale) { if ( jdbcTypeCode == Types.CHAR ) { return "cast(" + value + " as char(" + length + "))"; } else { return "cast(" + value + "as " + getTypeName( jdbcTypeCode, length, precision, scale ) + ")"; } }
Return an expression casting the value to the specified type. Simply calls cast(String, int, int, int, int) passing Column.DEFAULT_PRECISION and Column.DEFAULT_SCALE as the precision/scale.
Params:
  • value – The value to cast
  • jdbcTypeCode – The JDBC type code to cast to
  • length – The type length
Returns:The cast expression
/** * Return an expression casting the value to the specified type. Simply calls * {@link #cast(String, int, int, int, int)} passing {@link Column#DEFAULT_PRECISION} and * {@link Column#DEFAULT_SCALE} as the precision/scale. * * @param value The value to cast * @param jdbcTypeCode The JDBC type code to cast to * @param length The type length * * @return The cast expression */
public String cast(String value, int jdbcTypeCode, int length) { return cast( value, jdbcTypeCode, length, Column.DEFAULT_PRECISION, Column.DEFAULT_SCALE ); }
Return an expression casting the value to the specified type. Simply calls cast(String, int, int, int, int) passing Column.DEFAULT_LENGTH as the length
Params:
  • value – The value to cast
  • jdbcTypeCode – The JDBC type code to cast to
  • precision – The type precision
  • scale – The type scale
Returns:The cast expression
/** * Return an expression casting the value to the specified type. Simply calls * {@link #cast(String, int, int, int, int)} passing {@link Column#DEFAULT_LENGTH} as the length * * @param value The value to cast * @param jdbcTypeCode The JDBC type code to cast to * @param precision The type precision * @param scale The type scale * * @return The cast expression */
public String cast(String value, int jdbcTypeCode, int precision, int scale) { return cast( value, jdbcTypeCode, Column.DEFAULT_LENGTH, precision, scale ); }
Subclasses register a type name for the given type code and maximum column length. $l in the type name with be replaced by the column length (if appropriate).
Params:
  • code – The Types typecode
  • capacity – The maximum length of database type
  • name – The database type name
/** * Subclasses register a type name for the given type code and maximum * column length. <tt>$l</tt> in the type name with be replaced by the * column length (if appropriate). * * @param code The {@link java.sql.Types} typecode * @param capacity The maximum length of database type * @param name The database type name */
protected void registerColumnType(int code, long capacity, String name) { typeNames.put( code, capacity, name ); }
Subclasses register a type name for the given type code. $l in the type name with be replaced by the column length (if appropriate).
Params:
  • code – The Types typecode
  • name – The database type name
/** * Subclasses register a type name for the given type code. <tt>$l</tt> in * the type name with be replaced by the column length (if appropriate). * * @param code The {@link java.sql.Types} typecode * @param name The database type name */
protected void registerColumnType(int code, String name) { typeNames.put( code, name ); }
Allows the dialect to override a SqlTypeDescriptor.

If the passed sqlTypeDescriptor allows itself to be remapped (per SqlTypeDescriptor.canBeRemapped()), then this method uses getSqlTypeDescriptorOverride to get an optional override based on the SQL code returned by SqlTypeDescriptor.getSqlType().

If this dialect does not provide an override or if the sqlTypeDescriptor doe not allow itself to be remapped, then this method simply returns the original passed sqlTypeDescriptor
Params:
Throws:
See Also:
Returns:The SqlTypeDescriptor that should be used for this dialect; if there is no override, then original sqlTypeDescriptor is returned.
/** * Allows the dialect to override a {@link SqlTypeDescriptor}. * <p/> * If the passed {@code sqlTypeDescriptor} allows itself to be remapped (per * {@link org.hibernate.type.descriptor.sql.SqlTypeDescriptor#canBeRemapped()}), then this method uses * {@link #getSqlTypeDescriptorOverride} to get an optional override based on the SQL code returned by * {@link SqlTypeDescriptor#getSqlType()}. * <p/> * If this dialect does not provide an override or if the {@code sqlTypeDescriptor} doe not allow itself to be * remapped, then this method simply returns the original passed {@code sqlTypeDescriptor} * * @param sqlTypeDescriptor The {@link SqlTypeDescriptor} to override * @return The {@link SqlTypeDescriptor} that should be used for this dialect; * if there is no override, then original {@code sqlTypeDescriptor} is returned. * @throws IllegalArgumentException if {@code sqlTypeDescriptor} is null. * * @see #getSqlTypeDescriptorOverride */
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { if ( sqlTypeDescriptor == null ) { throw new IllegalArgumentException( "sqlTypeDescriptor is null" ); } if ( ! sqlTypeDescriptor.canBeRemapped() ) { return sqlTypeDescriptor; } final SqlTypeDescriptor overridden = getSqlTypeDescriptorOverride( sqlTypeDescriptor.getSqlType() ); return overridden == null ? sqlTypeDescriptor : overridden; }
Returns the SqlTypeDescriptor that should be used to handle the given JDBC type code. Returns null if there is no override.
Params:
  • sqlCode – A Types constant indicating the SQL column type
Returns:The SqlTypeDescriptor to use as an override, or null if there is no override.
/** * Returns the {@link SqlTypeDescriptor} that should be used to handle the given JDBC type code. Returns * {@code null} if there is no override. * * @param sqlCode A {@link Types} constant indicating the SQL column type * @return The {@link SqlTypeDescriptor} to use as an override, or {@code null} if there is no override. */
protected SqlTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) { SqlTypeDescriptor descriptor; switch ( sqlCode ) { case Types.CLOB: { descriptor = useInputStreamToInsertBlob() ? ClobTypeDescriptor.STREAM_BINDING : null; break; } default: { descriptor = null; break; } } return descriptor; }
The legacy behavior of Hibernate. LOBs are not processed by merge
/** * The legacy behavior of Hibernate. LOBs are not processed by merge */
@SuppressWarnings( {"UnusedDeclaration"}) protected static final LobMergeStrategy LEGACY_LOB_MERGE_STRATEGY = new LobMergeStrategy() { @Override public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) { return target; } @Override public Clob mergeClob(Clob original, Clob target, SessionImplementor session) { return target; } @Override public NClob mergeNClob(NClob original, NClob target, SessionImplementor session) { return target; } };
Merge strategy based on transferring contents based on streams.
/** * Merge strategy based on transferring contents based on streams. */
@SuppressWarnings( {"UnusedDeclaration"}) protected static final LobMergeStrategy STREAM_XFER_LOB_MERGE_STRATEGY = new LobMergeStrategy() { @Override public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) { if ( original != target ) { try { // the BLOB just read during the load phase of merge final OutputStream connectedStream = target.setBinaryStream( 1L ); // the BLOB from the detached state final InputStream detachedStream = original.getBinaryStream(); StreamCopier.copy( detachedStream, connectedStream ); return target; } catch (SQLException e ) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge BLOB data" ); } } else { return NEW_LOCATOR_LOB_MERGE_STRATEGY.mergeBlob( original, target, session ); } } @Override public Clob mergeClob(Clob original, Clob target, SessionImplementor session) { if ( original != target ) { try { // the CLOB just read during the load phase of merge final OutputStream connectedStream = target.setAsciiStream( 1L ); // the CLOB from the detached state final InputStream detachedStream = original.getAsciiStream(); StreamCopier.copy( detachedStream, connectedStream ); return target; } catch (SQLException e ) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge CLOB data" ); } } else { return NEW_LOCATOR_LOB_MERGE_STRATEGY.mergeClob( original, target, session ); } } @Override public NClob mergeNClob(NClob original, NClob target, SessionImplementor session) { if ( original != target ) { try { // the NCLOB just read during the load phase of merge final OutputStream connectedStream = target.setAsciiStream( 1L ); // the NCLOB from the detached state final InputStream detachedStream = original.getAsciiStream(); StreamCopier.copy( detachedStream, connectedStream ); return target; } catch (SQLException e ) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge NCLOB data" ); } } else { return NEW_LOCATOR_LOB_MERGE_STRATEGY.mergeNClob( original, target, session ); } } };
Merge strategy based on creating a new LOB locator.
/** * Merge strategy based on creating a new LOB locator. */
protected static final LobMergeStrategy NEW_LOCATOR_LOB_MERGE_STRATEGY = new LobMergeStrategy() { @Override public Blob mergeBlob(Blob original, Blob target, SessionImplementor session) { if ( original == null && target == null ) { return null; } try { final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session ); return original == null ? lobCreator.createBlob( ArrayHelper.EMPTY_BYTE_ARRAY ) : lobCreator.createBlob( original.getBinaryStream(), original.length() ); } catch (SQLException e) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge BLOB data" ); } } @Override public Clob mergeClob(Clob original, Clob target, SessionImplementor session) { if ( original == null && target == null ) { return null; } try { final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session ); return original == null ? lobCreator.createClob( "" ) : lobCreator.createClob( original.getCharacterStream(), original.length() ); } catch (SQLException e) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge CLOB data" ); } } @Override public NClob mergeNClob(NClob original, NClob target, SessionImplementor session) { if ( original == null && target == null ) { return null; } try { final LobCreator lobCreator = session.getFactory().getJdbcServices().getLobCreator( session ); return original == null ? lobCreator.createNClob( "" ) : lobCreator.createNClob( original.getCharacterStream(), original.length() ); } catch (SQLException e) { throw session.getFactory().getSQLExceptionHelper().convert( e, "unable to merge NCLOB data" ); } } }; public LobMergeStrategy getLobMergeStrategy() { return NEW_LOCATOR_LOB_MERGE_STRATEGY; } // hibernate type mapping support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get the name of the Hibernate Type associated with the given Types type code.
Params:
  • code – The Types type code
Throws:
Returns:The Hibernate Type name.
/** * Get the name of the Hibernate {@link org.hibernate.type.Type} associated with the given * {@link java.sql.Types} type code. * * @param code The {@link java.sql.Types} type code * @return The Hibernate {@link org.hibernate.type.Type} name. * @throws HibernateException If no mapping was specified for that type. */
@SuppressWarnings( {"UnusedDeclaration"}) public String getHibernateTypeName(int code) throws HibernateException { final String result = hibernateTypeNames.get( code ); if ( result == null ) { throw new HibernateException( "No Hibernate type mapping for java.sql.Types code: " + code ); } return result; }
Get the name of the Hibernate Type associated with the given Types typecode with the given storage specification parameters.
Params:
  • code – The Types typecode
  • length – The datatype length
  • precision – The datatype precision
  • scale – The datatype scale
Throws:
Returns:The Hibernate Type name.
/** * Get the name of the Hibernate {@link org.hibernate.type.Type} associated * with the given {@link java.sql.Types} typecode with the given storage * specification parameters. * * @param code The {@link java.sql.Types} typecode * @param length The datatype length * @param precision The datatype precision * @param scale The datatype scale * @return The Hibernate {@link org.hibernate.type.Type} name. * @throws HibernateException If no mapping was specified for that type. */
public String getHibernateTypeName(int code, int length, int precision, int scale) throws HibernateException { final String result = hibernateTypeNames.get( code, length, precision, scale ); if ( result == null ) { throw new HibernateException( String.format( "No Hibernate type mapping for type [code=%s, length=%s]", code, length ) ); } return result; }
Registers a Hibernate Type name for the given Types type code and maximum column length.
Params:
  • code – The Types typecode
  • capacity – The maximum length of database type
  • name – The Hibernate Type name
/** * Registers a Hibernate {@link org.hibernate.type.Type} name for the given * {@link java.sql.Types} type code and maximum column length. * * @param code The {@link java.sql.Types} typecode * @param capacity The maximum length of database type * @param name The Hibernate {@link org.hibernate.type.Type} name */
protected void registerHibernateType(int code, long capacity, String name) { hibernateTypeNames.put( code, capacity, name); }
Registers a Hibernate Type name for the given Types type code.
Params:
  • code – The Types typecode
  • name – The Hibernate Type name
/** * Registers a Hibernate {@link org.hibernate.type.Type} name for the given * {@link java.sql.Types} type code. * * @param code The {@link java.sql.Types} typecode * @param name The Hibernate {@link org.hibernate.type.Type} name */
protected void registerHibernateType(int code, String name) { hibernateTypeNames.put( code, name); } // function support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ protected void registerFunction(String name, SQLFunction function) { // HHH-7721: SQLFunctionRegistry expects all lowercase. Enforce, // just in case a user's customer dialect uses mixed cases. sqlFunctions.put( name.toLowerCase(Locale.ROOT), function ); }
Retrieves a map of the dialect's registered functions (functionName => SQLFunction).
Returns:The map of registered functions.
/** * Retrieves a map of the dialect's registered functions * (functionName => {@link org.hibernate.dialect.function.SQLFunction}). * * @return The map of registered functions. */
public final Map<String, SQLFunction> getFunctions() { return sqlFunctions; } // keyword support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ protected void registerKeyword(String word) { sqlKeywords.add( word ); } public Set<String> getKeywords() { return sqlKeywords; } // native identifier generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The class (which implements IdentifierGenerator) which acts as this dialects native generation strategy.

Comes into play whenever the user specifies the native generator.
Returns:The native generator class.
/** * The class (which implements {@link org.hibernate.id.IdentifierGenerator}) * which acts as this dialects native generation strategy. * <p/> * Comes into play whenever the user specifies the native generator. * * @return The native generator class. */
public Class getNativeIdentifierGeneratorClass() { if ( supportsIdentityColumns() ) { return IdentityGenerator.class; } else if ( supportsSequences() ) { return SequenceGenerator.class; } else { return TableHiLoGenerator.class; } } // IDENTITY support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support identity column key generation?
Returns:True if IDENTITY columns are supported; false otherwise.
/** * Does this dialect support identity column key generation? * * @return True if IDENTITY columns are supported; false otherwise. */
public boolean supportsIdentityColumns() { return false; }
Does the dialect support some form of inserting and selecting the generated IDENTITY value all in the same statement.
Returns:True if the dialect supports selecting the just generated IDENTITY in the insert statement.
/** * Does the dialect support some form of inserting and selecting * the generated IDENTITY value all in the same statement. * * @return True if the dialect supports selecting the just * generated IDENTITY in the insert statement. */
public boolean supportsInsertSelectIdentity() { return false; }
Whether this dialect have an Identity clause added to the data type or a completely separate identity data type
Returns:boolean
/** * Whether this dialect have an Identity clause added to the data type or a * completely separate identity data type * * @return boolean */
public boolean hasDataTypeInIdentityColumn() { return true; }
Provided we supportsInsertSelectIdentity, then attach the "select identity" clause to the insert statement.

Note, if supportsInsertSelectIdentity == false then the insert-string should be returned without modification.
Params:
  • insertString – The insert command
Returns:The insert command with any necessary identity select clause attached.
/** * Provided we {@link #supportsInsertSelectIdentity}, then attach the * "select identity" clause to the insert statement. * <p/> * Note, if {@link #supportsInsertSelectIdentity} == false then * the insert-string should be returned without modification. * * @param insertString The insert command * @return The insert command with any necessary identity select * clause attached. */
public String appendIdentitySelectToInsert(String insertString) { return insertString; }
Get the select command to use to retrieve the last generated IDENTITY value for a particular table
Params:
  • table – The table into which the insert was done
  • column – The PK column.
  • type – The Types type code.
Throws:
Returns:The appropriate select command
/** * Get the select command to use to retrieve the last generated IDENTITY * value for a particular table * * @param table The table into which the insert was done * @param column The PK column. * @param type The {@link java.sql.Types} type code. * @return The appropriate select command * @throws MappingException If IDENTITY generation is not supported. */
public String getIdentitySelectString(String table, String column, int type) throws MappingException { return getIdentitySelectString(); }
Get the select command to use to retrieve the last generated IDENTITY value.
Throws:
Returns:The appropriate select command
/** * Get the select command to use to retrieve the last generated IDENTITY * value. * * @return The appropriate select command * @throws MappingException If IDENTITY generation is not supported. */
protected String getIdentitySelectString() throws MappingException { throw new MappingException( getClass().getName() + " does not support identity key generation" ); }
The syntax used during DDL to define a column as being an IDENTITY of a particular type.
Params:
  • type – The Types type code.
Throws:
Returns:The appropriate DDL fragment.
/** * The syntax used during DDL to define a column as being an IDENTITY of * a particular type. * * @param type The {@link java.sql.Types} type code. * @return The appropriate DDL fragment. * @throws MappingException If IDENTITY generation is not supported. */
public String getIdentityColumnString(int type) throws MappingException { return getIdentityColumnString(); }
The syntax used during DDL to define a column as being an IDENTITY.
Throws:
Returns:The appropriate DDL fragment.
/** * The syntax used during DDL to define a column as being an IDENTITY. * * @return The appropriate DDL fragment. * @throws MappingException If IDENTITY generation is not supported. */
protected String getIdentityColumnString() throws MappingException { throw new MappingException( getClass().getName() + " does not support identity key generation" ); }
The keyword used to insert a generated value into an identity column (or null). Need if the dialect does not support inserts that specify no column values.
Returns:The appropriate keyword.
/** * The keyword used to insert a generated value into an identity column (or null). * Need if the dialect does not support inserts that specify no column values. * * @return The appropriate keyword. */
public String getIdentityInsertString() { return null; } // SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support sequences?
Returns:True if sequences supported; false otherwise.
/** * Does this dialect support sequences? * * @return True if sequences supported; false otherwise. */
public boolean supportsSequences() { return false; }
Does this dialect support "pooled" sequences. Not aware of a better name for this. Essentially can we specify the initial and increment values?
See Also:
Returns:True if such "pooled" sequences are supported; false otherwise.
/** * Does this dialect support "pooled" sequences. Not aware of a better * name for this. Essentially can we specify the initial and increment values? * * @return True if such "pooled" sequences are supported; false otherwise. * @see #getCreateSequenceStrings(String, int, int) * @see #getCreateSequenceString(String, int, int) */
public boolean supportsPooledSequences() { return false; }
Generate the appropriate select statement to to retrieve the next value of a sequence.

This should be a "stand alone" select statement.
Params:
  • sequenceName – the name of the sequence
Throws:
Returns:String The "nextval" select string.
/** * Generate the appropriate select statement to to retrieve the next value * of a sequence. * <p/> * This should be a "stand alone" select statement. * * @param sequenceName the name of the sequence * @return String The "nextval" select string. * @throws MappingException If sequences are not supported. */
public String getSequenceNextValString(String sequenceName) throws MappingException { throw new MappingException( getClass().getName() + " does not support sequences" ); }
Generate the select expression fragment that will retrieve the next value of a sequence as part of another (typically DML) statement.

This differs from getSequenceNextValString(String) in that this should return an expression usable within another statement.
Params:
  • sequenceName – the name of the sequence
Throws:
Returns:The "nextval" fragment.
/** * Generate the select expression fragment that will retrieve the next * value of a sequence as part of another (typically DML) statement. * <p/> * This differs from {@link #getSequenceNextValString(String)} in that this * should return an expression usable within another statement. * * @param sequenceName the name of the sequence * @return The "nextval" fragment. * @throws MappingException If sequences are not supported. */
public String getSelectSequenceNextValString(String sequenceName) throws MappingException { throw new MappingException( getClass().getName() + " does not support sequences" ); }
The multiline script used to create a sequence.
Params:
  • sequenceName – The name of the sequence
Throws:
Returns:The sequence creation commands
Deprecated:Use getCreateSequenceString(String, int, int) instead
/** * The multiline script used to create a sequence. * * @param sequenceName The name of the sequence * @return The sequence creation commands * @throws MappingException If sequences are not supported. * @deprecated Use {@link #getCreateSequenceString(String, int, int)} instead */
@Deprecated public String[] getCreateSequenceStrings(String sequenceName) throws MappingException { return new String[] { getCreateSequenceString( sequenceName ) }; }
An optional multi-line form for databases which supportsPooledSequences().
Params:
  • sequenceName – The name of the sequence
  • initialValue – The initial value to apply to 'create sequence' statement
  • incrementSize – The increment value to apply to 'create sequence' statement
Throws:
Returns:The sequence creation commands
/** * An optional multi-line form for databases which {@link #supportsPooledSequences()}. * * @param sequenceName The name of the sequence * @param initialValue The initial value to apply to 'create sequence' statement * @param incrementSize The increment value to apply to 'create sequence' statement * @return The sequence creation commands * @throws MappingException If sequences are not supported. */
public String[] getCreateSequenceStrings(String sequenceName, int initialValue, int incrementSize) throws MappingException { return new String[] { getCreateSequenceString( sequenceName, initialValue, incrementSize ) }; }
Typically dialects which support sequences can create a sequence with a single command. This is convenience form of getCreateSequenceStrings to help facilitate that.

Dialects which support sequences and can create a sequence in a single command need *only* override this method. Dialects which support sequences but require multiple commands to create a sequence should instead override getCreateSequenceStrings.
Params:
  • sequenceName – The name of the sequence
Throws:
Returns:The sequence creation command
/** * Typically dialects which support sequences can create a sequence * with a single command. This is convenience form of * {@link #getCreateSequenceStrings} to help facilitate that. * <p/> * Dialects which support sequences and can create a sequence in a * single command need *only* override this method. Dialects * which support sequences but require multiple commands to create * a sequence should instead override {@link #getCreateSequenceStrings}. * * @param sequenceName The name of the sequence * @return The sequence creation command * @throws MappingException If sequences are not supported. */
protected String getCreateSequenceString(String sequenceName) throws MappingException { throw new MappingException( getClass().getName() + " does not support sequences" ); }
Overloaded form of getCreateSequenceString(String), additionally taking the initial value and increment size to be applied to the sequence definition.

The default definition is to suffix getCreateSequenceString(String) with the string: " start with {initialValue} increment by {incrementSize}" where {initialValue} and {incrementSize} are replacement placeholders. Generally dialects should only need to override this method if different key phrases are used to apply the allocation information.
Params:
  • sequenceName – The name of the sequence
  • initialValue – The initial value to apply to 'create sequence' statement
  • incrementSize – The increment value to apply to 'create sequence' statement
Throws:
Returns:The sequence creation command
/** * Overloaded form of {@link #getCreateSequenceString(String)}, additionally * taking the initial value and increment size to be applied to the sequence * definition. * </p> * The default definition is to suffix {@link #getCreateSequenceString(String)} * with the string: " start with {initialValue} increment by {incrementSize}" where * {initialValue} and {incrementSize} are replacement placeholders. Generally * dialects should only need to override this method if different key phrases * are used to apply the allocation information. * * @param sequenceName The name of the sequence * @param initialValue The initial value to apply to 'create sequence' statement * @param incrementSize The increment value to apply to 'create sequence' statement * @return The sequence creation command * @throws MappingException If sequences are not supported. */
protected String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) throws MappingException { if ( supportsPooledSequences() ) { return getCreateSequenceString( sequenceName ) + " start with " + initialValue + " increment by " + incrementSize; } throw new MappingException( getClass().getName() + " does not support pooled sequences" ); }
The multiline script used to drop a sequence.
Params:
  • sequenceName – The name of the sequence
Throws:
Returns:The sequence drop commands
/** * The multiline script used to drop a sequence. * * @param sequenceName The name of the sequence * @return The sequence drop commands * @throws MappingException If sequences are not supported. */
public String[] getDropSequenceStrings(String sequenceName) throws MappingException { return new String[]{getDropSequenceString( sequenceName )}; }
Typically dialects which support sequences can drop a sequence with a single command. This is convenience form of getDropSequenceStrings to help facilitate that.

Dialects which support sequences and can drop a sequence in a single command need *only* override this method. Dialects which support sequences but require multiple commands to drop a sequence should instead override getDropSequenceStrings.
Params:
  • sequenceName – The name of the sequence
Throws:
Returns:The sequence drop commands
/** * Typically dialects which support sequences can drop a sequence * with a single command. This is convenience form of * {@link #getDropSequenceStrings} to help facilitate that. * <p/> * Dialects which support sequences and can drop a sequence in a * single command need *only* override this method. Dialects * which support sequences but require multiple commands to drop * a sequence should instead override {@link #getDropSequenceStrings}. * * @param sequenceName The name of the sequence * @return The sequence drop commands * @throws MappingException If sequences are not supported. */
protected String getDropSequenceString(String sequenceName) throws MappingException { throw new MappingException( getClass().getName() + " does not support sequences" ); }
Get the select command used retrieve the names of all sequences.
See Also:
Returns:The select command; or null if sequences are not supported.
/** * Get the select command used retrieve the names of all sequences. * * @return The select command; or null if sequences are not supported. * @see org.hibernate.tool.hbm2ddl.SchemaUpdate */
public String getQuerySequencesString() { return null; } // GUID support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get the command used to select a GUID from the underlying database.

Optional operation.
Returns:The appropriate command.
/** * Get the command used to select a GUID from the underlying database. * <p/> * Optional operation. * * @return The appropriate command. */
public String getSelectGUIDString() { throw new UnsupportedOperationException( getClass().getName() + " does not support GUIDs" ); } // limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support some form of limiting query results via a SQL clause?
Returns:True if this dialect supports some form of LIMIT.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Does this dialect support some form of limiting query results * via a SQL clause? * * @return True if this dialect supports some form of LIMIT. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean supportsLimit() { return false; }
Does this dialect's LIMIT support (if any) additionally support specifying an offset?
Returns:True if the dialect supports an offset within the limit support.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Does this dialect's LIMIT support (if any) additionally * support specifying an offset? * * @return True if the dialect supports an offset within the limit support. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean supportsLimitOffset() { return supportsLimit(); }
Does this dialect support bind variables (i.e., prepared statement parameters) for its limit/offset?
Returns:True if bind variables can be used; false otherwise.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Does this dialect support bind variables (i.e., prepared statement * parameters) for its limit/offset? * * @return True if bind variables can be used; false otherwise. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean supportsVariableLimit() { return supportsLimit(); }
ANSI SQL defines the LIMIT clause to be in the form LIMIT offset, limit. Does this dialect require us to bind the parameters in reverse order?
Returns:true if the correct order is limit, offset
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * ANSI SQL defines the LIMIT clause to be in the form LIMIT offset, limit. * Does this dialect require us to bind the parameters in reverse order? * * @return true if the correct order is limit, offset * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean bindLimitParametersInReverseOrder() { return false; }
Does the LIMIT clause come at the start of the SELECT statement, rather than at the end?
Returns:true if limit parameters should come before other parameters
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Does the <tt>LIMIT</tt> clause come at the start of the * <tt>SELECT</tt> statement, rather than at the end? * * @return true if limit parameters should come before other parameters * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean bindLimitParametersFirst() { return false; }
Does the LIMIT clause take a "maximum" row number instead of a total number of returned rows?

This is easiest understood via an example. Consider you have a table with 20 rows, but you only want to retrieve rows number 11 through 20. Generally, a limit with offset would say that the offset = 11 and the limit = 10 (we only want 10 rows at a time); this is specifying the total number of returned rows. Some dialects require that we instead specify offset = 11 and limit = 20, where 20 is the "last" row we want relative to offset (i.e. total number of rows = 20 - 11 = 9)

So essentially, is limit relative from offset? Or is limit absolute?
Returns:True if limit is relative from offset; false otherwise.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Does the <tt>LIMIT</tt> clause take a "maximum" row number instead * of a total number of returned rows? * <p/> * This is easiest understood via an example. Consider you have a table * with 20 rows, but you only want to retrieve rows number 11 through 20. * Generally, a limit with offset would say that the offset = 11 and the * limit = 10 (we only want 10 rows at a time); this is specifying the * total number of returned rows. Some dialects require that we instead * specify offset = 11 and limit = 20, where 20 is the "last" row we want * relative to offset (i.e. total number of rows = 20 - 11 = 9) * <p/> * So essentially, is limit relative from offset? Or is limit absolute? * * @return True if limit is relative from offset; false otherwise. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean useMaxForLimit() { return false; }
Generally, if there is no limit applied to a Hibernate query we do not apply any limits to the SQL query. This option forces that the limit be written to the SQL query.
Returns:True to force limit into SQL query even if none specified in Hibernate query; false otherwise.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Generally, if there is no limit applied to a Hibernate query we do not apply any limits * to the SQL query. This option forces that the limit be written to the SQL query. * * @return True to force limit into SQL query even if none specified in Hibernate query; false otherwise. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public boolean forceLimitUsage() { return false; }
Given a limit and an offset, apply the limit clause to the query.
Params:
  • query – The query to which to apply the limit.
  • offset – The offset of the limit
  • limit – The limit of the limit ;)
Returns:The modified query statement with the limit applied.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Given a limit and an offset, apply the limit clause to the query. * * @param query The query to which to apply the limit. * @param offset The offset of the limit * @param limit The limit of the limit ;) * @return The modified query statement with the limit applied. * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public String getLimitString(String query, int offset, int limit) { return getLimitString( query, ( offset > 0 || forceLimitUsage() ) ); }
Apply s limit clause to the query.

Typically dialects utilize variable limit clauses when they support limits. Thus, when building the select command we do not actually need to know the limit or the offest since we will just be using placeholders.

Here we do still pass along whether or not an offset was specified so that dialects not supporting offsets can generate proper exceptions. In general, dialects will override one or the other of this method and getLimitString(String, int, int).
Params:
  • query – The query to which to apply the limit.
  • hasOffset – Is the query requesting an offset?
Returns:the modified SQL
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Apply s limit clause to the query. * <p/> * Typically dialects utilize {@link #supportsVariableLimit() variable} * limit clauses when they support limits. Thus, when building the * select command we do not actually need to know the limit or the offest * since we will just be using placeholders. * <p/> * Here we do still pass along whether or not an offset was specified * so that dialects not supporting offsets can generate proper exceptions. * In general, dialects will override one or the other of this method and * {@link #getLimitString(String, int, int)}. * * @param query The query to which to apply the limit. * @param hasOffset Is the query requesting an offset? * @return the modified SQL * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated protected String getLimitString(String query, boolean hasOffset) { throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName()); }
Hibernate APIs explicitly state that setFirstResult() should be a zero-based offset. Here we allow the Dialect a chance to convert that value based on what the underlying db or driver will expect.

NOTE: what gets passed into getLimitString(String, int, int) is the zero-based offset. Dialects which do not supportsVariableLimit should take care to perform any needed first-row-conversion calls prior to injecting the limit values into the SQL string.
Params:
  • zeroBasedFirstResult – The user-supplied, zero-based first row offset.
See Also:
Returns:The corresponding db/dialect specific offset.
Deprecated:buildLimitHandler(String, RowSelection) should be overridden instead.
/** * Hibernate APIs explicitly state that setFirstResult() should be a zero-based offset. Here we allow the * Dialect a chance to convert that value based on what the underlying db or driver will expect. * <p/> * NOTE: what gets passed into {@link #getLimitString(String,int,int)} is the zero-based offset. Dialects which * do not {@link #supportsVariableLimit} should take care to perform any needed first-row-conversion calls prior * to injecting the limit values into the SQL string. * * @param zeroBasedFirstResult The user-supplied, zero-based first row offset. * @return The corresponding db/dialect specific offset. * @see org.hibernate.Query#setFirstResult * @see org.hibernate.Criteria#setFirstResult * @deprecated {@link #buildLimitHandler(String, RowSelection)} should be overridden instead. */
@Deprecated public int convertToFirstRowValue(int zeroBasedFirstResult) { return zeroBasedFirstResult; }
Build delegate managing LIMIT clause.
Params:
  • sql – SQL query.
  • selection – Selection criteria. null in case of unlimited number of rows.
Returns:LIMIT clause delegate.
/** * Build delegate managing LIMIT clause. * * @param sql SQL query. * @param selection Selection criteria. {@code null} in case of unlimited number of rows. * @return LIMIT clause delegate. */
public LimitHandler buildLimitHandler(String sql, RowSelection selection) { return new LegacyLimitHandler( this, sql, selection ); } // lock acquisition support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Informational metadata about whether this dialect is known to support specifying timeouts for requested lock acquisitions.
Returns:True is this dialect supports specifying lock timeouts.
/** * Informational metadata about whether this dialect is known to support * specifying timeouts for requested lock acquisitions. * * @return True is this dialect supports specifying lock timeouts. */
public boolean supportsLockTimeouts() { return true; }
If this dialect supports specifying lock timeouts, are those timeouts rendered into the SQL string as parameters. The implication is that Hibernate will need to bind the timeout value as a parameter in the PreparedStatement. If true, the param position is always handled as the last parameter; if the dialect specifies the lock timeout elsewhere in the SQL statement then the timeout value should be directly rendered into the statement and this method should return false.
Returns:True if the lock timeout is rendered into the SQL string as a parameter; false otherwise.
/** * If this dialect supports specifying lock timeouts, are those timeouts * rendered into the <tt>SQL</tt> string as parameters. The implication * is that Hibernate will need to bind the timeout value as a parameter * in the {@link java.sql.PreparedStatement}. If true, the param position * is always handled as the last parameter; if the dialect specifies the * lock timeout elsewhere in the <tt>SQL</tt> statement then the timeout * value should be directly rendered into the statement and this method * should return false. * * @return True if the lock timeout is rendered into the <tt>SQL</tt> * string as a parameter; false otherwise. */
public boolean isLockTimeoutParameterized() { return false; }
Get a strategy instance which knows how to acquire a database-level lock of the specified mode for this dialect.
Params:
  • lockable – The persister for the entity to be locked.
  • lockMode – The type of lock to be acquired.
Returns:The appropriate locking strategy.
Since:3.2
/** * Get a strategy instance which knows how to acquire a database-level lock * of the specified mode for this dialect. * * @param lockable The persister for the entity to be locked. * @param lockMode The type of lock to be acquired. * @return The appropriate locking strategy. * @since 3.2 */
public LockingStrategy getLockingStrategy(Lockable lockable, LockMode lockMode) { switch ( lockMode ) { case PESSIMISTIC_FORCE_INCREMENT: return new PessimisticForceIncrementLockingStrategy( lockable, lockMode ); case PESSIMISTIC_WRITE: return new PessimisticWriteSelectLockingStrategy( lockable, lockMode ); case PESSIMISTIC_READ: return new PessimisticReadSelectLockingStrategy( lockable, lockMode ); case OPTIMISTIC: return new OptimisticLockingStrategy( lockable, lockMode ); case OPTIMISTIC_FORCE_INCREMENT: return new OptimisticForceIncrementLockingStrategy( lockable, lockMode ); default: return new SelectLockingStrategy( lockable, lockMode ); } }
Given LockOptions (lockMode, timeout), determine the appropriate for update fragment to use.
Params:
  • lockOptions – contains the lock mode to apply.
Returns:The appropriate for update fragment.
/** * Given LockOptions (lockMode, timeout), determine the appropriate for update fragment to use. * * @param lockOptions contains the lock mode to apply. * @return The appropriate for update fragment. */
public String getForUpdateString(LockOptions lockOptions) { final LockMode lockMode = lockOptions.getLockMode(); return getForUpdateString( lockMode, lockOptions.getTimeOut() ); } @SuppressWarnings( {"deprecation"}) private String getForUpdateString(LockMode lockMode, int timeout){ switch ( lockMode ) { case UPGRADE: return getForUpdateString(); case PESSIMISTIC_READ: return getReadLockString( timeout ); case PESSIMISTIC_WRITE: return getWriteLockString( timeout ); case UPGRADE_NOWAIT: case FORCE: case PESSIMISTIC_FORCE_INCREMENT: return getForUpdateNowaitString(); case UPGRADE_SKIPLOCKED: return getForUpdateSkipLockedString(); default: return ""; } }
Given a lock mode, determine the appropriate for update fragment to use.
Params:
  • lockMode – The lock mode to apply.
Returns:The appropriate for update fragment.
/** * Given a lock mode, determine the appropriate for update fragment to use. * * @param lockMode The lock mode to apply. * @return The appropriate for update fragment. */
public String getForUpdateString(LockMode lockMode) { return getForUpdateString( lockMode, LockOptions.WAIT_FOREVER ); }
Get the string to append to SELECT statements to acquire locks for this dialect.
Returns:The appropriate FOR UPDATE clause string.
/** * Get the string to append to SELECT statements to acquire locks * for this dialect. * * @return The appropriate <tt>FOR UPDATE</tt> clause string. */
public String getForUpdateString() { return " for update"; }
Get the string to append to SELECT statements to acquire WRITE locks for this dialect. Location of the of the returned string is treated the same as getForUpdateString.
Params:
  • timeout – in milliseconds, -1 for indefinite wait and 0 for no wait.
Returns:The appropriate LOCK clause string.
/** * Get the string to append to SELECT statements to acquire WRITE locks * for this dialect. Location of the of the returned string is treated * the same as getForUpdateString. * * @param timeout in milliseconds, -1 for indefinite wait and 0 for no wait. * @return The appropriate <tt>LOCK</tt> clause string. */
public String getWriteLockString(int timeout) { return getForUpdateString(); }
Get the string to append to SELECT statements to acquire WRITE locks for this dialect. Location of the of the returned string is treated the same as getForUpdateString.
Params:
  • timeout – in milliseconds, -1 for indefinite wait and 0 for no wait.
Returns:The appropriate LOCK clause string.
/** * Get the string to append to SELECT statements to acquire WRITE locks * for this dialect. Location of the of the returned string is treated * the same as getForUpdateString. * * @param timeout in milliseconds, -1 for indefinite wait and 0 for no wait. * @return The appropriate <tt>LOCK</tt> clause string. */
public String getReadLockString(int timeout) { return getForUpdateString(); }
Is FOR UPDATE OF syntax supported?
Returns:True if the database supports FOR UPDATE OF syntax; false otherwise.
/** * Is <tt>FOR UPDATE OF</tt> syntax supported? * * @return True if the database supports <tt>FOR UPDATE OF</tt> syntax; * false otherwise. */
public boolean forUpdateOfColumns() { // by default we report no support return false; }
Does this dialect support FOR UPDATE in conjunction with outer joined rows?
Returns:True if outer joined rows can be locked via FOR UPDATE.
/** * Does this dialect support <tt>FOR UPDATE</tt> in conjunction with * outer joined rows? * * @return True if outer joined rows can be locked via <tt>FOR UPDATE</tt>. */
public boolean supportsOuterJoinForUpdate() { return true; }
Get the FOR UPDATE OF column_list fragment appropriate for this dialect given the aliases of the columns to be write locked.
Params:
  • aliases – The columns to be write locked.
Returns:The appropriate FOR UPDATE OF column_list clause string.
/** * Get the <tt>FOR UPDATE OF column_list</tt> fragment appropriate for this * dialect given the aliases of the columns to be write locked. * * @param aliases The columns to be write locked. * @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string. */
public String getForUpdateString(String aliases) { // by default we simply return the getForUpdateString() result since // the default is to say no support for "FOR UPDATE OF ..." return getForUpdateString(); }
Get the FOR UPDATE OF column_list fragment appropriate for this dialect given the aliases of the columns to be write locked.
Params:
  • aliases – The columns to be write locked.
  • lockOptions – the lock options to apply
Returns:The appropriate FOR UPDATE OF column_list clause string.
/** * Get the <tt>FOR UPDATE OF column_list</tt> fragment appropriate for this * dialect given the aliases of the columns to be write locked. * * @param aliases The columns to be write locked. * @param lockOptions the lock options to apply * @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string. */
@SuppressWarnings({"unchecked", "UnusedParameters"}) public String getForUpdateString(String aliases, LockOptions lockOptions) { LockMode lockMode = lockOptions.getLockMode(); final Iterator<Map.Entry<String, LockMode>> itr = lockOptions.getAliasLockIterator(); while ( itr.hasNext() ) { // seek the highest lock mode final Map.Entry<String, LockMode>entry = itr.next(); final LockMode lm = entry.getValue(); if ( lm.greaterThan( lockMode ) ) { lockMode = lm; } } lockOptions.setLockMode( lockMode ); return getForUpdateString( lockOptions ); }
Retrieves the FOR UPDATE NOWAIT syntax specific to this dialect.
Returns:The appropriate FOR UPDATE NOWAIT clause string.
/** * Retrieves the <tt>FOR UPDATE NOWAIT</tt> syntax specific to this dialect. * * @return The appropriate <tt>FOR UPDATE NOWAIT</tt> clause string. */
public String getForUpdateNowaitString() { // by default we report no support for NOWAIT lock semantics return getForUpdateString(); }
Retrieves the FOR UPDATE SKIP LOCKED syntax specific to this dialect.
Returns:The appropriate FOR UPDATE SKIP LOCKED clause string.
/** * Retrieves the <tt>FOR UPDATE SKIP LOCKED</tt> syntax specific to this dialect. * * @return The appropriate <tt>FOR UPDATE SKIP LOCKED</tt> clause string. */
public String getForUpdateSkipLockedString() { // by default we report no support for SKIP_LOCKED lock semantics return getForUpdateString(); }
Get the FOR UPDATE OF column_list NOWAIT fragment appropriate for this dialect given the aliases of the columns to be write locked.
Params:
  • aliases – The columns to be write locked.
Returns:The appropriate FOR UPDATE OF colunm_list NOWAIT clause string.
/** * Get the <tt>FOR UPDATE OF column_list NOWAIT</tt> fragment appropriate * for this dialect given the aliases of the columns to be write locked. * * @param aliases The columns to be write locked. * @return The appropriate <tt>FOR UPDATE OF colunm_list NOWAIT</tt> clause string. */
public String getForUpdateNowaitString(String aliases) { return getForUpdateString( aliases ); }
Get the FOR UPDATE OF column_list SKIP LOCKED fragment appropriate for this dialect given the aliases of the columns to be write locked.
Params:
  • aliases – The columns to be write locked.
Returns:The appropriate FOR UPDATE colunm_list SKIP LOCKED clause string.
/** * Get the <tt>FOR UPDATE OF column_list SKIP LOCKED</tt> fragment appropriate * for this dialect given the aliases of the columns to be write locked. * * @param aliases The columns to be write locked. * @return The appropriate <tt>FOR UPDATE colunm_list SKIP LOCKED</tt> clause string. */
public String getForUpdateSkipLockedString(String aliases) { return getForUpdateString( aliases ); }
Some dialects support an alternative means to SELECT FOR UPDATE, whereby a "lock hint" is appends to the table name in the from clause.

contributed by Helge Schulz
Params:
  • mode – The lock mode to apply
  • tableName – The name of the table to which to apply the lock hint.
Returns:The table with any required lock hints.
Deprecated:use appendLockHint(LockOptions,String) instead
/** * Some dialects support an alternative means to <tt>SELECT FOR UPDATE</tt>, * whereby a "lock hint" is appends to the table name in the from clause. * <p/> * contributed by <a href="http://sourceforge.net/users/heschulz">Helge Schulz</a> * * @param mode The lock mode to apply * @param tableName The name of the table to which to apply the lock hint. * @return The table with any required lock hints. * @deprecated use {@code appendLockHint(LockOptions,String)} instead */
@Deprecated public String appendLockHint(LockMode mode, String tableName) { return appendLockHint( new LockOptions( mode ), tableName ); }
Some dialects support an alternative means to SELECT FOR UPDATE, whereby a "lock hint" is appends to the table name in the from clause.

contributed by Helge Schulz
Params:
  • lockOptions – The lock options to apply
  • tableName – The name of the table to which to apply the lock hint.
Returns:The table with any required lock hints.
/** * Some dialects support an alternative means to <tt>SELECT FOR UPDATE</tt>, * whereby a "lock hint" is appends to the table name in the from clause. * <p/> * contributed by <a href="http://sourceforge.net/users/heschulz">Helge Schulz</a> * * @param lockOptions The lock options to apply * @param tableName The name of the table to which to apply the lock hint. * @return The table with any required lock hints. */
public String appendLockHint(LockOptions lockOptions, String tableName){ return tableName; }
Modifies the given SQL by applying the appropriate updates for the specified lock modes and key columns.

The behavior here is that of an ANSI SQL SELECT FOR UPDATE. This method is really intended to allow dialects which do not support SELECT FOR UPDATE to achieve this in their own fashion.
Params:
  • sql – the SQL string to modify
  • aliasedLockOptions – lock options indexed by aliased table names.
  • keyColumnNames – a map of key columns indexed by aliased table names.
Returns:the modified SQL string.
/** * Modifies the given SQL by applying the appropriate updates for the specified * lock modes and key columns. * <p/> * The behavior here is that of an ANSI SQL <tt>SELECT FOR UPDATE</tt>. This * method is really intended to allow dialects which do not support * <tt>SELECT FOR UPDATE</tt> to achieve this in their own fashion. * * @param sql the SQL string to modify * @param aliasedLockOptions lock options indexed by aliased table names. * @param keyColumnNames a map of key columns indexed by aliased table names. * @return the modified SQL string. */
public String applyLocksToSql(String sql, LockOptions aliasedLockOptions, Map<String, String[]> keyColumnNames) { return sql + new ForUpdateFragment( this, aliasedLockOptions, keyColumnNames ).toFragmentString(); } // table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Command used to create a table.
Returns:The command used to create a table.
/** * Command used to create a table. * * @return The command used to create a table. */
public String getCreateTableString() { return "create table"; }
Slight variation on getCreateTableString. Here, we have the command used to create a table when there is no primary key and duplicate rows are expected.

Most databases do not care about the distinction; originally added for Teradata support which does care.
Returns:The command used to create a multiset table.
/** * Slight variation on {@link #getCreateTableString}. Here, we have the * command used to create a table when there is no primary key and * duplicate rows are expected. * <p/> * Most databases do not care about the distinction; originally added for * Teradata support which does care. * * @return The command used to create a multiset table. */
public String getCreateMultisetTableString() { return getCreateTableString(); } // temporary table support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support temporary tables?
Returns:True if temp tables are supported; false otherwise.
/** * Does this dialect support temporary tables? * * @return True if temp tables are supported; false otherwise. */
public boolean supportsTemporaryTables() { return false; }
Generate a temporary table name given the base table.
Params:
  • baseTableName – The table name from which to base the temp table name.
Returns:The generated temp table name.
/** * Generate a temporary table name given the base table. * * @param baseTableName The table name from which to base the temp table name. * @return The generated temp table name. */
public String generateTemporaryTableName(String baseTableName) { return "HT_" + baseTableName; }
Command used to create a temporary table.
Returns:The command used to create a temporary table.
/** * Command used to create a temporary table. * * @return The command used to create a temporary table. */
public String getCreateTemporaryTableString() { return "create table"; }
Get any fragments needing to be postfixed to the command for temporary table creation.
Returns:Any required postfix.
/** * Get any fragments needing to be postfixed to the command for * temporary table creation. * * @return Any required postfix. */
public String getCreateTemporaryTablePostfix() { return ""; }
Command used to drop a temporary table.
Returns:The command used to drop a temporary table.
/** * Command used to drop a temporary table. * * @return The command used to drop a temporary table. */
public String getDropTemporaryTableString() { return "drop table"; }
Does the dialect require that temporary table DDL statements occur in isolation from other statements? This would be the case if the creation would cause any current transaction to get committed implicitly.

JDBC defines a standard way to query for this information via the DatabaseMetaData.dataDefinitionCausesTransactionCommit() method. However, that does not distinguish between temporary table DDL and other forms of DDL; MySQL, for example, reports DDL causing a transaction commit via its driver, even though that is not the case for temporary table DDL.

Possible return values and their meanings:
Returns:see the result matrix above.
/** * Does the dialect require that temporary table DDL statements occur in * isolation from other statements? This would be the case if the creation * would cause any current transaction to get committed implicitly. * <p/> * JDBC defines a standard way to query for this information via the * {@link java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()} * method. However, that does not distinguish between temporary table * DDL and other forms of DDL; MySQL, for example, reports DDL causing a * transaction commit via its driver, even though that is not the case for * temporary table DDL. * <p/> * Possible return values and their meanings:<ul> * <li>{@link Boolean#TRUE} - Unequivocally, perform the temporary table DDL * in isolation.</li> * <li>{@link Boolean#FALSE} - Unequivocally, do <b>not</b> perform the * temporary table DDL in isolation.</li> * <li><i>null</i> - defer to the JDBC driver response in regards to * {@link java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()}</li> * </ul> * * @return see the result matrix above. */
public Boolean performTemporaryTableDDLInIsolation() { return null; }
Do we need to drop the temporary table after use?
Returns:True if the table should be dropped.
/** * Do we need to drop the temporary table after use? * * @return True if the table should be dropped. */
public boolean dropTemporaryTableAfterUse() { return true; } // callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of returning ResultSet *by position*. Pre-Java 8, registering such ResultSet-returning parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract.
Params:
  • statement – The callable statement.
  • position – The bind position at which to register the output param.
Throws:
Returns:The number of (contiguous) bind positions used.
/** * Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of * returning {@link java.sql.ResultSet} *by position*. Pre-Java 8, registering such ResultSet-returning * parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract. * * @param statement The callable statement. * @param position The bind position at which to register the output param. * * @return The number of (contiguous) bind positions used. * * @throws SQLException Indicates problems registering the param. */
public int registerResultSetOutParameter(CallableStatement statement, int position) throws SQLException { throw new UnsupportedOperationException( getClass().getName() + " does not support resultsets via stored procedures" ); }
Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of returning ResultSet *by name*. Pre-Java 8, registering such ResultSet-returning parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract.
Params:
  • statement – The callable statement.
  • name – The parameter name (for drivers which support named parameters).
Throws:
Returns:The number of (contiguous) bind positions used.
/** * Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of * returning {@link java.sql.ResultSet} *by name*. Pre-Java 8, registering such ResultSet-returning * parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract. * * @param statement The callable statement. * @param name The parameter name (for drivers which support named parameters). * * @return The number of (contiguous) bind positions used. * * @throws SQLException Indicates problems registering the param. */
@SuppressWarnings("UnusedParameters") public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException { throw new UnsupportedOperationException( getClass().getName() + " does not support resultsets via stored procedures" ); }
Given a callable statement previously processed by registerResultSetOutParameter, extract the ResultSet from the OUT parameter.
Params:
  • statement – The callable statement.
Throws:
  • SQLException – Indicates problems extracting the result set.
Returns:The extracted result set.
/** * Given a callable statement previously processed by {@link #registerResultSetOutParameter}, * extract the {@link java.sql.ResultSet} from the OUT parameter. * * @param statement The callable statement. * @return The extracted result set. * @throws SQLException Indicates problems extracting the result set. */
public ResultSet getResultSet(CallableStatement statement) throws SQLException { throw new UnsupportedOperationException( getClass().getName() + " does not support resultsets via stored procedures" ); }
Given a callable statement previously processed by registerResultSetOutParameter, extract the ResultSet.
Params:
  • statement – The callable statement.
  • position – The bind position at which to register the output param.
Throws:
  • SQLException – Indicates problems extracting the result set.
Returns:The extracted result set.
/** * Given a callable statement previously processed by {@link #registerResultSetOutParameter}, * extract the {@link java.sql.ResultSet}. * * @param statement The callable statement. * @param position The bind position at which to register the output param. * * @return The extracted result set. * * @throws SQLException Indicates problems extracting the result set. */
@SuppressWarnings("UnusedParameters") public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException { throw new UnsupportedOperationException( getClass().getName() + " does not support resultsets via stored procedures" ); }
Given a callable statement previously processed by registerResultSetOutParameter, extract the ResultSet from the OUT parameter.
Params:
  • statement – The callable statement.
  • name – The parameter name (for drivers which support named parameters).
Throws:
  • SQLException – Indicates problems extracting the result set.
Returns:The extracted result set.
/** * Given a callable statement previously processed by {@link #registerResultSetOutParameter}, * extract the {@link java.sql.ResultSet} from the OUT parameter. * * @param statement The callable statement. * @param name The parameter name (for drivers which support named parameters). * * @return The extracted result set. * * @throws SQLException Indicates problems extracting the result set. */
@SuppressWarnings("UnusedParameters") public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException { throw new UnsupportedOperationException( getClass().getName() + " does not support resultsets via stored procedures" ); } // current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support a way to retrieve the database's current timestamp value?
Returns:True if the current timestamp can be retrieved; false otherwise.
/** * Does this dialect support a way to retrieve the database's current * timestamp value? * * @return True if the current timestamp can be retrieved; false otherwise. */
public boolean supportsCurrentTimestampSelection() { return false; }
Should the value returned by getCurrentTimestampSelectString be treated as callable. Typically this indicates that JDBC escape syntax is being used...
Returns:True if the getCurrentTimestampSelectString return is callable; false otherwise.
/** * Should the value returned by {@link #getCurrentTimestampSelectString} * be treated as callable. Typically this indicates that JDBC escape * syntax is being used... * * @return True if the {@link #getCurrentTimestampSelectString} return * is callable; false otherwise. */
public boolean isCurrentTimestampSelectStringCallable() { throw new UnsupportedOperationException( "Database not known to define a current timestamp function" ); }
Retrieve the command used to retrieve the current timestamp from the database.
Returns:The command.
/** * Retrieve the command used to retrieve the current timestamp from the * database. * * @return The command. */
public String getCurrentTimestampSelectString() { throw new UnsupportedOperationException( "Database not known to define a current timestamp function" ); }
The name of the database-specific SQL function for retrieving the current timestamp.
Returns:The function name.
/** * The name of the database-specific SQL function for retrieving the * current timestamp. * * @return The function name. */
public String getCurrentTimestampSQLFunctionName() { // the standard SQL function name is current_timestamp... return "current_timestamp"; } // SQLException support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build an instance of the SQLExceptionConverter preferred by this dialect for converting SQLExceptions into Hibernate's JDBCException hierarchy.

The preferred method is to not override this method; if possible, buildSQLExceptionConversionDelegate() should be overridden instead. If this method is not overridden, the default SQLExceptionConverter implementation executes 3 SQLException converter delegates:
  1. a "static" delegate based on the JDBC 4 defined SQLException hierarchy;
  2. the vendor-specific delegate returned by buildSQLExceptionConversionDelegate(); (it is strongly recommended that specific Dialect implementations override buildSQLExceptionConversionDelegate())
  3. a delegate that interprets SQLState codes for either X/Open or SQL-2003 codes, depending on java.sql.DatabaseMetaData#getSQLStateType

If this method is overridden, it is strongly recommended that the returned SQLExceptionConverter interpret SQL errors based on vendor-specific error codes rather than the SQLState since the interpretation is more accurate when using vendor-specific ErrorCodes.
See Also:
Returns:The Dialect's preferred SQLExceptionConverter, or null to indicate that the default SQLExceptionConverter should be used.
Deprecated:buildSQLExceptionConversionDelegate() should be overridden instead.
/** * Build an instance of the SQLExceptionConverter preferred by this dialect for * converting SQLExceptions into Hibernate's JDBCException hierarchy. * <p/> * The preferred method is to not override this method; if possible, * {@link #buildSQLExceptionConversionDelegate()} should be overridden * instead. * * If this method is not overridden, the default SQLExceptionConverter * implementation executes 3 SQLException converter delegates: * <ol> * <li>a "static" delegate based on the JDBC 4 defined SQLException hierarchy;</li> * <li>the vendor-specific delegate returned by {@link #buildSQLExceptionConversionDelegate()}; * (it is strongly recommended that specific Dialect implementations * override {@link #buildSQLExceptionConversionDelegate()})</li> * <li>a delegate that interprets SQLState codes for either X/Open or SQL-2003 codes, * depending on java.sql.DatabaseMetaData#getSQLStateType</li> * </ol> * <p/> * If this method is overridden, it is strongly recommended that the * returned {@link SQLExceptionConverter} interpret SQL errors based on * vendor-specific error codes rather than the SQLState since the * interpretation is more accurate when using vendor-specific ErrorCodes. * * @return The Dialect's preferred SQLExceptionConverter, or null to * indicate that the default {@link SQLExceptionConverter} should be used. * * @see {@link #buildSQLExceptionConversionDelegate()} * @deprecated {@link #buildSQLExceptionConversionDelegate()} should be * overridden instead. */
@Deprecated public SQLExceptionConverter buildSQLExceptionConverter() { return null; }
Build an instance of a SQLExceptionConversionDelegate for interpreting dialect-specific error or SQLState codes.

When buildSQLExceptionConverter returns null, the default SQLExceptionConverter is used to interpret SQLState and error codes. If this method is overridden to return a non-null value, the default SQLExceptionConverter will use the returned SQLExceptionConversionDelegate in addition to the following standard delegates:
  1. a "static" delegate based on the JDBC 4 defined SQLException hierarchy;
  2. a delegate that interprets SQLState codes for either X/Open or SQL-2003 codes, depending on java.sql.DatabaseMetaData#getSQLStateType

It is strongly recommended that specific Dialect implementations override this method, since interpretation of a SQL error is much more accurate when based on the a vendor-specific ErrorCode rather than the SQLState.

Specific Dialects may override to return whatever is most appropriate for that vendor.
Returns:The SQLExceptionConversionDelegate for this dialect
/** * Build an instance of a {@link SQLExceptionConversionDelegate} for * interpreting dialect-specific error or SQLState codes. * <p/> * When {@link #buildSQLExceptionConverter} returns null, the default * {@link SQLExceptionConverter} is used to interpret SQLState and * error codes. If this method is overridden to return a non-null value, * the default {@link SQLExceptionConverter} will use the returned * {@link SQLExceptionConversionDelegate} in addition to the following * standard delegates: * <ol> * <li>a "static" delegate based on the JDBC 4 defined SQLException hierarchy;</li> * <li>a delegate that interprets SQLState codes for either X/Open or SQL-2003 codes, * depending on java.sql.DatabaseMetaData#getSQLStateType</li> * </ol> * <p/> * It is strongly recommended that specific Dialect implementations override this * method, since interpretation of a SQL error is much more accurate when based on * the a vendor-specific ErrorCode rather than the SQLState. * <p/> * Specific Dialects may override to return whatever is most appropriate for that vendor. * * @return The SQLExceptionConversionDelegate for this dialect */
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() { return null; } private static final ViolatedConstraintNameExtracter EXTRACTER = new ViolatedConstraintNameExtracter() { public String extractConstraintName(SQLException sqle) { return null; } }; public ViolatedConstraintNameExtracter getViolatedConstraintNameExtracter() { return EXTRACTER; } // union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Given a Types type code, determine an appropriate null value to use in a select clause.

One thing to consider here is that certain databases might require proper casting for the nulls here since the select here will be part of a UNION/UNION ALL.
Params:
  • sqlType – The Types type code.
Returns:The appropriate select clause value fragment.
/** * Given a {@link java.sql.Types} type code, determine an appropriate * null value to use in a select clause. * <p/> * One thing to consider here is that certain databases might * require proper casting for the nulls here since the select here * will be part of a UNION/UNION ALL. * * @param sqlType The {@link java.sql.Types} type code. * @return The appropriate select clause value fragment. */
public String getSelectClauseNullString(int sqlType) { return "null"; }
Does this dialect support UNION ALL, which is generally a faster variant of UNION?
Returns:True if UNION ALL is supported; false otherwise.
/** * Does this dialect support UNION ALL, which is generally a faster * variant of UNION? * * @return True if UNION ALL is supported; false otherwise. */
public boolean supportsUnionAll() { return false; } // miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Create a JoinFragment strategy responsible for handling this dialect's variations in how joins are handled.
Returns:This dialect's JoinFragment strategy.
/** * Create a {@link org.hibernate.sql.JoinFragment} strategy responsible * for handling this dialect's variations in how joins are handled. * * @return This dialect's {@link org.hibernate.sql.JoinFragment} strategy. */
public JoinFragment createOuterJoinFragment() { return new ANSIJoinFragment(); }
Create a CaseFragment strategy responsible for handling this dialect's variations in how CASE statements are handled.
Returns:This dialect's CaseFragment strategy.
/** * Create a {@link org.hibernate.sql.CaseFragment} strategy responsible * for handling this dialect's variations in how CASE statements are * handled. * * @return This dialect's {@link org.hibernate.sql.CaseFragment} strategy. */
public CaseFragment createCaseFragment() { return new ANSICaseFragment(); }
The fragment used to insert a row without specifying any column values. This is not possible on some databases.
Returns:The appropriate empty values clause.
/** * The fragment used to insert a row without specifying any column values. * This is not possible on some databases. * * @return The appropriate empty values clause. */
public String getNoColumnsInsertString() { return "values ( )"; }
The name of the SQL function that transforms a string to lowercase
Returns:The dialect-specific lowercase function.
/** * The name of the SQL function that transforms a string to * lowercase * * @return The dialect-specific lowercase function. */
public String getLowercaseFunction() { return "lower"; }
The name of the SQL function that can do case insensitive like comparison.
Returns: The dialect-specific "case insensitive" like function.
/** * The name of the SQL function that can do case insensitive <b>like</b> comparison. * * @return The dialect-specific "case insensitive" like function. */
public String getCaseInsensitiveLike(){ return "like"; }
Does this dialect support case insensitive LIKE restrictions?
Returns:true if the underlying database supports case insensitive like comparison, false otherwise. The default is false.
/** * Does this dialect support case insensitive LIKE restrictions? * * @return {@code true} if the underlying database supports case insensitive like comparison, * {@code false} otherwise. The default is {@code false}. */
public boolean supportsCaseInsensitiveLike(){ return false; }
Meant as a means for end users to affect the select strings being sent to the database and perhaps manipulate them in some fashion.

The recommend approach is to instead use Interceptor.onPrepareStatement(String).
Params:
  • select – The select command
Returns:The mutated select command, or the same as was passed in.
/** * Meant as a means for end users to affect the select strings being sent * to the database and perhaps manipulate them in some fashion. * <p/> * The recommend approach is to instead use * {@link org.hibernate.Interceptor#onPrepareStatement(String)}. * * @param select The select command * @return The mutated select command, or the same as was passed in. */
public String transformSelectString(String select) { return select; }
What is the maximum length Hibernate can use for generated aliases?

The maximum here should account for the fact that Hibernate often needs to append "uniqueing" information to the end of generated aliases. That "uniqueing" information will be added to the end of a identifier generated to the length specified here; so be sure to leave some room (generally speaking 5 positions will suffice).
Returns:The maximum length.
/** * What is the maximum length Hibernate can use for generated aliases? * <p/> * The maximum here should account for the fact that Hibernate often needs to append "uniqueing" information * to the end of generated aliases. That "uniqueing" information will be added to the end of a identifier * generated to the length specified here; so be sure to leave some room (generally speaking 5 positions will * suffice). * * @return The maximum length. */
public int getMaxAliasLength() { return 10; }
The SQL literal value to which this database maps boolean values.
Params:
  • bool – The boolean value
Returns:The appropriate SQL literal.
/** * The SQL literal value to which this database maps boolean values. * * @param bool The boolean value * @return The appropriate SQL literal. */
public String toBooleanValueString(boolean bool) { return bool ? "1" : "0"; } // identifier quoting support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The character specific to this dialect used to begin a quoted identifier.
Returns:The dialect's specific open quote character.
/** * The character specific to this dialect used to begin a quoted identifier. * * @return The dialect's specific open quote character. */
public char openQuote() { return '"'; }
The character specific to this dialect used to close a quoted identifier.
Returns:The dialect's specific close quote character.
/** * The character specific to this dialect used to close a quoted identifier. * * @return The dialect's specific close quote character. */
public char closeQuote() { return '"'; }
Apply dialect-specific quoting.

By default, the incoming value is checked to see if its first character is the back-tick (`). If so, the dialect specific quoting is applied.
Params:
  • name – The value to be quoted.
See Also:
Returns:The quoted (or unmodified, if not starting with back-tick) value.
/** * Apply dialect-specific quoting. * <p/> * By default, the incoming value is checked to see if its first character * is the back-tick (`). If so, the dialect specific quoting is applied. * * @param name The value to be quoted. * @return The quoted (or unmodified, if not starting with back-tick) value. * @see #openQuote() * @see #closeQuote() */
public final String quote(String name) { if ( name == null ) { return null; } if ( name.charAt( 0 ) == '`' ) { return openQuote() + name.substring( 1, name.length() - 1 ) + closeQuote(); } else { return name; } } // DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Get the SQL command used to create the named schema
Params:
  • schemaName – The name of the schema to be created.
Returns:The creation command
/** * Get the SQL command used to create the named schema * * @param schemaName The name of the schema to be created. * * @return The creation command */
public String getCreateSchemaCommand(String schemaName) { return "create schema " + schemaName; }
Get the SQL command used to drop the named schema
Params:
  • schemaName – The name of the schema to be dropped.
Returns:The drop command
/** * Get the SQL command used to drop the named schema * * @param schemaName The name of the schema to be dropped. * * @return The drop command */
public String getDropSchemaCommand(String schemaName) { return "drop schema " + schemaName; }
Does this dialect support the ALTER TABLE syntax?
Returns:True if we support altering of tables; false otherwise.
/** * Does this dialect support the <tt>ALTER TABLE</tt> syntax? * * @return True if we support altering of tables; false otherwise. */
public boolean hasAlterTable() { return true; }
Do we need to drop constraints before dropping tables in this dialect?
Returns:True if constraints must be dropped prior to dropping the table; false otherwise.
/** * Do we need to drop constraints before dropping tables in this dialect? * * @return True if constraints must be dropped prior to dropping * the table; false otherwise. */
public boolean dropConstraints() { return true; }
Do we need to qualify index names with the schema name?
Returns:boolean
/** * Do we need to qualify index names with the schema name? * * @return boolean */
public boolean qualifyIndexName() { return true; }
The syntax used to add a column to a table (optional).
Returns:The "add column" fragment.
/** * The syntax used to add a column to a table (optional). * * @return The "add column" fragment. */
public String getAddColumnString() { throw new UnsupportedOperationException( "No add column syntax supported by " + getClass().getName() ); }
The syntax for the suffix used to add a column to a table (optional).
Returns:The suffix "add column" fragment.
/** * The syntax for the suffix used to add a column to a table (optional). * * @return The suffix "add column" fragment. */
public String getAddColumnSuffixString() { return ""; } public String getDropForeignKeyString() { return " drop constraint "; } public String getTableTypeString() { // grrr... for differentiation of mysql storage engines return ""; }
The syntax used to add a foreign key constraint to a table.
Params:
  • constraintName – The FK constraint name.
  • foreignKey – The names of the columns comprising the FK
  • referencedTable – The table referenced by the FK
  • primaryKey – The explicit columns in the referencedTable referenced by this FK.
  • referencesPrimaryKey – if false, constraint should be explicit about which column names the constraint refers to
Returns:the "add FK" fragment
/** * The syntax used to add a foreign key constraint to a table. * * @param constraintName The FK constraint name. * @param foreignKey The names of the columns comprising the FK * @param referencedTable The table referenced by the FK * @param primaryKey The explicit columns in the referencedTable referenced * by this FK. * @param referencesPrimaryKey if false, constraint should be * explicit about which column names the constraint refers to * * @return the "add FK" fragment */
public String getAddForeignKeyConstraintString( String constraintName, String[] foreignKey, String referencedTable, String[] primaryKey, boolean referencesPrimaryKey) { final StringBuilder res = new StringBuilder( 30 ); res.append( " add constraint " ) .append( quote( constraintName ) ) .append( " foreign key (" ) .append( StringHelper.join( ", ", foreignKey ) ) .append( ") references " ) .append( referencedTable ); if ( !referencesPrimaryKey ) { res.append( " (" ) .append( StringHelper.join( ", ", primaryKey ) ) .append( ')' ); } return res.toString(); }
The syntax used to add a primary key constraint to a table.
Params:
  • constraintName – The name of the PK constraint.
Returns:The "add PK" fragment
/** * The syntax used to add a primary key constraint to a table. * * @param constraintName The name of the PK constraint. * @return The "add PK" fragment */
public String getAddPrimaryKeyConstraintString(String constraintName) { return " add constraint " + constraintName + " primary key "; }
Does the database/driver have bug in deleting rows that refer to other rows being deleted in the same query?
Returns:true if the database/driver has this bug
/** * Does the database/driver have bug in deleting rows that refer to other rows being deleted in the same query? * * @return {@code true} if the database/driver has this bug */
public boolean hasSelfReferentialForeignKeyBug() { return false; }
The keyword used to specify a nullable column.
Returns:String
/** * The keyword used to specify a nullable column. * * @return String */
public String getNullColumnString() { return ""; }
Does this dialect/database support commenting on tables, columns, etc?
Returns:true if commenting is supported
/** * Does this dialect/database support commenting on tables, columns, etc? * * @return {@code true} if commenting is supported */
public boolean supportsCommentOn() { return false; }
Get the comment into a form supported for table definition.
Params:
  • comment – The comment to apply
Returns:The comment fragment
/** * Get the comment into a form supported for table definition. * * @param comment The comment to apply * * @return The comment fragment */
public String getTableComment(String comment) { return ""; }
Get the comment into a form supported for column definition.
Params:
  • comment – The comment to apply
Returns:The comment fragment
/** * Get the comment into a form supported for column definition. * * @param comment The comment to apply * * @return The comment fragment */
public String getColumnComment(String comment) { return ""; }
For dropping a table, can the phrase "if exists" be applied before the table name?

NOTE : Only one or the other (or neither) of this and supportsIfExistsAfterTableName should return true
Returns:true if the "if exists" can be applied before the table name
/** * For dropping a table, can the phrase "if exists" be applied before the table name? * <p/> * NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsAfterTableName} should return true * * @return {@code true} if the "if exists" can be applied before the table name */
public boolean supportsIfExistsBeforeTableName() { return false; }
For dropping a table, can the phrase "if exists" be applied after the table name?

NOTE : Only one or the other (or neither) of this and supportsIfExistsBeforeTableName should return true
Returns:true if the "if exists" can be applied after the table name
/** * For dropping a table, can the phrase "if exists" be applied after the table name? * <p/> * NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsBeforeTableName} should return true * * @return {@code true} if the "if exists" can be applied after the table name */
public boolean supportsIfExistsAfterTableName() { return false; }
For dropping a constraint with an "alter table", can the phrase "if exists" be applied before the constraint name?

NOTE : Only one or the other (or neither) of this and supportsIfExistsAfterConstraintName should return true
Returns:true if the "if exists" can be applied before the constraint name
/** * For dropping a constraint with an "alter table", can the phrase "if exists" be applied before the constraint name? * <p/> * NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsAfterConstraintName} should return true * * @return {@code true} if the "if exists" can be applied before the constraint name */
public boolean supportsIfExistsBeforeConstraintName() { return false; }
For dropping a constraint with an "alter table", can the phrase "if exists" be applied after the constraint name?

NOTE : Only one or the other (or neither) of this and supportsIfExistsBeforeConstraintName should return true
Returns:true if the "if exists" can be applied after the constraint name
/** * For dropping a constraint with an "alter table", can the phrase "if exists" be applied after the constraint name? * <p/> * NOTE : Only one or the other (or neither) of this and {@link #supportsIfExistsBeforeConstraintName} should return true * * @return {@code true} if the "if exists" can be applied after the constraint name */
public boolean supportsIfExistsAfterConstraintName() { return false; }
Generate a DROP TABLE statement
Params:
  • tableName – The name of the table to drop
Returns:The DROP TABLE command
/** * Generate a DROP TABLE statement * * @param tableName The name of the table to drop * * @return The DROP TABLE command */
public String getDropTableString(String tableName) { final StringBuilder buf = new StringBuilder( "drop table " ); if ( supportsIfExistsBeforeTableName() ) { buf.append( "if exists " ); } buf.append( tableName ).append( getCascadeConstraintsString() ); if ( supportsIfExistsAfterTableName() ) { buf.append( " if exists" ); } return buf.toString(); }
Does this dialect support column-level check constraints?
Returns:True if column-level CHECK constraints are supported; false otherwise.
/** * Does this dialect support column-level check constraints? * * @return True if column-level CHECK constraints are supported; false * otherwise. */
public boolean supportsColumnCheck() { return true; }
Does this dialect support table-level check constraints?
Returns:True if table-level CHECK constraints are supported; false otherwise.
/** * Does this dialect support table-level check constraints? * * @return True if table-level CHECK constraints are supported; false * otherwise. */
public boolean supportsTableCheck() { return true; }
Does this dialect support cascaded delete on foreign key definitions?
Returns:true indicates that the dialect does support cascaded delete on foreign keys.
/** * Does this dialect support cascaded delete on foreign key definitions? * * @return {@code true} indicates that the dialect does support cascaded delete on foreign keys. */
public boolean supportsCascadeDelete() { return true; }
Completely optional cascading drop clause
Returns:String
/** * Completely optional cascading drop clause * * @return String */
public String getCascadeConstraintsString() { return ""; }
Returns the separator to use for defining cross joins when translating HQL queries.

Typically this will be either [ cross join ] or [, ]

Note that the spaces are important!
Returns:The cross join separator
/** * Returns the separator to use for defining cross joins when translating HQL queries. * <p/> * Typically this will be either [<tt> cross join </tt>] or [<tt>, </tt>] * <p/> * Note that the spaces are important! * * @return The cross join separator */
public String getCrossJoinSeparator() { return " cross join "; } public ColumnAliasExtractor getColumnAliasExtractor() { return ColumnAliasExtractor.COLUMN_LABEL_EXTRACTOR; } // Informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Does this dialect support empty IN lists?

For example, is [where XYZ in ()] a supported construct?
Returns:True if empty in lists are supported; false otherwise.
Since:3.2
/** * Does this dialect support empty IN lists? * <p/> * For example, is [where XYZ in ()] a supported construct? * * @return True if empty in lists are supported; false otherwise. * @since 3.2 */
public boolean supportsEmptyInList() { return true; }
Are string comparisons implicitly case insensitive.

In other words, does [where 'XYZ' = 'xyz'] resolve to true?
Returns:True if comparisons are case insensitive.
Since:3.2
/** * Are string comparisons implicitly case insensitive. * <p/> * In other words, does [where 'XYZ' = 'xyz'] resolve to true? * * @return True if comparisons are case insensitive. * @since 3.2 */
public boolean areStringComparisonsCaseInsensitive() { return false; }
Is this dialect known to support what ANSI-SQL terms "row value constructor" syntax; sometimes called tuple syntax.

Basically, does it support syntax like "... where (FIRST_NAME, LAST_NAME) = ('Steve', 'Ebersole') ...".
Returns:True if this SQL dialect is known to support "row value constructor" syntax; false otherwise.
Since:3.2
/** * Is this dialect known to support what ANSI-SQL terms "row value * constructor" syntax; sometimes called tuple syntax. * <p/> * Basically, does it support syntax like * "... where (FIRST_NAME, LAST_NAME) = ('Steve', 'Ebersole') ...". * * @return True if this SQL dialect is known to support "row value * constructor" syntax; false otherwise. * @since 3.2 */
public boolean supportsRowValueConstructorSyntax() { // return false here, as most databases do not properly support this construct... return false; }
If the dialect supports row values, does it offer such support in IN lists as well?

For example, "... where (FIRST_NAME, LAST_NAME) IN ( (?, ?), (?, ?) ) ..."
Returns:True if this SQL dialect is known to support "row value constructor" syntax in the IN list; false otherwise.
Since:3.2
/** * If the dialect supports {@link #supportsRowValueConstructorSyntax() row values}, * does it offer such support in IN lists as well? * <p/> * For example, "... where (FIRST_NAME, LAST_NAME) IN ( (?, ?), (?, ?) ) ..." * * @return True if this SQL dialect is known to support "row value * constructor" syntax in the IN list; false otherwise. * @since 3.2 */
public boolean supportsRowValueConstructorSyntaxInInList() { return false; }
Should LOBs (both BLOB and CLOB) be bound using stream operations (i.e. PreparedStatement.setBinaryStream).
Returns:True if BLOBs and CLOBs should be bound using stream operations.
Since:3.2
/** * Should LOBs (both BLOB and CLOB) be bound using stream operations (i.e. * {@link java.sql.PreparedStatement#setBinaryStream}). * * @return True if BLOBs and CLOBs should be bound using stream operations. * @since 3.2 */
public boolean useInputStreamToInsertBlob() { return true; }
Does this dialect support parameters within the SELECT clause of INSERT ... SELECT ... statements?
Returns:True if this is supported; false otherwise.
Since:3.2
/** * Does this dialect support parameters within the <tt>SELECT</tt> clause of * <tt>INSERT ... SELECT ...</tt> statements? * * @return True if this is supported; false otherwise. * @since 3.2 */
public boolean supportsParametersInInsertSelect() { return true; }
Does this dialect require that references to result variables (i.e, select expresssion aliases) in an ORDER BY clause be replaced by column positions (1-origin) as defined by the select clause?
Returns:true if result variable references in the ORDER BY clause should be replaced by column positions; false otherwise.
/** * Does this dialect require that references to result variables * (i.e, select expresssion aliases) in an ORDER BY clause be * replaced by column positions (1-origin) as defined * by the select clause? * @return true if result variable references in the ORDER BY * clause should be replaced by column positions; * false otherwise. */
public boolean replaceResultVariableInOrderByClauseWithPosition() { return false; }
Renders an ordering fragment
Params:
  • expression – The SQL order expression. In case of @OrderBy annotation user receives property placeholder (e.g. attribute name enclosed in '{' and '}' signs).
  • collation – Collation string in format collate IDENTIFIER, or null if expression has not been explicitly specified.
  • order – Order direction. Possible values: asc, desc, or null if expression has not been explicitly specified.
  • nulls – Nulls precedence. Default value: NullPrecedence.NONE.
Returns:Renders single element of ORDER BY clause.
/** * Renders an ordering fragment * * @param expression The SQL order expression. In case of {@code @OrderBy} annotation user receives property placeholder * (e.g. attribute name enclosed in '{' and '}' signs). * @param collation Collation string in format {@code collate IDENTIFIER}, or {@code null} * if expression has not been explicitly specified. * @param order Order direction. Possible values: {@code asc}, {@code desc}, or {@code null} * if expression has not been explicitly specified. * @param nulls Nulls precedence. Default value: {@link NullPrecedence#NONE}. * @return Renders single element of {@code ORDER BY} clause. */
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nulls) { final StringBuilder orderByElement = new StringBuilder( expression ); if ( collation != null ) { orderByElement.append( " " ).append( collation ); } if ( order != null ) { orderByElement.append( " " ).append( order ); } if ( nulls != NullPrecedence.NONE ) { orderByElement.append( " nulls " ).append( nulls.name().toLowerCase(Locale.ROOT) ); } return orderByElement.toString(); }
Does this dialect require that parameters appearing in the SELECT clause be wrapped in cast() calls to tell the db parser the expected type.
Returns:True if select clause parameter must be cast()ed
Since:3.2
/** * Does this dialect require that parameters appearing in the <tt>SELECT</tt> clause be wrapped in <tt>cast()</tt> * calls to tell the db parser the expected type. * * @return True if select clause parameter must be cast()ed * @since 3.2 */
public boolean requiresCastingOfParametersInSelectClause() { return false; }
Does this dialect support asking the result set its positioning information on forward only cursors. Specifically, in the case of scrolling fetches, Hibernate needs to use ResultSet.isAfterLast and ResultSet.isBeforeFirst. Certain drivers do not allow access to these methods for forward only cursors.

NOTE : this is highly driver dependent!
Returns:True if methods like ResultSet.isAfterLast and ResultSet.isBeforeFirst are supported for forward only cursors; false otherwise.
Since:3.2
/** * Does this dialect support asking the result set its positioning * information on forward only cursors. Specifically, in the case of * scrolling fetches, Hibernate needs to use * {@link java.sql.ResultSet#isAfterLast} and * {@link java.sql.ResultSet#isBeforeFirst}. Certain drivers do not * allow access to these methods for forward only cursors. * <p/> * NOTE : this is highly driver dependent! * * @return True if methods like {@link java.sql.ResultSet#isAfterLast} and * {@link java.sql.ResultSet#isBeforeFirst} are supported for forward * only cursors; false otherwise. * @since 3.2 */
public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() { return true; }
Does this dialect support definition of cascade delete constraints which can cause circular chains?
Returns:True if circular cascade delete constraints are supported; false otherwise.
Since:3.2
/** * Does this dialect support definition of cascade delete constraints * which can cause circular chains? * * @return True if circular cascade delete constraints are supported; false * otherwise. * @since 3.2 */
public boolean supportsCircularCascadeDeleteConstraints() { return true; }
Are subselects supported as the left-hand-side (LHS) of IN-predicates.

In other words, is syntax like "... IN (1, 2, 3) ..." supported?
Returns:True if subselects can appear as the LHS of an in-predicate; false otherwise.
Since:3.2
/** * Are subselects supported as the left-hand-side (LHS) of * IN-predicates. * <p/> * In other words, is syntax like "... <subquery> IN (1, 2, 3) ..." supported? * * @return True if subselects can appear as the LHS of an in-predicate; * false otherwise. * @since 3.2 */
public boolean supportsSubselectAsInPredicateLHS() { return true; }
Expected LOB usage pattern is such that I can perform an insert via prepared statement with a parameter binding for a LOB value without crazy casting to JDBC driver implementation-specific classes...

Part of the trickiness here is the fact that this is largely driver dependent. For example, Oracle (which is notoriously bad with LOB support in their drivers historically) actually does a pretty good job with LOB support as of the 10.2.x versions of their drivers...
Returns:True if normal LOB usage patterns can be used with this driver; false if driver-specific hookiness needs to be applied.
Since:3.2
/** * Expected LOB usage pattern is such that I can perform an insert * via prepared statement with a parameter binding for a LOB value * without crazy casting to JDBC driver implementation-specific classes... * <p/> * Part of the trickiness here is the fact that this is largely * driver dependent. For example, Oracle (which is notoriously bad with * LOB support in their drivers historically) actually does a pretty good * job with LOB support as of the 10.2.x versions of their drivers... * * @return True if normal LOB usage patterns can be used with this driver; * false if driver-specific hookiness needs to be applied. * @since 3.2 */
public boolean supportsExpectedLobUsagePattern() { return true; }
Does the dialect support propagating changes to LOB values back to the database? Talking about mutating the internal value of the locator as opposed to supplying a new locator instance...

For BLOBs, the internal value might be changed by: Blob.setBinaryStream, Blob.setBytes(long, byte[]), Blob.setBytes(long, byte[], int, int), or Blob.truncate(long).

For CLOBs, the internal value might be changed by: Clob.setAsciiStream(long), Clob.setCharacterStream(long), Clob.setString(long, String), Clob.setString(long, String, int, int), or Clob.truncate(long).

NOTE : I do not know the correct answer currently for databases which (1) are not part of the cruise control process or (2) do not supportsExpectedLobUsagePattern.
Returns:True if the changes are propagated back to the database; false otherwise.
Since:3.2
/** * Does the dialect support propagating changes to LOB * values back to the database? Talking about mutating the * internal value of the locator as opposed to supplying a new * locator instance... * <p/> * For BLOBs, the internal value might be changed by: * {@link java.sql.Blob#setBinaryStream}, * {@link java.sql.Blob#setBytes(long, byte[])}, * {@link java.sql.Blob#setBytes(long, byte[], int, int)}, * or {@link java.sql.Blob#truncate(long)}. * <p/> * For CLOBs, the internal value might be changed by: * {@link java.sql.Clob#setAsciiStream(long)}, * {@link java.sql.Clob#setCharacterStream(long)}, * {@link java.sql.Clob#setString(long, String)}, * {@link java.sql.Clob#setString(long, String, int, int)}, * or {@link java.sql.Clob#truncate(long)}. * <p/> * NOTE : I do not know the correct answer currently for * databases which (1) are not part of the cruise control process * or (2) do not {@link #supportsExpectedLobUsagePattern}. * * @return True if the changes are propagated back to the * database; false otherwise. * @since 3.2 */
public boolean supportsLobValueChangePropogation() { // todo : pretty sure this is the same as the java.sql.DatabaseMetaData.locatorsUpdateCopy method added in JDBC 4, see HHH-6046 return true; }
Is it supported to materialize a LOB locator outside the transaction in which it was created?

Again, part of the trickiness here is the fact that this is largely driver dependent.

NOTE: all database I have tested which supportsExpectedLobUsagePattern() also support the ability to materialize a LOB outside the owning transaction...
Returns:True if unbounded materialization is supported; false otherwise.
Since:3.2
/** * Is it supported to materialize a LOB locator outside the transaction in * which it was created? * <p/> * Again, part of the trickiness here is the fact that this is largely * driver dependent. * <p/> * NOTE: all database I have tested which {@link #supportsExpectedLobUsagePattern()} * also support the ability to materialize a LOB outside the owning transaction... * * @return True if unbounded materialization is supported; false otherwise. * @since 3.2 */
public boolean supportsUnboundedLobLocatorMaterialization() { return true; }
Does this dialect support referencing the table being mutated in a subquery. The "table being mutated" is the table referenced in an UPDATE or a DELETE query. And so can that table then be referenced in a subquery of said UPDATE/DELETE query.

For example, would the following two syntaxes be supported:
  • delete from TABLE_A where ID not in ( select ID from TABLE_A )
  • update TABLE_A set NON_ID = 'something' where ID in ( select ID from TABLE_A)
Returns:True if this dialect allows references the mutating table from a subquery.
/** * Does this dialect support referencing the table being mutated in * a subquery. The "table being mutated" is the table referenced in * an UPDATE or a DELETE query. And so can that table then be * referenced in a subquery of said UPDATE/DELETE query. * <p/> * For example, would the following two syntaxes be supported:<ul> * <li>delete from TABLE_A where ID not in ( select ID from TABLE_A )</li> * <li>update TABLE_A set NON_ID = 'something' where ID in ( select ID from TABLE_A)</li> * </ul> * * @return True if this dialect allows references the mutating table from * a subquery. */
public boolean supportsSubqueryOnMutatingTable() { return true; }
Does the dialect support an exists statement in the select clause?
Returns:True if exists checks are allowed in the select clause; false otherwise.
/** * Does the dialect support an exists statement in the select clause? * * @return True if exists checks are allowed in the select clause; false otherwise. */
public boolean supportsExistsInSelect() { return true; }
For the underlying database, is READ_COMMITTED isolation implemented by forcing readers to wait for write locks to be released?
Returns:True if writers block readers to achieve READ_COMMITTED; false otherwise.
/** * For the underlying database, is READ_COMMITTED isolation implemented by * forcing readers to wait for write locks to be released? * * @return True if writers block readers to achieve READ_COMMITTED; false otherwise. */
public boolean doesReadCommittedCauseWritersToBlockReaders() { return false; }
For the underlying database, is REPEATABLE_READ isolation implemented by forcing writers to wait for read locks to be released?
Returns:True if readers block writers to achieve REPEATABLE_READ; false otherwise.
/** * For the underlying database, is REPEATABLE_READ isolation implemented by * forcing writers to wait for read locks to be released? * * @return True if readers block writers to achieve REPEATABLE_READ; false otherwise. */
public boolean doesRepeatableReadCauseReadersToBlockWriters() { return false; }
Does this dialect support using a JDBC bind parameter as an argument to a function or procedure call?
Returns:Returns true if the database supports accepting bind params as args, false otherwise. The default is true.
/** * Does this dialect support using a JDBC bind parameter as an argument * to a function or procedure call? * * @return Returns {@code true} if the database supports accepting bind params as args, {@code false} otherwise. The * default is {@code true}. */
@SuppressWarnings( {"UnusedDeclaration"}) public boolean supportsBindAsCallableArgument() { return true; }
Does this dialect support `count(a,b)`?
Returns:True if the database supports counting tuples; false otherwise.
/** * Does this dialect support `count(a,b)`? * * @return True if the database supports counting tuples; false otherwise. */
public boolean supportsTupleCounts() { return false; }
Does this dialect support `count(distinct a,b)`?
Returns:True if the database supports counting distinct tuples; false otherwise.
/** * Does this dialect support `count(distinct a,b)`? * * @return True if the database supports counting distinct tuples; false otherwise. */
public boolean supportsTupleDistinctCounts() { // oddly most database in fact seem to, so true is the default. return true; }
If supportsTupleDistinctCounts() is true, does the Dialect require the tuple to be wrapped with parens?
Returns:boolean
/** * If {@link #supportsTupleDistinctCounts()} is true, does the Dialect require the tuple to be wrapped with parens? * * @return boolean */
public boolean requiresParensForTupleDistinctCounts() { return false; }
Return the limit that the underlying database places on the number elements in an IN predicate. If the database defines no such limits, simply return zero or less-than-zero.
Returns:int The limit, or zero-or-less to indicate no limit.
/** * Return the limit that the underlying database places on the number elements in an {@code IN} predicate. * If the database defines no such limits, simply return zero or less-than-zero. * * @return int The limit, or zero-or-less to indicate no limit. */
public int getInExpressionCountLimit() { return 0; }
HHH-4635 Oracle expects all Lob values to be last in inserts and updates.
Returns:boolean True of Lob values should be last, false if it does not matter.
/** * HHH-4635 * Oracle expects all Lob values to be last in inserts and updates. * * @return boolean True of Lob values should be last, false if it * does not matter. */
public boolean forceLobAsLastValue() { return false; }
Some dialects have trouble applying pessimistic locking depending upon what other query options are specified (paging, ordering, etc). This method allows these dialects to request that locking be applied by subsequent selects.
Returns:true indicates that the dialect requests that locking be applied by subsequent select; false (the default) indicates that locking should be applied to the main SQL statement..
/** * Some dialects have trouble applying pessimistic locking depending upon what other query options are * specified (paging, ordering, etc). This method allows these dialects to request that locking be applied * by subsequent selects. * * @return {@code true} indicates that the dialect requests that locking be applied by subsequent select; * {@code false} (the default) indicates that locking should be applied to the main SQL statement.. */
public boolean useFollowOnLocking() { return false; }
Negate an expression
Params:
  • expression – The expression to negate
Returns:The negated expression
/** * Negate an expression * * @param expression The expression to negate * * @return The negated expression */
public String getNotExpression(String expression) { return "not " + expression; }
Get the UniqueDelegate supported by this dialect
Returns:The UniqueDelegate
/** * Get the UniqueDelegate supported by this dialect * * @return The UniqueDelegate */
public UniqueDelegate getUniqueDelegate() { return uniqueDelegate; }
Does this dialect support the UNIQUE column syntax?
Returns:boolean
Deprecated:getUniqueDelegate() should be overridden instead.
/** * Does this dialect support the <tt>UNIQUE</tt> column syntax? * * @return boolean * * @deprecated {@link #getUniqueDelegate()} should be overridden instead. */
@Deprecated public boolean supportsUnique() { return true; }
Does this dialect support adding Unique constraints via create and alter table ?
Returns:boolean
Deprecated:getUniqueDelegate() should be overridden instead.
/** * Does this dialect support adding Unique constraints via create and alter table ? * * @return boolean * * @deprecated {@link #getUniqueDelegate()} should be overridden instead. */
@Deprecated public boolean supportsUniqueConstraintInCreateAlterTable() { return true; }
The syntax used to add a unique constraint to a table.
Params:
  • constraintName – The name of the unique constraint.
Returns:The "add unique" fragment
Deprecated:getUniqueDelegate() should be overridden instead.
/** * The syntax used to add a unique constraint to a table. * * @param constraintName The name of the unique constraint. * @return The "add unique" fragment * * @deprecated {@link #getUniqueDelegate()} should be overridden instead. */
@Deprecated public String getAddUniqueConstraintString(String constraintName) { return " add constraint " + constraintName + " unique "; }
Is the combination of not-null and unique supported?
Returns:deprecated
Deprecated:getUniqueDelegate() should be overridden instead.
/** * Is the combination of not-null and unique supported? * * @return deprecated * * @deprecated {@link #getUniqueDelegate()} should be overridden instead. */
@Deprecated public boolean supportsNotNullUnique() { return true; }
Apply a hint to the query. The entire query is provided, allowing the Dialect full control over the placement and syntax of the hint. By default, ignore the hint and simply return the query.
Params:
  • query – The query to which to apply the hint.
  • hints – The hints to apply
Returns:The modified SQL
/** * Apply a hint to the query. The entire query is provided, allowing the Dialect full control over the placement * and syntax of the hint. By default, ignore the hint and simply return the query. * * @param query The query to which to apply the hint. * @param hints The hints to apply * @return The modified SQL */
public String getQueryHintString(String query, List<String> hints) { return query; }
Certain dialects support a subset of ScrollModes. Provide a default to be used by Criteria and Query.
Returns:ScrollMode
/** * Certain dialects support a subset of ScrollModes. Provide a default to be used by Criteria and Query. * * @return ScrollMode */
public ScrollMode defaultScrollMode() { return ScrollMode.SCROLL_INSENSITIVE; }
Does this dialect support tuples in subqueries? Ex: delete from Table1 where (col1, col2) in (select col1, col2 from Table2)
Returns:boolean
/** * Does this dialect support tuples in subqueries? Ex: * delete from Table1 where (col1, col2) in (select col1, col2 from Table2) * * @return boolean */
public boolean supportsTuplesInSubqueries() { return true; } public CallableStatementSupport getCallableStatementSupport() { // most databases do not support returning cursors (ref_cursor)... return StandardCallableStatementSupport.NO_REF_CURSOR_INSTANCE; } }