All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.dialect.DerbyDialect Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.dialect;

import java.lang.reflect.Method;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Locale;

import org.hibernate.MappingException;
import org.hibernate.dialect.function.AnsiTrimFunction;
import org.hibernate.dialect.function.DerbyConcatFunction;
import org.hibernate.dialect.pagination.AbstractLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.LimitHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.spi.RowSelection;
import org.hibernate.hql.spi.id.IdTableSupportStandardImpl;
import org.hibernate.hql.spi.id.MultiTableBulkIdStrategy;
import org.hibernate.hql.spi.id.local.AfterUseAction;
import org.hibernate.hql.spi.id.local.LocalTemporaryTableBulkIdStrategy;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DerbyCaseFragment;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorDerbyDatabaseImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;

import org.jboss.logging.Logger;

/**
 * Hibernate Dialect for Cloudscape 10 - aka Derby. This implements both an
 * override for the identity column generator as well as for the case statement
 * issue documented at:
 * http://www.jroller.com/comments/kenlars99/Weblog/cloudscape_soon_to_be_derby
 *
 * @author Simon Johnston
 *
 * @deprecated HHH-6073
 */
@Deprecated
public class DerbyDialect extends DB2Dialect {
	@SuppressWarnings("deprecation")
	private static final CoreMessageLogger LOG = Logger.getMessageLogger(
			CoreMessageLogger.class,
			DerbyDialect.class.getName()
	);

	private int driverVersionMajor;
	private int driverVersionMinor;
	private final LimitHandler limitHandler;

	/**
	 * Constructs a DerbyDialect
	 */
	@SuppressWarnings("deprecation")
	public DerbyDialect() {
		super();
		if ( this.getClass() == DerbyDialect.class ) {
			LOG.deprecatedDerbyDialect();
		}

		registerFunction( "concat", new DerbyConcatFunction() );
		registerFunction( "trim", new AnsiTrimFunction() );
		registerColumnType( Types.BLOB, "blob" );
		registerDerbyKeywords();
		determineDriverVersion();

		if ( driverVersionMajor > 10 || ( driverVersionMajor == 10 && driverVersionMinor >= 7 ) ) {
			registerColumnType( Types.BOOLEAN, "boolean" );
		}

		this.limitHandler = new DerbyLimitHandler();
	}

	private void determineDriverVersion() {
		try {
			// locate the derby sysinfo class and query its version info
			final Class sysinfoClass = ReflectHelper.classForName( "org.apache.derby.tools.sysinfo", this.getClass() );
			final Method majorVersionGetter = sysinfoClass.getMethod( "getMajorVersion", ReflectHelper.NO_PARAM_SIGNATURE );
			final Method minorVersionGetter = sysinfoClass.getMethod( "getMinorVersion", ReflectHelper.NO_PARAM_SIGNATURE );
			driverVersionMajor = (Integer) majorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS );
			driverVersionMinor = (Integer) minorVersionGetter.invoke( null, ReflectHelper.NO_PARAMS );
		}
		catch ( Exception e ) {
			LOG.unableToLoadDerbyDriver( e.getMessage() );
			driverVersionMajor = -1;
			driverVersionMinor = -1;
		}
	}

	private boolean isTenPointFiveReleaseOrNewer() {
		return driverVersionMajor > 10 || ( driverVersionMajor == 10 && driverVersionMinor >= 5 );
	}

	@Override
	public String getCrossJoinSeparator() {
		return ", ";
	}

	@Override
	public CaseFragment createCaseFragment() {
		return new DerbyCaseFragment();
	}

	@Override
	public boolean dropConstraints() {
		return true;
	}

	@Override
	public boolean supportsSequences() {
		// technically sequence support was added in 10.6.1.0...
		//
		// The problem though is that I am not exactly sure how to differentiate 10.6.1.0 from any other 10.6.x release.
		//
		// http://db.apache.org/derby/docs/10.0/publishedapi/org/apache/derby/tools/sysinfo.html seems incorrect.  It
		// states that derby's versioning scheme is major.minor.maintenance, but obviously 10.6.1.0 has 4 components
		// to it, not 3.
		//
		// Let alone the fact that it states that versions with the matching major.minor are 'feature
		// compatible' which is clearly not the case here (sequence support is a new feature...)
		return driverVersionMajor > 10 || ( driverVersionMajor == 10 && driverVersionMinor >= 6 );
	}

	@Override
	public String getQuerySequencesString() {
		if ( supportsSequences() ) {
			return "select sys.sysschemas.schemaname as sequence_schema, sys.syssequences.* from sys.syssequences left join sys.sysschemas on sys.syssequences.schemaid = sys.sysschemas.schemaid";
		}
		else {
			return null;
		}
	}

	@Override
	public SequenceInformationExtractor getSequenceInformationExtractor() {
		if ( getQuerySequencesString() == null ) {
			return SequenceInformationExtractorNoOpImpl.INSTANCE;
		}
		else {
			return SequenceInformationExtractorDerbyDatabaseImpl.INSTANCE;
		}
	}

	@Override
	public String getSequenceNextValString(String sequenceName) {
		if ( supportsSequences() ) {
			return "values next value for " + sequenceName;
		}
		else {
			throw new MappingException( "Derby does not support sequence prior to release 10.6.1.0" );
		}
	}

	@Override
	public boolean supportsLimit() {
		return isTenPointFiveReleaseOrNewer();
	}

	@Override
	public boolean supportsCommentOn() {
		//HHH-4531
		return false;
	}

	@Override
	@SuppressWarnings("deprecation")
	public boolean supportsLimitOffset() {
		return isTenPointFiveReleaseOrNewer();
	}

	@Override
	public String getForUpdateString() {
		return " for update with rs";
	}

	@Override
	public String getWriteLockString(int timeout) {
		return " for update with rs";
	}

	@Override
	public String getReadLockString(int timeout) {
		return " for read only with rs";
	}


	@Override
	public LimitHandler getLimitHandler() {
		return limitHandler;
	}

	@Override
	public boolean supportsTuplesInSubqueries() {
		return false;
	}

	/**
	 * {@inheritDoc}
	 * 

* From Derby 10.5 Docs: *

	 * Query
	 * [ORDER BY clause]
	 * [result offset clause]
	 * [fetch first clause]
	 * [FOR UPDATE clause]
	 * [WITH {RR|RS|CS|UR}]
	 * 
*/ @Override public String getLimitString(String query, final int offset, final int limit) { final StringBuilder sb = new StringBuilder(query.length() + 50); final String normalizedSelect = query.toLowerCase(Locale.ROOT).trim(); final int forUpdateIndex = normalizedSelect.lastIndexOf( "for update") ; if ( hasForUpdateClause( forUpdateIndex ) ) { sb.append( query.substring( 0, forUpdateIndex-1 ) ); } else if ( hasWithClause( normalizedSelect ) ) { sb.append( query.substring( 0, getWithIndex( query ) - 1 ) ); } else { sb.append( query ); } if ( offset == 0 ) { sb.append( " fetch first " ); } else { sb.append( " offset " ).append( offset ).append( " rows fetch next " ); } sb.append( limit ).append( " rows only" ); if ( hasForUpdateClause( forUpdateIndex ) ) { sb.append( ' ' ); sb.append( query.substring( forUpdateIndex ) ); } else if ( hasWithClause( normalizedSelect ) ) { sb.append( ' ' ).append( query.substring( getWithIndex( query ) ) ); } return sb.toString(); } @Override public boolean supportsVariableLimit() { // we bind the limit and offset values directly into the sql... return false; } private boolean hasForUpdateClause(int forUpdateIndex) { return forUpdateIndex >= 0; } private boolean hasWithClause(String normalizedSelect){ return normalizedSelect.startsWith( "with ", normalizedSelect.length() - 7 ); } private int getWithIndex(String querySelect) { int i = querySelect.lastIndexOf( "with " ); if ( i < 0 ) { i = querySelect.lastIndexOf( "WITH " ); } return i; } // Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override public boolean supportsLobValueChangePropogation() { return false; } @Override public boolean supportsUnboundedLobLocatorMaterialization() { return false; } private final class DerbyLimitHandler extends AbstractLimitHandler { /** * {@inheritDoc} *

* From Derby 10.5 Docs: *

		 * Query
		 * [ORDER BY clause]
		 * [result offset clause]
		 * [fetch first clause]
		 * [FOR UPDATE clause]
		 * [WITH {RR|RS|CS|UR}]
		 * 
*/ @Override public String processSql(String sql, RowSelection selection) { final StringBuilder sb = new StringBuilder( sql.length() + 50 ); final String normalizedSelect = sql.toLowerCase(Locale.ROOT).trim(); final int forUpdateIndex = normalizedSelect.lastIndexOf( "for update" ); if (hasForUpdateClause( forUpdateIndex )) { sb.append( sql.substring( 0, forUpdateIndex - 1 ) ); } else if (hasWithClause( normalizedSelect )) { sb.append( sql.substring( 0, getWithIndex( sql ) - 1 ) ); } else { sb.append( sql ); } if (LimitHelper.hasFirstRow( selection )) { sb.append( " offset " ).append( selection.getFirstRow() ).append( " rows fetch next " ); } else { sb.append( " fetch first " ); } sb.append( getMaxOrLimit( selection ) ).append(" rows only" ); if (hasForUpdateClause( forUpdateIndex )) { sb.append( ' ' ); sb.append( sql.substring( forUpdateIndex ) ); } else if (hasWithClause( normalizedSelect )) { sb.append( ' ' ).append( sql.substring( getWithIndex( sql ) ) ); } return sb.toString(); } @Override public boolean supportsLimit() { return isTenPointFiveReleaseOrNewer(); } @Override @SuppressWarnings("deprecation") public boolean supportsLimitOffset() { return isTenPointFiveReleaseOrNewer(); } @Override public boolean supportsVariableLimit() { return false; } } @Override public IdentifierHelper buildIdentifierHelper( IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) throws SQLException { builder.applyIdentifierCasing( dbMetaData ); builder.applyReservedWords( dbMetaData ); builder.applyReservedWords( getKeywords() ); builder.setNameQualifierSupport( getNameQualifierSupport() ); return builder.build(); } protected void registerDerbyKeywords() { registerKeyword( "ADD" ); registerKeyword( "ALL" ); registerKeyword( "ALLOCATE" ); registerKeyword( "ALTER" ); registerKeyword( "AND" ); registerKeyword( "ANY" ); registerKeyword( "ARE" ); registerKeyword( "AS" ); registerKeyword( "ASC" ); registerKeyword( "ASSERTION" ); registerKeyword( "AT" ); registerKeyword( "AUTHORIZATION" ); registerKeyword( "AVG" ); registerKeyword( "BEGIN" ); registerKeyword( "BETWEEN" ); registerKeyword( "BIT" ); registerKeyword( "BOOLEAN" ); registerKeyword( "BOTH" ); registerKeyword( "BY" ); registerKeyword( "CALL" ); registerKeyword( "CASCADE" ); registerKeyword( "CASCADED" ); registerKeyword( "CASE" ); registerKeyword( "CAST" ); registerKeyword( "CHAR" ); registerKeyword( "CHARACTER" ); registerKeyword( "CHECK" ); registerKeyword( "CLOSE" ); registerKeyword( "COLLATE" ); registerKeyword( "COLLATION" ); registerKeyword( "COLUMN" ); registerKeyword( "COMMIT" ); registerKeyword( "CONNECT" ); registerKeyword( "CONNECTION" ); registerKeyword( "CONSTRAINT" ); registerKeyword( "CONSTRAINTS" ); registerKeyword( "CONTINUE" ); registerKeyword( "CONVERT" ); registerKeyword( "CORRESPONDING" ); registerKeyword( "COUNT" ); registerKeyword( "CREATE" ); registerKeyword( "CURRENT" ); registerKeyword( "CURRENT_DATE" ); registerKeyword( "CURRENT_TIME" ); registerKeyword( "CURRENT_TIMESTAMP" ); registerKeyword( "CURRENT_USER" ); registerKeyword( "CURSOR" ); registerKeyword( "DEALLOCATE" ); registerKeyword( "DEC" ); registerKeyword( "DECIMAL" ); registerKeyword( "DECLARE" ); registerKeyword( "DEFERRABLE" ); registerKeyword( "DEFERRED" ); registerKeyword( "DELETE" ); registerKeyword( "DESC" ); registerKeyword( "DESCRIBE" ); registerKeyword( "DIAGNOSTICS" ); registerKeyword( "DISCONNECT" ); registerKeyword( "DISTINCT" ); registerKeyword( "DOUBLE" ); registerKeyword( "DROP" ); registerKeyword( "ELSE" ); registerKeyword( "END" ); registerKeyword( "ENDEXEC" ); registerKeyword( "ESCAPE" ); registerKeyword( "EXCEPT" ); registerKeyword( "EXCEPTION" ); registerKeyword( "EXEC" ); registerKeyword( "EXECUTE" ); registerKeyword( "EXISTS" ); registerKeyword( "EXPLAIN" ); registerKeyword( "EXTERNAL" ); registerKeyword( "FALSE" ); registerKeyword( "FETCH" ); registerKeyword( "FIRST" ); registerKeyword( "FLOAT" ); registerKeyword( "FOR" ); registerKeyword( "FOREIGN" ); registerKeyword( "FOUND" ); registerKeyword( "FROM" ); registerKeyword( "FULL" ); registerKeyword( "FUNCTION" ); registerKeyword( "GET" ); registerKeyword( "GET_CURRENT_CONNECTION" ); registerKeyword( "GLOBAL" ); registerKeyword( "GO" ); registerKeyword( "GOTO" ); registerKeyword( "GRANT" ); registerKeyword( "GROUP" ); registerKeyword( "HAVING" ); registerKeyword( "HOUR" ); registerKeyword( "IDENTITY" ); registerKeyword( "IMMEDIATE" ); registerKeyword( "IN" ); registerKeyword( "INDICATOR" ); registerKeyword( "INITIALLY" ); registerKeyword( "INNER" ); registerKeyword( "INOUT" ); registerKeyword( "INPUT" ); registerKeyword( "INSENSITIVE" ); registerKeyword( "INSERT" ); registerKeyword( "INT" ); registerKeyword( "INTEGER" ); registerKeyword( "INTERSECT" ); registerKeyword( "INTO" ); registerKeyword( "IS" ); registerKeyword( "ISOLATION" ); registerKeyword( "JOIN" ); registerKeyword( "KEY" ); registerKeyword( "LAST" ); registerKeyword( "LEFT" ); registerKeyword( "LIKE" ); registerKeyword( "LONGINT" ); registerKeyword( "LOWER" ); registerKeyword( "LTRIM" ); registerKeyword( "MATCH" ); registerKeyword( "MAX" ); registerKeyword( "MIN" ); registerKeyword( "MINUTE" ); registerKeyword( "NATIONAL" ); registerKeyword( "NATURAL" ); registerKeyword( "NCHAR" ); registerKeyword( "NVARCHAR" ); registerKeyword( "NEXT" ); registerKeyword( "NO" ); registerKeyword( "NOT" ); registerKeyword( "NULL" ); registerKeyword( "NULLIF" ); registerKeyword( "NUMERIC" ); registerKeyword( "OF" ); registerKeyword( "ON" ); registerKeyword( "ONLY" ); registerKeyword( "OPEN" ); registerKeyword( "OPTION" ); registerKeyword( "OR" ); registerKeyword( "ORDER" ); registerKeyword( "OUT" ); registerKeyword( "OUTER" ); registerKeyword( "OUTPUT" ); registerKeyword( "OVERLAPS" ); registerKeyword( "PAD" ); registerKeyword( "PARTIAL" ); registerKeyword( "PREPARE" ); registerKeyword( "PRESERVE" ); registerKeyword( "PRIMARY" ); registerKeyword( "PRIOR" ); registerKeyword( "PRIVILEGES" ); registerKeyword( "PROCEDURE" ); registerKeyword( "PUBLIC" ); registerKeyword( "READ" ); registerKeyword( "REAL" ); registerKeyword( "REFERENCES" ); registerKeyword( "RELATIVE" ); registerKeyword( "RESTRICT" ); registerKeyword( "REVOKE" ); registerKeyword( "RIGHT" ); registerKeyword( "ROLLBACK" ); registerKeyword( "ROWS" ); registerKeyword( "RTRIM" ); registerKeyword( "SCHEMA" ); registerKeyword( "SCROLL" ); registerKeyword( "SECOND" ); registerKeyword( "SELECT" ); registerKeyword( "SESSION_USER" ); registerKeyword( "SET" ); registerKeyword( "SMALLINT" ); registerKeyword( "SOME" ); registerKeyword( "SPACE" ); registerKeyword( "SQL" ); registerKeyword( "SQLCODE" ); registerKeyword( "SQLERROR" ); registerKeyword( "SQLSTATE" ); registerKeyword( "SUBSTR" ); registerKeyword( "SUBSTRING" ); registerKeyword( "SUM" ); registerKeyword( "SYSTEM_USER" ); registerKeyword( "TABLE" ); registerKeyword( "TEMPORARY" ); registerKeyword( "TIMEZONE_HOUR" ); registerKeyword( "TIMEZONE_MINUTE" ); registerKeyword( "TO" ); registerKeyword( "TRAILING" ); registerKeyword( "TRANSACTION" ); registerKeyword( "TRANSLATE" ); registerKeyword( "TRANSLATION" ); registerKeyword( "TRUE" ); registerKeyword( "UNION" ); registerKeyword( "UNIQUE" ); registerKeyword( "UNKNOWN" ); registerKeyword( "UPDATE" ); registerKeyword( "UPPER" ); registerKeyword( "USER" ); registerKeyword( "USING" ); registerKeyword( "VALUES" ); registerKeyword( "VARCHAR" ); registerKeyword( "VARYING" ); registerKeyword( "VIEW" ); registerKeyword( "WHENEVER" ); registerKeyword( "WHERE" ); registerKeyword( "WITH" ); registerKeyword( "WORK" ); registerKeyword( "WRITE" ); registerKeyword( "XML" ); registerKeyword( "XMLEXISTS" ); registerKeyword( "XMLPARSE" ); registerKeyword( "XMLSERIALIZE" ); registerKeyword( "YEAR" ); } /** * {@inheritDoc} *

* From Derby docs: *

	 *     The DECLARE GLOBAL TEMPORARY TABLE statement defines a temporary table for the current connection.
	 * 
* * {@link DB2Dialect} returns a {@link org.hibernate.hql.spi.id.global.GlobalTemporaryTableBulkIdStrategy} that * will make temporary tables created at startup and hence unavailable for subsequent connections.
* see HHH-10238. *

*/ @Override public MultiTableBulkIdStrategy getDefaultMultiTableBulkIdStrategy() { return new LocalTemporaryTableBulkIdStrategy(new IdTableSupportStandardImpl() { @Override public String generateIdTableName(String baseName) { return "session." + super.generateIdTableName( baseName ); } @Override public String getCreateIdTableCommand() { return "declare global temporary table"; } @Override public String getCreateIdTableStatementOptions() { return "not logged"; } }, AfterUseAction.CLEAN, null); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy