⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dialect.java

📁 hibernate-3.1.3-all-src.zip 面向对象的访问数据库工具
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//$Id: Dialect.java 9165 2006-01-28 12:07:25Z steveebersole $
package org.hibernate.dialect;

import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
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.StandardSQLFunction;
import org.hibernate.engine.Mapping;
import org.hibernate.exception.SQLExceptionConverter;
import org.hibernate.exception.SQLStateConverter;
import org.hibernate.exception.ViolatedConstraintNameExtracter;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.SequenceGenerator;
import org.hibernate.id.TableHiLoGenerator;
import org.hibernate.mapping.Column;
import org.hibernate.sql.ANSICaseFragment;
import org.hibernate.sql.ANSIJoinFragment;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.Type;
import org.hibernate.util.ReflectHelper;
import org.hibernate.util.StringHelper;

/**
 * Represents a dialect of SQL implemented by a particular RDBMS.
 * Subclasses implement Hibernate compatibility with different systems.<br>
 * <br>
 * Subclasses should provide a public default constructor that <tt>register()</tt>
 * a set of type mappings and default Hibernate properties.<br>
 * <br>
 * Subclasses should be immutable.
 *
 * @author Gavin King, David Channon
 */
public abstract class Dialect {

	private static final Log log = LogFactory.getLog( Dialect.class );

	static final String DEFAULT_BATCH_SIZE = "15";
	static final String NO_BATCH = "0";

	private static final Map STANDARD_AGGREGATE_FUNCTIONS = new HashMap();

	static {
		STANDARD_AGGREGATE_FUNCTIONS.put( "count", new StandardSQLFunction("count") {
			public Type getReturnType(Type columnType, Mapping mapping) {
				return Hibernate.INTEGER;
			}
		} );

		STANDARD_AGGREGATE_FUNCTIONS.put( "avg", new StandardSQLFunction("avg") {
			public Type getReturnType(Type columnType, Mapping mapping) throws QueryException {
				int[] sqlTypes;
				try {
					sqlTypes = columnType.sqlTypes( mapping );
				}
				catch ( MappingException me ) {
					throw new QueryException( me );
				}
				if ( sqlTypes.length != 1 ) throw new QueryException( "multi-column type in avg()" );
				int sqlType = sqlTypes[0];
				if ( sqlType == Types.INTEGER || sqlType == Types.BIGINT || sqlType == Types.TINYINT ) {
					return Hibernate.FLOAT;
				}
				else {
					return columnType;
				}
			}
		} );

		STANDARD_AGGREGATE_FUNCTIONS.put( "max", new StandardSQLFunction("max") );
		STANDARD_AGGREGATE_FUNCTIONS.put( "min", new StandardSQLFunction("min") );
		STANDARD_AGGREGATE_FUNCTIONS.put( "sum", new StandardSQLFunction("sum") );
	}

	private final TypeNames typeNames = new TypeNames();
	private final TypeNames hibernateTypeNames = new TypeNames();

	private final Properties properties = new Properties();
	private final Map sqlFunctions = new HashMap();
	private final Set sqlKeywords = new HashSet();

	
	protected Dialect() {
		log.info( "Using dialect: " + this );
		sqlFunctions.putAll( STANDARD_AGGREGATE_FUNCTIONS );

		// standard sql92 functions (can be overridden by subclasses)
		registerFunction( "substring", new SQLFunctionTemplate( Hibernate.STRING, "substring(?1, ?2, ?3)" ) );
		registerFunction( "locate", new SQLFunctionTemplate( Hibernate.INTEGER, "locate(?1, ?2, ?3)" ) );
		registerFunction( "trim", new SQLFunctionTemplate( Hibernate.STRING, "trim(?1 ?2 ?3 ?4)" ) );
		registerFunction( "length", new StandardSQLFunction( "length", Hibernate.INTEGER ) );
		registerFunction( "bit_length", new StandardSQLFunction( "bit_length", Hibernate.INTEGER ) );
		registerFunction( "coalesce", new StandardSQLFunction( "coalesce" ) );
		registerFunction( "nullif", new StandardSQLFunction( "nullif" ) );
		registerFunction( "abs", new StandardSQLFunction( "abs" ) );
		registerFunction( "mod", new StandardSQLFunction( "mod", Hibernate.INTEGER) );
		registerFunction( "sqrt", new StandardSQLFunction( "sqrt", Hibernate.DOUBLE) );
		registerFunction( "upper", new StandardSQLFunction("upper") );
		registerFunction( "lower", new StandardSQLFunction("lower") );
		registerFunction( "cast", new CastFunction() );
		registerFunction( "extract", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(?1 ?2 ?3)") );
		
		//map second/minute/hour/day/month/year to ANSI extract(), override on subclasses
		registerFunction( "second", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(second from ?1)") );
		registerFunction( "minute", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(minute from ?1)") );
		registerFunction( "hour", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(hour from ?1)") );
		registerFunction( "day", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(day from ?1)") );
		registerFunction( "month", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(month from ?1)") );
		registerFunction( "year", new SQLFunctionTemplate(Hibernate.INTEGER, "extract(year from ?1)") );
		
		registerFunction( "str", new SQLFunctionTemplate(Hibernate.STRING, "cast(?1 as char)") );

        // register hibernate types for default use in scalar sqlquery type auto detection
		registerHibernateType( Types.BIGINT, Hibernate.BIG_INTEGER.getName() );
		registerHibernateType( Types.BINARY, Hibernate.BINARY.getName() );
		registerHibernateType( Types.BIT, Hibernate.BOOLEAN.getName() );
		registerHibernateType( Types.CHAR, Hibernate.CHARACTER.getName() );
		registerHibernateType( Types.DATE, Hibernate.DATE.getName() );
		registerHibernateType( Types.DOUBLE, Hibernate.DOUBLE.getName() );
		registerHibernateType( Types.FLOAT, Hibernate.FLOAT.getName() );
		registerHibernateType( Types.INTEGER, Hibernate.INTEGER.getName() );
		registerHibernateType( Types.SMALLINT, Hibernate.SHORT.getName() );
		registerHibernateType( Types.TINYINT, Hibernate.BYTE.getName() );
		registerHibernateType( Types.TIME, Hibernate.TIME.getName() );
		registerHibernateType( Types.TIMESTAMP, Hibernate.TIMESTAMP.getName() );
		registerHibernateType( Types.VARCHAR, Hibernate.STRING.getName() );
		registerHibernateType( Types.VARBINARY, Hibernate.BINARY.getName() );
		registerHibernateType( Types.NUMERIC, Hibernate.BIG_DECIMAL.getName() );
		registerHibernateType( Types.BLOB, Hibernate.BLOB.getName() );
		registerHibernateType( Types.CLOB, Hibernate.CLOB.getName() );
		
	}

	public String toString() {
		return getClass().getName();
	}

	/**
	 * Characters used for quoting SQL identifiers
	 */
	public static final String QUOTE = "`\"[";
	public static final String CLOSED_QUOTE = "`\"]";


	/**
	 * Get the name of the database type associated with the given
	 * <tt>java.sql.Types</tt> typecode.
	 *
	 * @param code <tt>java.sql.Types</tt> typecode
	 * @return the database type name
	 * @throws HibernateException
	 */
	public String getTypeName(int code) throws HibernateException {
		String result = typeNames.get( code );
		if ( result == null ) {
			throw new HibernateException( "No default type mapping for (java.sql.Types) " + code );
		}
		return result;
	}

	
	public String getHibernateTypeName(int code) throws HibernateException {
		String result = hibernateTypeNames.get( code );
		if ( result == null ) {
			throw new HibernateException( 
					"No Hibernate type mapping for java.sql.Types code: " +
					code);
		}
		return result;
	}

	public String getHibernateTypeName(int code, int length, int precision, int scale) throws HibernateException {
		String result = hibernateTypeNames.get( code, length, precision, scale );
		if ( result == null ) {
			throw new HibernateException( 
					"No Hibernate type mapping for java.sql.Types code: " +
					code +
					", length: " +
					length 
				);
		}
		return result;		
	}

	/**
	 * Get the name of the database type associated with the given
	 * <tt>java.sql.Types</tt> typecode.
	 * @param code      <tt>java.sql.Types</tt> typecode
	 * @param length    the length or precision of the column
	 * @param precision the precision of the column
	 * @param scale the scale of the column
	 *
	 * @return the database type name
	 * @throws HibernateException
	 */
	public String getTypeName(int code, int length, int precision, int scale) throws HibernateException {
		String result = typeNames.get( code, length, precision, scale );
		if ( result == null ) {
			throw new HibernateException( 
					"No type mapping for java.sql.Types code: " +
					code +
					", length: " +
					length 
				);
		}
		return result;
	}
	
	public String getCastTypeName(int code) {
		return getTypeName(
				code, 
				Column.DEFAULT_LENGTH, 
				Column.DEFAULT_PRECISION, 
				Column.DEFAULT_SCALE 
			);
	}

	protected void registerFunction(String name, SQLFunction function) {
		sqlFunctions.put( name, function );
	}

	protected void registerKeyword(String word) {
		sqlKeywords.add(word);
	}
	
	public Set getKeywords() {
		return sqlKeywords;
	}

	/**
	 * Subclasses register a typename 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     <tt>java.sql.Types</tt> typecode
	 * @param capacity maximum length of database type
	 * @param name     the database type name
	 */
	protected void registerColumnType(int code, int capacity, String name) {
		typeNames.put( code, capacity, name );
	}

	/**
	 * Subclasses register a typename for the given type code. <tt>$l</tt> in
	 * the type name with be replaced by the column length (if appropriate).
	 *
	 * @param code <tt>java.sql.Types</tt> typecode
	 * @param name the database type name
	 */
	protected void registerColumnType(int code, String name) {
		typeNames.put( code, name );
	}
	
	protected void registerHibernateType(int sqlcode, String name) {
		hibernateTypeNames.put( sqlcode, name);
	}

	protected void registerHibernateType(int sqlcode, int capacity, String name) {
		hibernateTypeNames.put( sqlcode, capacity, name);
	}

	/**
	 * Does this dialect support the <tt>ALTER TABLE</tt> syntax?
	 *
	 * @return boolean
	 */
	public boolean hasAlterTable() {
		return true;
	}

	/**
	 * Do we need to drop constraints before dropping tables in this dialect?
	 *
	 * @return boolean
	 */
	public boolean dropConstraints() {
		return true;
	}

	/**
	 * Do we need to qualify index names with the schema name?
	 *
	 * @return boolean
	 */
	public boolean qualifyIndexName() {
		return true;
	}

	/**
	 * Does the <tt>FOR UPDATE OF</tt> syntax specify particular
	 * columns?
	 */
	public boolean forUpdateOfColumns() {
		return false;
	}

	/**
	 * Retrieves the <tt>FOR UPDATE OF column_list</tt> syntax specific to this
	 * dialect, where the given aliases represent the aliases of the columns
	 * which are to be write locked.
	 *
	 * @return The appropriate <tt>FOR UPDATE OF column_list</tt> clause string.
	 */
	public String getForUpdateString(String aliases) {
		return getForUpdateString();
	}

	/**
	 * Retrieves the <tt>FOR UPDATE OF column_list NOWAIT</tt> syntax specific
	 * to this dialect, where the given aliases represent the aliases of the
	 * columns which are to be write locked.
	 *
	 * @return The appropriate <tt>FOR UPDATE colunm_list</tt> NOWAIT clause string.
	 */
	public String getForUpdateNowaitString(String aliases) {
		return getForUpdateString( aliases );
	}

	/**
	 * Retrieves the <tt>FOR UPDATE</tt> syntax specific to this dialect.
	 *
	 * @return The appropriate <tt>FOR UPDATE</tt> clause string.
	 */
	public String getForUpdateString() {
		return " for update";
	}

	/**
	 * 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() {
		return getForUpdateString();
	}

	/**
	 * Does this dialect support the <tt>UNIQUE</tt> column syntax?
	 *
	 * @return boolean
	 */
	public boolean supportsUnique() {
		return true;
	}
	

    /**
     * Does this dialect support adding Unique constraints via create and alter table ?
     * @return boolean
     */
	public boolean supportsUniqueConstraintInCreateAlterTable() {
	    return true;
	}


	/**
	 * The syntax used to add a column to a table (optional).
	 */
	public String getAddColumnString() {
		throw new UnsupportedOperationException( "No add column syntax supported by Dialect" );
	}

	public String getDropForeignKeyString() {
		return " drop constraint ";
	}

	public String getTableTypeString() {
		return "";
	}

	/**
	 * The syntax used to add a foreign key constraint to a table.
	 * 
	 * @param referencesPrimaryKey if false, constraint should be 
	 * explicit about which column names the constraint refers to
	 *
	 * @return String
	 */
	public String getAddForeignKeyConstraintString(
			String constraintName,
			String[] foreignKey,
			String referencedTable,
			String[] primaryKey, 
			boolean referencesPrimaryKey
	) {
		StringBuffer res = new StringBuffer( 30 );
		
		res.append( " add constraint " )
		   .append( 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.
	 *
	 * @return String
	 */
	public String getAddPrimaryKeyConstraintString(String constraintName) {
		return " add constraint " + constraintName + " primary key ";
	}

	/**
	 * The keyword used to specify a nullable column.
	 *
	 * @return String
	 */
	public String getNullColumnString() {
		return "";
	}

	/**
	 * Does this dialect support identity column key generation?
	 *
	 * @return boolean
	 */
	public boolean supportsIdentityColumns() {
		return false;
	}

	/**
	 * Does this dialect support sequences?
	 *
	 * @return boolean
	 */
	public boolean supportsSequences() {
		return false;
	}

	public boolean supportsInsertSelectIdentity() {
		return false;
	}

	/**
	 * Append a clause to retrieve the generated identity value for the
	 * given <tt>INSERT</tt> statement.
	 */
	public String appendIdentitySelectToInsert(String insertString) {
		return insertString;
	}

	protected String getIdentitySelectString() throws MappingException {
		throw new MappingException( "Dialect does not support identity key generation" );
	}

	/**
	 * The syntax that returns the identity value of the last insert, if
	 * identity column key generation is supported.
	 *
	 * @param type TODO
	 * @throws MappingException if no native key generation
	 */
	public String getIdentitySelectString(String table, String column, int type)
			throws MappingException {
		return getIdentitySelectString();
	}

	protected String getIdentityColumnString() throws MappingException {
		throw new MappingException( "Dialect does not support identity key generation" );
	}

	/**
	 * The keyword used to specify an identity column, if identity
	 * column key generation is supported.
	 *
	 * @param type the SQL column type, as defined by <tt>java.sql.Types</tt>
	 * @throws MappingException if no native key generation
	 */
	public String getIdentityColumnString(int type) throws MappingException {
		return getIdentityColumnString();
	}

	/**
	 * 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 String
	 */
	public String getIdentityInsertString() {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -