Get rid of deprecated dialect methods, JoinFragment, LegacyLimitHandler, LegacySequenceSupport, CaseFragment, SelectFragment etc.

This commit is contained in:
Christian Beikov 2021-10-01 01:12:52 +02:00
parent f416b728a9
commit 40ccad1db2
95 changed files with 614 additions and 5422 deletions

View File

@ -242,18 +242,6 @@ public class CUBRIDDialect extends Dialect {
return SequenceInformationExtractorCUBRIDDatabaseImpl.INSTANCE;
}
@Override
public String getFromDual() {
//TODO: is this really needed?
//TODO: would "from table({0})" be better?
return "from db_root";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public char openQuote() {
return '[';
@ -284,11 +272,6 @@ public class CUBRIDDialect extends Dialect {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsIfExistsBeforeTableName() {
return true;

View File

@ -28,7 +28,6 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAppender;
@ -352,13 +351,6 @@ public class CacheDialect extends Dialect {
return " null";
}
@Override
@SuppressWarnings("deprecation")
public JoinFragment createOuterJoinFragment() {
// Create an OuterJoinGenerator for this dialect.
return new CacheJoinFragment();
}
@Override
public String getNoColumnsInsertString() {
// The keyword used to insert a row without specifying
@ -400,11 +392,6 @@ public class CacheDialect extends Dialect {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsOrderByInSubquery() {
// This is just a guess

View File

@ -1,28 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.community.dialect;
import org.hibernate.AssertionFailure;
import org.hibernate.sql.ANSIJoinFragment;
import org.hibernate.sql.JoinType;
/**
* A Cach&eacute; dialect join. Differs from ANSI only in that full outer join
* is not supported.
*
* @author Jeff Miller
* @author Jonathan Levinson
*/
public class CacheJoinFragment extends ANSIJoinFragment {
public void addJoin(String rhsTableName, String rhsAlias, String[] lhsColumns, String[] rhsColumns, JoinType joinType, String on) {
if ( joinType == JoinType.FULL_JOIN ) {
throw new AssertionFailure( "Cache does not support full outer joins" );
}
super.addJoin( rhsTableName, rhsAlias, lhsColumns, rhsColumns, joinType, on );
}
}

View File

@ -525,16 +525,6 @@ public class FirebirdDialect extends Dialect {
return getVersion() >= 200;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean requiresCastingOfParametersInSelectClause() {
return true;
}
@Override
public boolean supportsLobValueChangePropagation() {
// May need changes in Jaybird for this to work
@ -558,11 +548,6 @@ public class FirebirdDialect extends Dialect {
return 1500;
}
@Override
public boolean supportsTuplesInSubqueries() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return getVersion() >= 300;
@ -669,16 +654,6 @@ public class FirebirdDialect extends Dialect {
return false;
}
@Override
public String getFromDual() {
return "from rdb$database";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public NullOrdering getNullOrdering() {
return getVersion() >= 200 ? NullOrdering.SMALLEST : NullOrdering.LAST;

View File

@ -8,7 +8,6 @@ package org.hibernate.community.dialect;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.GroupByConstantRenderingStrategy;
import org.hibernate.dialect.Replacer;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.CaseLeastGreatestEmulation;
@ -321,16 +320,6 @@ public class InformixDialect extends Dialect {
return limitHandler;
}
@Override
public String getFromDual() {
return "from (select 0 from systables where tabid=1) as dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public boolean supportsOrderByInSubquery() {
// This is just a guess
@ -394,11 +383,6 @@ public class InformixDialect extends Dialect {
return "select distinct current timestamp from informix.systables";
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
}
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,

View File

@ -8,7 +8,6 @@ package org.hibernate.community.dialect;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.GroupByConstantRenderingStrategy;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
@ -421,12 +420,6 @@ public class IngresDialect extends Dialect {
);
}
@Override
@SuppressWarnings("deprecation")
public String getCurrentTimestampSQLFunctionName() {
return getVersion() >= 930 ? "current_timestamp" : "date(now)";
}
// union subclass support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@ -464,19 +457,6 @@ public class IngresDialect extends Dialect {
return getVersion() >= 930;
}
// limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public String getFromDual() {
//this is only necessary if the query has a where clause
return "from (select 0) as dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@ -484,11 +464,6 @@ public class IngresDialect extends Dialect {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExpectedLobUsagePattern() {
return false;
@ -515,11 +490,6 @@ public class IngresDialect extends Dialect {
}
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
}
@Override
public boolean supportsFetchClause(FetchClauseType type) {
return getVersion() >= 930;

View File

@ -21,8 +21,6 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -231,28 +229,11 @@ public class MaxDBDialect extends Dialect {
return SequenceInformationExtractorSAPDBDatabaseImpl.INSTANCE;
}
@Override
public String getFromDual() {
return "from dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public boolean supportsOffsetInSubquery() {
return true;
}
@Override
@SuppressWarnings("deprecation")
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
}
@Override
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
EntityMappingType rootEntityDescriptor,

View File

@ -251,16 +251,6 @@ public class MimerSQLDialect extends Dialect {
return OffsetFetchLimitHandler.INSTANCE;
}
@Override
public String getFromDual() {
return "from (values(0))";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public boolean supportsOuterJoinForUpdate() {
return false;

View File

@ -22,8 +22,6 @@ import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DecodeCaseFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAppender;
@ -320,27 +318,11 @@ public class RDMSOS2200Dialect extends Dialect {
return " including contents";
}
@Override
@SuppressWarnings("deprecation")
public CaseFragment createCaseFragment() {
return new DecodeCaseFragment();
}
@Override
public LimitHandler getLimitHandler() {
return FetchLimitHandler.INSTANCE;
}
@Override
public String getFromDual() {
return "from rdms.rdms_dummy where key_col=1";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public boolean supportsOrderByInSubquery() {
// This is just a guess

View File

@ -418,13 +418,6 @@ public class SQLiteDialect extends Dialect {
};
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override

View File

@ -8,7 +8,6 @@ package org.hibernate.community.dialect;
import org.hibernate.LockOptions;
import org.hibernate.dialect.GroupByConstantRenderingStrategy;
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.dialect.SybaseDialect;
import org.hibernate.dialect.identity.IdentityColumnSupport;
@ -124,26 +123,11 @@ public class SybaseAnywhereDialect extends SybaseDialect {
return false;
}
@Override
public String getFromDual() {
return "from sys.dummy";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new SybaseAnywhereIdentityColumnSupport();
}
@Override
public boolean forUpdateOfColumns() {
return getVersion() >= 1000;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return getVersion() >= 1000 ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE;
@ -183,8 +167,4 @@ public class SybaseAnywhereDialect extends SybaseDialect {
return TopLimitHandler.INSTANCE;
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
}

View File

@ -13,7 +13,6 @@ import org.hibernate.boot.model.relational.QualifiedNameImpl;
import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.GroupByConstantRenderingStrategy;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.community.dialect.identity.Teradata14IdentityColumnSupport;
@ -347,11 +346,6 @@ public class TeradataDialect extends Dialect {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsOrderByInSubquery() {
// This is just a guess
@ -604,8 +598,4 @@ public class TeradataDialect extends Dialect {
return TopLimitHandler.INSTANCE;
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
}

View File

@ -215,21 +215,11 @@ public class TimesTenDialect extends Dialect {
return SequenceInformationExtractorTimesTenDatabaseImpl.INSTANCE;
}
@Override
public String getCrossJoinSeparator() {
return ", ";
}
@Override
public boolean supportsNoWait() {
return true;
}
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return RowLockStrategy.COLUMN;
@ -359,11 +349,6 @@ public class TimesTenDialect extends Dialect {
return false;
}
@Override
public boolean supportsUniqueConstraintInCreateAlterTable() {
return false;
}
@Override
public String getSelectClauseNullString(int sqlType) {
switch (sqlType) {

View File

@ -744,6 +744,7 @@ public abstract class AbstractHANADialect extends Dialect {
this.clobTypeDescriptor = new HANAClobTypeDescriptor( MAX_LOB_PREFETCH_SIZE_DEFAULT_VALUE,
useUnicodeStringTypesDefault().booleanValue() );
// Note that 38 is the maximum precision HANA supports
registerColumnType( Types.DECIMAL, "decimal($p, $s)" );
//there is no 'numeric' type in HANA
registerColumnType( Types.NUMERIC, "decimal($p, $s)" );
@ -945,11 +946,6 @@ public abstract class AbstractHANADialect extends Dialect {
};
}
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return RowLockStrategy.COLUMN;
@ -1018,11 +1014,6 @@ public abstract class AbstractHANADialect extends Dialect {
return getForUpdateString() + " nowait";
}
@Override
public String getNotExpression(final String expression) {
return "not (" + expression + ")";
}
@Override
public String getQuerySequencesString() {
return "select * from sys.sequences";
@ -1167,11 +1158,6 @@ public abstract class AbstractHANADialect extends Dialect {
return true;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
@ -1208,16 +1194,6 @@ public abstract class AbstractHANADialect extends Dialect {
return false;
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return true;
}
@Override
public int getMaxAliasLength() {
return 128;
@ -1375,16 +1351,6 @@ public abstract class AbstractHANADialect extends Dialect {
return timeoutInSeconds;
}
@Override
public String getFromDual() {
return "from sys.dummy";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public String getQueryHintString(String query, List<String> hints) {
return query + " with hint (" + String.join( ",", hints ) + ")";
@ -1700,8 +1666,4 @@ public abstract class AbstractHANADialect extends Dialect {
protected abstract Boolean useUnicodeStringTypesDefault();
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
}

View File

@ -26,7 +26,6 @@ import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStra
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
@ -251,11 +250,6 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
return "select getdate()";
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
}
@Override
public NullOrdering getNullOrdering() {
return NullOrdering.SMALLEST;
@ -287,11 +281,6 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
@ -312,11 +301,6 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
return false;
}
@Override
public boolean supportsTuplesInSubqueries() {
return false;
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new AbstractTransactSQLIdentityColumnSupport();

View File

@ -175,16 +175,6 @@ public class CockroachDialect extends Dialect {
return true;
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return true;
}
@Override
public boolean supportsPartitionBy() {
return true;
@ -588,11 +578,6 @@ public class CockroachDialect extends Dialect {
return getVersion() >= 2010;
}
@Override
public boolean forUpdateOfColumns() {
return getVersion() >= 2010;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return getVersion() >= 2010 ? RowLockStrategy.TABLE : RowLockStrategy.NONE;

View File

@ -8,6 +8,8 @@ package org.hibernate.dialect;
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.sequence.DB2iSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
import org.hibernate.dialect.unique.UniqueDelegate;
@ -35,8 +37,8 @@ public class DB2400V7R3Dialect extends DB2400Dialect {
}
@Override
public boolean supportsSequences() {
return true;
public SequenceSupport getSequenceSupport() {
return DB2iSequenceSupport.INSTANCE;
}
@Override
@ -46,18 +48,6 @@ public class DB2400V7R3Dialect extends DB2400Dialect {
"or sequence_schema=current_schema";
}
@Override
@SuppressWarnings("deprecation")
public String getLimitString(String sql, int offset, int limit) {
if ( offset == 0 ) {
return sql + " fetch first " + limit + " rows only";
}
//nest the main query in an outer select
return "select * from (select inner2_.*,rownumber() over(order by order of inner2_) as rownumber_ from ("
+ sql + " fetch first " + limit + " rows only) as inner2_) as inner1_ where rownumber_>"
+ offset + " order by rownumber_";
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new DB2IdentityColumnSupport();

View File

@ -8,7 +8,6 @@ package org.hibernate.dialect;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.NullPrecedence;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.function.DB2FormatEmulation;
@ -52,7 +51,7 @@ import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Locale;
import jakarta.persistence.TemporalType;
/**
@ -470,48 +469,19 @@ public class DB2Dialect extends Dialect {
return false;
}
/**
* {@inheritDoc}
* <p/>
* NOTE : DB2 is known to support parameters in the <tt>SELECT</tt> clause, but only in casted form
* (see {@link #requiresCastingOfParametersInSelectClause()}).
*/
@Override
public boolean supportsParametersInInsertSelect() {
return true;
}
/**
* {@inheritDoc}
* <p/>
* DB2 in fact does require that parameters appearing in the select clause be wrapped in cast() calls
* to tell the DB parser the type of the select value.
*/
@Override
public boolean requiresCastingOfParametersInSelectClause() {
return true;
}
@Override
public boolean supportsResultSetPositionQueryMethodsOnForwardOnlyCursor() {
return false;
}
@Override
public String getCrossJoinSeparator() {
//DB2 v9.1 doesn't support 'cross join' syntax
//DB2 9.7 and later support "cross join"
return getVersion() < 970 ? ", " : super.getCrossJoinSeparator();
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsLobValueChangePropagation() {
return false;
@ -527,16 +497,6 @@ public class DB2Dialect extends Dialect {
return false;
}
@Override
public String getFromDual() {
return "from sysibm.dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
protected JdbcTypeDescriptor getSqlTypeDescriptorOverride(int sqlCode) {
final int version = getVersion();
@ -619,11 +579,6 @@ public class DB2Dialect extends Dialect {
return uniqueDelegate;
}
@Override
public String getNotExpression( String expression ) {
return "not (" + expression + ")";
}
@Override
public LimitHandler getLimitHandler() {
return limitHandler;
@ -645,54 +600,6 @@ public class DB2Dialect extends Dialect {
};
}
/**
* Handle DB2 "support" for null precedence...
*
* @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 nullPrecedence Nulls precedence. Default value: {@link NullPrecedence#NONE}.
*
* @return SQL string.
*/
@Override
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nullPrecedence) {
if ( nullPrecedence == null || nullPrecedence == NullPrecedence.NONE ) {
return super.renderOrderByElement( expression, collation, order, NullPrecedence.NONE );
}
// DB2 FTW! A null precedence was explicitly requested, but DB2 "support" for null precedence
// is a joke. Basically it supports combos that align with what it does anyway. Here is the
// support matrix:
// * ASC + NULLS FIRST -> case statement
// * ASC + NULLS LAST -> just drop the NULLS LAST from sql fragment
// * DESC + NULLS FIRST -> just drop the NULLS FIRST from sql fragment
// * DESC + NULLS LAST -> case statement
if ( ( nullPrecedence == NullPrecedence.FIRST && "desc".equalsIgnoreCase( order ) )
|| ( nullPrecedence == NullPrecedence.LAST && "asc".equalsIgnoreCase( order ) ) ) {
// we have one of:
// * ASC + NULLS LAST
// * DESC + NULLS FIRST
// so just drop the null precedence. *NOTE*: we could pass along the null precedence here,
// but only DB2 9.7 or greater understand it; dropping it is more portable across DB2 versions
return super.renderOrderByElement( expression, collation, order, NullPrecedence.NONE );
}
return String.format(
Locale.ENGLISH,
"case when %s is null then %s else %s end,%s %s",
expression,
nullPrecedence == NullPrecedence.FIRST ? "0" : "1",
nullPrecedence == NullPrecedence.FIRST ? "1" : "0",
expression,
order == null ? "asc" : order
);
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new DB2IdentityColumnSupport();
@ -703,11 +610,6 @@ public class DB2Dialect extends Dialect {
return true;
}
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return false;
}
@Override
public boolean supportsPartitionBy() {
return true;
@ -728,16 +630,6 @@ public class DB2Dialect extends Dialect {
return true;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.FUNCTION;
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
@Override
public void appendDatetimeFormat(SqlAppender appender, String format) {
//DB2 does not need nor support FM

View File

@ -43,8 +43,6 @@ import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStra
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.DerbyCaseFragment;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@ -365,19 +363,6 @@ public class DerbyDialect extends Dialect {
}
}
@Override
public String getCrossJoinSeparator() {
//Derby 10.5 doesn't support 'cross join' syntax
//Derby 10.6 and later support "cross join"
return getVersion() < 1060 ? ", " : super.getCrossJoinSeparator();
}
@Override
@SuppressWarnings("deprecation")
public CaseFragment createCaseFragment() {
return new DerbyCaseFragment();
}
@Override
public SequenceSupport getSequenceSupport() {
return getVersion() < 1060
@ -409,16 +394,6 @@ public class DerbyDialect extends Dialect {
return DB2Dialect.selectNullString( sqlType );
}
@Override
public String getFromDual() {
return "from (values 0) as dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public boolean supportsCommentOn() {
//HHH-4531
@ -494,12 +469,6 @@ public class DerbyDialect extends Dialect {
return new DB2IdentityColumnSupport();
}
@Override
public boolean supportsTuplesInSubqueries() {
//checked on Derby 10.14
return false;
}
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
//TODO: check this
@ -512,18 +481,6 @@ public class DerbyDialect extends Dialect {
return true;
}
@Override
public boolean requiresCastingOfParametersInSelectClause() {
//checked on Derby 10.14
return true;
}
@Override
public boolean supportsEmptyInList() {
//checked on Derby 10.14
return false;
}
@Override
public boolean supportsTupleDistinctCounts() {
//checked on Derby 10.14
@ -567,11 +524,6 @@ public class DerbyDialect extends Dialect {
);
}
@Override
public String getNotExpression( String expression ) {
return "not (" + expression + ")";
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@ -861,11 +813,6 @@ public class DerbyDialect extends Dialect {
);
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.FUNCTION;
}
@Override
public boolean supportsPartitionBy() {
return false;

View File

@ -11,20 +11,18 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.NullOrdering;
import org.hibernate.query.NullPrecedence;
import org.hibernate.ScrollMode;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
import org.hibernate.boot.model.relational.Sequence;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.*;
import org.hibernate.dialect.identity.IdentityColumnSupport;
import org.hibernate.dialect.identity.IdentityColumnSupportImpl;
import org.hibernate.dialect.lock.*;
import org.hibernate.dialect.pagination.LegacyLimitHandler;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
@ -39,9 +37,6 @@ import org.hibernate.exception.spi.ConversionContext;
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.SQLExceptionConverter;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.id.enhanced.SequenceStyleGenerator;
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;
@ -72,7 +67,6 @@ import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.*;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
@ -962,60 +956,6 @@ public abstract class Dialect implements ConversionContext {
|| typeCode == Types.DOUBLE;
}
/**
* 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.
*
* @deprecated this just calls the default constructor and does not pass in the
* {@link org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo}.
*/
@Deprecated
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 <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.
*
* @deprecated this just calls the default constructor and does not pass in the
* {@link org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo}.
*/
@Deprecated
public static Dialect getDialect(Properties props) throws HibernateException {
final String dialectName = props.getProperty( Environment.DIALECT );
if ( dialectName == null ) {
return getDialect();
}
return instantiateDialect( dialectName );
}
/**
* @deprecated this just calls the default constructor and does not pass in the
* {@link org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo}.
*/
@Deprecated
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.
*
@ -1051,41 +991,6 @@ public abstract class Dialect implements ConversionContext {
}
}
// public static interface Initializable {
// void initialize(
// Connection jdbcConnection,
// ExtractedDatabaseMetadata extractedMeta,
// ServiceRegistry registry) {
//
// }
// }
// todo (6.0) : new overall Dialect design?
// original (and currently) Dialect is designed/intended to be completely
// static information - that works great until databases have have
// deviations between versison for the information we need (which
// is highly likely. note that "static" here means information that
// the Dialect can know about the underlying database, but without
// actually being able to query the db through JDBC, which would be
// an example of doing it dynamically
// so might be better to design a better intention, such that Dialect
// is built with has access to information about the underlying
// database either through the JDBC Connection or some form of
// "extracted metadata". I think the former is both more flexible/powerful
// and simple (if there is no Connection the Dialect can just do what it
// does today
//
// todo (6.0) : a related point is to consider a singular JDBC Connection
// that is:
// 1) opened once at the stat of bootstrapping (at what specific point?)
// 2) can be accessed by different bootstrapping aspects - only ever opening
// that one for all of bootstrap. practically this may have to be
// 2 Connections because of the "break" between the boot service registry
// (building JdbcServices, etc) and handling metadata.
// 3) closed at conclusion
/**
* Get the name of the database type associated with the given
* {@link Types} typecode, with no length, precision,
@ -1518,22 +1423,6 @@ public abstract class Dialect implements ConversionContext {
// native identifier generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 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.
* @deprecated use {@link #getNativeIdentifierGeneratorStrategy()} instead
*/
@Deprecated
public Class getNativeIdentifierGeneratorClass() {
return getIdentityColumnSupport().supportsIdentityColumns()
? IdentityGenerator.class
: SequenceStyleGenerator.class;
}
/**
* Resolves the native generation strategy associated to this dialect.
* <p/>
@ -1562,7 +1451,7 @@ public abstract class Dialect implements ConversionContext {
// SEQUENCE support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public SequenceSupport getSequenceSupport() {
return new LegacySequenceSupport(this);
return NoSequenceSupport.INSTANCE;
}
/**
@ -1597,29 +1486,6 @@ public abstract class Dialect implements ConversionContext {
throw new UnsupportedOperationException( getClass().getName() + " does not support GUIDs" );
}
// 'from dual' support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Some databases require a bit of syntactic noise when
* there are no tables in the from clause.
*
* @return the SQL equivalent to Oracle's {@code from dual}.
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public String getFromDual() {
// The standard SQL solution to get a dual table is to use the VALUES clause
return "from (values (0)) as dual";
}
/**
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsSelectQueryWithoutFromClause() {
return true;
}
public boolean supportsTemporaryTables() {
// Most databases do
return true;
@ -1633,11 +1499,7 @@ public abstract class Dialect implements ConversionContext {
* {@link org.hibernate.query.Query#setFirstResult(int)} for
* this dialect.
*/
@SuppressWarnings("deprecation")
public LimitHandler getLimitHandler() {
if ( supportsLimit() ) {
return new LegacyLimitHandler( this );
}
throw new UnsupportedOperationException("this dialect does not support query pagination");
}
@ -1802,20 +1664,6 @@ public abstract class Dialect implements ConversionContext {
return getReadLockString( timeout );
}
/**
* Does the <tt>FOR UPDATE OF</tt> clause accept a list of columns
* instead of a list of table aliases?
*
* @return True if the database supports <tt>FOR UPDATE OF</tt> syntax;
* false otherwise.
* @deprecated Use {@link #getWriteRowLockStrategy()} instead
*/
@Deprecated
public boolean forUpdateOfColumns() {
// by default we report no support
return false;
}
/**
* The row lock strategy to use for write locks.
*/
@ -1919,21 +1767,6 @@ public abstract class Dialect implements ConversionContext {
return getForUpdateString( aliases );
}
/**
* Some dialects support an alternative means to <tt>SELECT FOR UPDATE</tt>,
* whereby a "lock hint" is appended 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 <tt>SELECT FOR UPDATE</tt>,
* whereby a "lock hint" is appended to the table name in the from clause.
@ -1943,9 +1776,7 @@ public abstract class Dialect implements ConversionContext {
* @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.
* @deprecated This was moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public String appendLockHint(LockOptions lockOptions, String tableName){
return tableName;
}
@ -2118,9 +1949,7 @@ public abstract class Dialect implements ConversionContext {
* timestamp value?
*
* @return True if the current timestamp can be retrieved; false otherwise.
* @deprecated no longer called
*/
@Deprecated
public boolean supportsCurrentTimestampSelection() {
return false;
}
@ -2132,9 +1961,7 @@ public abstract class Dialect implements ConversionContext {
*
* @return True if the {@link #getCurrentTimestampSelectString} return
* is callable; false otherwise.
* @deprecated no longer called
*/
@Deprecated
public boolean isCurrentTimestampSelectStringCallable() {
throw new UnsupportedOperationException( "Database not known to define a current timestamp function" );
}
@ -2144,75 +1971,19 @@ public abstract class Dialect implements ConversionContext {
* database.
*
* @return The command.
* @deprecated no longer called, use {@link #currentTimestamp()}
*/
@Deprecated
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.
*
* @return The function name.
*
* @deprecated use {@link #currentTimestamp()},
* {@link #currentLocalTimestamp()}, or
* {@link #currentTimestampWithTimeZone()}.
*/
@Deprecated
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.
* <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 #buildSQLExceptionConversionDelegate()
* @deprecated {@link #buildSQLExceptionConversionDelegate()} should be
* overridden instead.
*/
@Deprecated
public SQLExceptionConverter buildSQLExceptionConverter() {
return null;
}
/**
* 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,
* 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:
@ -2278,32 +2049,6 @@ public abstract class Dialect implements ConversionContext {
// miscellaneous support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Create a {@link JoinFragment} strategy responsible
* for handling this dialect's variations in how joins are handled.
*
* @return This dialect's {@link JoinFragment} strategy.
* @deprecated migrating away from deprecated {@link JoinFragment}
*/
@Deprecated
public JoinFragment createOuterJoinFragment() {
return new ANSIJoinFragment();
}
/**
* Create a {@link CaseFragment} strategy responsible
* for handling this dialect's variations in how CASE statements are
* handled.
*
* @return This dialect's {@link CaseFragment} strategy.
* @deprecated migrating away from deprecated {@link CaseFragment}
*/
@Deprecated
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.
@ -2907,144 +2652,12 @@ public abstract class Dialect implements ConversionContext {
return "";
}
/**
* The separator to use for declaring cross joins in a SQL query,
* typically either {@code " cross join "} or a comma {@code ", "},
* where the spaces are required.
*
* @return The cross join separator, with spaces
*/
public String getCrossJoinSeparator() {
return " cross join ";
}
/**
* The separator to use between a table name and its alias in a SQL
* query, typically either {@code " as "} where the spaces are
* required, or a space character {@code " "}.
*
* @return The separator keyword, if any, with spaces
*/
public String getTableAliasSeparator() {
return " as ";
}
public ColumnAliasExtractor getColumnAliasExtractor() {
return ColumnAliasExtractor.COLUMN_LABEL_EXTRACTOR;
}
// Informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* 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;
}
/**
* 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
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsRowValueConstructorSyntax() {
// return false here, as most databases do not properly support this construct...
return false;
}
/**
* Is this dialect known to support what ANSI-SQL terms "row value constructor" syntax,
* sometimes called tuple syntax, in the SET clause;
* <p/>
* Basically, does it support syntax like
* "... SET (FIRST_NAME, LAST_NAME) = ('Steve', 'Ebersole') ...".
*
* @return True if this SQL dialect is known to support "row value constructor" syntax in the SET clause; false otherwise.
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsRowValueConstructorSyntaxInSet() {
return supportsRowValueConstructorSyntax();
}
/**
* Is this dialect known to support what ANSI-SQL terms "row value
* constructor" syntax; sometimes called tuple syntax with quantified predicates.
* <p/>
* Basically, does it support syntax like
* "... where (FIRST_NAME, LAST_NAME) = ALL (select ...) ...".
*
* @return True if this SQL dialect is known to support "row value
* constructor" syntax with quantified predicates; false otherwise.
* @since 6.0
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
// return false here, as most databases do not properly support this construct...
return false;
}
/**
* 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
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsRowValueConstructorSyntaxInInList() {
return false;
}
/**
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean supportsRowValueConstructorSyntaxInInSubquery() {
return supportsRowValueConstructorSyntaxInInList();
}
/**
* The strategy to use for rendering summarizations in the GROUP BY clause.
*
* @since 6.0
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.NONE;
}
/**
* The strategy to use for rendering constants in the GROUP BY clause.
*
* @since 6.0
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.CONSTANT_EXPRESSION;
}
/**
* Should LOBs (both BLOB and CLOB) be bound using stream operations (i.e.
* {@link PreparedStatement#setBinaryStream}).
@ -3067,23 +2680,6 @@ public abstract class Dialect implements ConversionContext {
return true;
}
/**
* Does this dialect require that references to result variables
* (i.e, select expression 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.
* @deprecated We now use ordinal rendering by default to produce smaller SQL
* @see #supportsOrdinalSelectItemReference
*/
@Deprecated
public boolean replaceResultVariableInOrderByClauseWithPosition() {
return false;
}
/**
* Does this dialect support references to result variables
* (i.e, select items) by column positions (1-origin) as defined
@ -3114,47 +2710,6 @@ public abstract class Dialect implements ConversionContext {
return true;
}
/**
* 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.
* @deprecated todo (6.0): remove?
*/
@Deprecated
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 <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
* @deprecated Moved to {@link AbstractSqlAstTranslator}
*/
@Deprecated
public boolean requiresCastingOfParametersInSelectClause() {
return false;
}
/**
* Does this dialect require that integer divisions be wrapped in <tt>cast()</tt>
* calls to tell the db parser the expected type.
@ -3397,7 +2952,7 @@ public abstract class Dialect implements ConversionContext {
/**
* Return whether the dialect considers an empty-string value as null.
*
* @return boolean True if an empty string is treated as null, false othrwise.
* @return boolean True if an empty string is treated as null, false otherwise.
*/
public boolean isEmptyStringTreatedAsNull() {
return false;
@ -3417,19 +2972,6 @@ public abstract class Dialect implements ConversionContext {
return false;
}
/**
* Negate an expression
*
* @param expression The expression to negate
*
* @return The negated expression
* @deprecated todo (6.0): Remove
*/
@Deprecated
public String getNotExpression(String expression) {
return "not " + expression;
}
/**
* Get the UniqueDelegate supported by this dialect
*
@ -3439,55 +2981,6 @@ public abstract class Dialect implements ConversionContext {
return uniqueDelegate;
}
/**
* 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 ?
*
* @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.
*
* @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?
*
* @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.
@ -3522,18 +3015,6 @@ public abstract class Dialect implements ConversionContext {
return ScrollMode.SCROLL_INSENSITIVE;
}
/**
* Does this dialect support tuples in subqueries? Ex:
* delete from Table1 where (col1, col2) in (select col1, col2 from Table2)
*
* @return boolean
* @deprecated See {@link #supportsRowValueConstructorSyntaxInInSubquery()}
*/
@Deprecated
public boolean supportsTuplesInSubqueries() {
return true;
}
/**
* Does this dialect support offset in subqueries? Ex:
* select * from Table1 where col1 in (select col1 from Table2 order by col2 limit 1 offset 1)
@ -3647,20 +3128,6 @@ public abstract class Dialect implements ConversionContext {
return databaseMetaData != null && databaseMetaData.supportsNamedParameters();
}
/**
* Does this dialect supports Nationalized Types
*
* @return boolean
*
* @deprecated (since 6.0) Prefer {@link #getNationalizationSupport()} which gives a little
* better insight into what is supported. This is interpreted as true if the supported
* strategy is {@link NationalizationSupport#EXPLICIT}
*/
@Deprecated
public final boolean supportsNationalizedTypes() {
return getNationalizationSupport() == NationalizationSupport.EXPLICIT;
}
public NationalizationSupport getNationalizationSupport() {
return NationalizationSupport.EXPLICIT;
}
@ -3990,7 +3457,7 @@ public abstract class Dialect implements ConversionContext {
*/
Size resolveSize(
JdbcTypeDescriptor jdbcType,
JavaTypeDescriptor javaType,
JavaTypeDescriptor<?> javaType,
Integer precision,
Integer scale, Long length);
}
@ -3999,7 +3466,7 @@ public abstract class Dialect implements ConversionContext {
@Override
public Size resolveSize(
JdbcTypeDescriptor jdbcType,
JavaTypeDescriptor javaType,
JavaTypeDescriptor<?> javaType,
Integer precision,
Integer scale,
Long length) {
@ -4292,168 +3759,6 @@ public abstract class Dialect implements ConversionContext {
return false;
}
// deprecated limit/offset support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean supportsLimit() {
return false;
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean supportsLimitOffset() {
return supportsLimit();
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean supportsVariableLimit() {
return supportsLimit();
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean bindLimitParametersInReverseOrder() {
return false;
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean bindLimitParametersFirst() {
return false;
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean useMaxForLimit() {
return false;
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public boolean forceLimitUsage() {
return false;
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public String getLimitString(String query, int offset, int limit) {
return getLimitString( query, offset > 0 || forceLimitUsage() );
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
protected String getLimitString(String query, boolean hasOffset) {
throw new UnsupportedOperationException( "Paged queries not supported by " + getClass().getName());
}
/**
* @deprecated {@link #getLimitHandler()} should be overridden instead.
*/
@Deprecated
public int convertToFirstRowValue(int zeroBasedFirstResult) {
return zeroBasedFirstResult;
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public boolean supportsSequences() {
return false;
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public boolean supportsPooledSequences() {
return false;
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public String getSequenceNextValString(String sequenceName) throws MappingException {
throw new MappingException("dialect does not support sequences");
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public String getSelectSequenceNextValString(String sequenceName) throws MappingException {
throw new MappingException("dialect does not support sequences");
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public String getSequenceNextValString(String sequenceName, int increment) throws MappingException {
return getSequenceNextValString( sequenceName );
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public String[] getCreateSequenceStrings(String sequenceName, int initialValue, int incrementSize) throws MappingException {
return new String[] { getCreateSequenceString( sequenceName, initialValue, incrementSize ) };
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
protected String getCreateSequenceString(String sequenceName) throws MappingException {
return "create sequence " + sequenceName;
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
protected String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) throws MappingException {
return getCreateSequenceString( sequenceName ) + " start with " + initialValue + " increment by " + incrementSize;
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
public String[] getDropSequenceStrings(String sequenceName) throws MappingException {
return new String[]{ getDropSequenceString( sequenceName ) };
}
/**
* @deprecated implement {@link SequenceSupport} and override {@link #getSequenceSupport()}
*/
@Deprecated
protected String getDropSequenceString(String sequenceName) throws MappingException {
return "drop sequence " + sequenceName;
}
/**
* Annotation to be appended to the end of each COLUMN clause for temporary tables.
*

View File

@ -325,11 +325,6 @@ public class H2Dialect extends Dialect {
return sequenceInformationExtractor;
}
@Override
public String getFromDual() {
return "from dual";
}
@Override
public NullOrdering getNullOrdering() {
return NullOrdering.FIRST;
@ -432,11 +427,6 @@ public class H2Dialect extends Dialect {
return true;
}
@Override
public boolean supportsTuplesInSubqueries() {
return supportsTuplesInSubqueries;
}
@Override
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
return SelectItemReferenceStrategy.ALIAS;

View File

@ -395,17 +395,6 @@ public class HSQLDialect extends Dialect {
return SequenceInformationExtractorHSQLDBDatabaseImpl.INSTANCE;
}
@Override
public String getFromDual() {
return "from (values(0))";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
// This is only supported when the PostgreSQL compatibility is enabled
return false;
}
@Override
public ViolatedConstraintNameExtractor getViolatedConstraintNameExtractor() {
return version < 200 ? EXTRACTOR_18 : EXTRACTOR_20;
@ -621,16 +610,6 @@ public class HSQLDialect extends Dialect {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean requiresCastingOfParametersInSelectClause() {
return true;
}
@Override
public boolean doesReadCommittedCauseWritersToBlockReaders() {
return version >= 200;

View File

@ -1,72 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.dialect;
import org.hibernate.MappingException;
import org.hibernate.dialect.sequence.SequenceSupport;
/**
* @author Gavin King
*/
@SuppressWarnings("deprecation")
public class LegacySequenceSupport implements SequenceSupport {
private Dialect dialect;
public LegacySequenceSupport(Dialect dialect) {
this.dialect = dialect;
}
@Override
public boolean supportsSequences() {
return dialect.supportsSequences();
}
@Override
public boolean supportsPooledSequences() {
return dialect.supportsPooledSequences();
}
@Override
public String getSequenceNextValString(String sequenceName) throws MappingException {
return dialect.getSequenceNextValString( sequenceName );
}
@Override
public String getSequenceNextValString(String sequenceName, int increment) throws MappingException {
return dialect.getSequenceNextValString( sequenceName, increment );
}
@Override
public String getSelectSequenceNextValString(String sequenceName) throws MappingException {
return dialect.getSelectSequenceNextValString( sequenceName );
}
@Override
public String[] getCreateSequenceStrings(String sequenceName, int initialValue, int incrementSize) throws MappingException {
return dialect.getCreateSequenceStrings( sequenceName, initialValue, incrementSize );
}
@Override
public String getCreateSequenceString(String sequenceName) throws MappingException {
return dialect.getCreateSequenceString( sequenceName );
}
@Override
public String getCreateSequenceString(String sequenceName, int initialValue, int incrementSize) throws MappingException {
return dialect.getCreateSequenceString( sequenceName, initialValue, incrementSize );
}
@Override
public String[] getDropSequenceStrings(String sequenceName) throws MappingException {
return dialect.getDropSequenceStrings( sequenceName );
}
@Override
public String getDropSequenceString(String sequenceName) throws MappingException {
return dialect.getDropSequenceString( sequenceName );
}
}

View File

@ -8,7 +8,6 @@ package org.hibernate.dialect;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.dialect.sequence.MariaDBSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
@ -93,11 +92,6 @@ public class MariaDBDialect extends MySQLDialect {
};
}
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return true;
}
@Override
public boolean supportsWindowFunctions() {
return getVersion() >= 1020;
@ -160,11 +154,6 @@ public class MariaDBDialect extends MySQLDialect {
return getVersion() >= 1030;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.CLAUSE;
}
@Override
boolean supportsForShare() {
//only supported on MySQL

View File

@ -15,7 +15,6 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.query.CastType;
import org.hibernate.query.NullOrdering;
import org.hibernate.query.NullPrecedence;
import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
import org.hibernate.cfg.Environment;
@ -194,7 +193,7 @@ public class MySQLDialect extends Dialect {
@Override
public Size resolveSize(
JdbcTypeDescriptor jdbcType,
JavaTypeDescriptor javaType,
JavaTypeDescriptor<?> javaType,
Integer precision,
Integer scale,
Long length) {
@ -535,15 +534,6 @@ public class MySQLDialect extends Dialect {
}
}
/**
* @see <a href="https://dev.mysql.com/worklog/task/?id=7019">MySQL 5.7 work log</a>
* @return true for MySQL 5.7 and above
*/
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return getMySQLVersion() >= 570;
}
@Override
public boolean supportsUnionAll() {
return getMySQLVersion() >= 500;
@ -622,11 +612,6 @@ public class MySQLDialect extends Dialect {
return LimitLimitHandler.INSTANCE;
}
@Override
public String getFromDual() {
return "from dual";
}
@Override
public char closeQuote() {
return '`';
@ -796,47 +781,13 @@ public class MySQLDialect extends Dialect {
return uniqueDelegate;
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
@Override
public boolean supportsNullPrecedence() {
return false;
}
@Override
public boolean supportsRowValueConstructorSyntaxInSet() {
return false;
}
@Override
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nulls) {
final StringBuilder orderByElement = new StringBuilder();
if ( nulls != NullPrecedence.NONE ) {
// Workaround for NULLS FIRST / LAST support.
orderByElement.append( "case when " ).append( expression ).append( " is null then " );
if ( nulls == NullPrecedence.FIRST ) {
orderByElement.append( "0 else 1" );
}
else {
orderByElement.append( "1 else 0" );
}
orderByElement.append( " end," );
}
// Nulls precedence has already been handled so passing NONE value.
orderByElement.append( super.renderOrderByElement( expression, collation, order, NullPrecedence.NONE ) );
return orderByElement.toString();
}
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsLobValueChangePropagation() {
// note: at least my local MySQL 5.1 install shows this not working...
@ -900,11 +851,6 @@ public class MySQLDialect extends Dialect {
return super.buildIdentifierHelper( builder, dbMetaData );
}
@Override
public String getNotExpression(String expression) {
return "not (" + expression + ")";
}
@Override
public IdentityColumnSupport getIdentityColumnSupport() {
return new MySQLIdentityColumnSupport();
@ -1149,8 +1095,4 @@ public class MySQLDialect extends Dialect {
return getMySQLVersion() >= 800;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.CLAUSE;
}
}

View File

@ -47,7 +47,6 @@ import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.*;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@ -545,7 +544,7 @@ public class OracleDialect extends Dialect {
// Oracle has DOUBLE semantics for the REAL type, so we map it to float(24)
registerColumnType( Types.REAL, "float(24)" );
// // Note that 38 is the maximum precision Oracle supports
// Note that 38 is the maximum precision Oracle supports
registerColumnType( Types.NUMERIC, "number($p,$s)" );
registerColumnType( Types.DECIMAL, "number($p,$s)" );
}
@ -701,11 +700,6 @@ public class OracleDialect extends Dialect {
return "sequence";
}
@Override
public String getTableAliasSeparator() {
return " ";
}
// features which change between 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@ -715,32 +709,6 @@ public class OracleDialect extends Dialect {
: new Oracle12cIdentityColumnSupport();
}
@Override
@SuppressWarnings("deprecation")
public JoinFragment createOuterJoinFragment() {
return getVersion() < 1000 ? new OracleJoinFragment() : new ANSIJoinFragment();
}
@Override
public String getCrossJoinSeparator() {
return getVersion() < 1000 ? ", " : " cross join ";
}
/**
* Map case support to the Oracle DECODE function. Oracle did not
* add support for CASE until 9i.
* <p/>
* {@inheritDoc}
*/
@Override
@SuppressWarnings("deprecation")
public CaseFragment createCaseFragment() {
return getVersion() < 900
? new DecodeCaseFragment()
// Oracle did add support for ANSI CASE statements in 9i
: new ANSICaseFragment();
}
@Override
public LimitHandler getLimitHandler() {
return limitHandler;
@ -774,15 +742,6 @@ public class OracleDialect extends Dialect {
: "select systimestamp from dual";
}
@Override
@SuppressWarnings("deprecation")
public String getCurrentTimestampSQLFunctionName() {
return getVersion() < 900
? "sysdate"
// the standard SQL function name is current_timestamp...
: "current_timestamp";
}
// features which remain constant across 8i, 9i, and 10g ~~~~~~~~~~~~~~~~~~
@ -801,16 +760,6 @@ public class OracleDialect extends Dialect {
return false;
}
@Override
public String getFromDual() {
return "from dual";
}
@Override
public boolean supportsSelectQueryWithoutFromClause() {
return false;
}
@Override
public SequenceSupport getSequenceSupport() {
return OracleSequenceSupport.INSTANCE;
@ -925,26 +874,11 @@ public class OracleDialect extends Dialect {
return false;
}
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsExistsInSelect() {
return false;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.FUNCTION;
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
@Override
public int getInExpressionCountLimit() {
return PARAM_LIST_SIZE_LIMIT;
@ -1006,11 +940,6 @@ public class OracleDialect extends Dialect {
);
}
@Override
public String getNotExpression( String expression ) {
return "not (" + expression + ")";
}
@Override
public String getQueryHintString(String sql, String hints) {
String statementType = statementType(sql);
@ -1070,22 +999,6 @@ public class OracleDialect extends Dialect {
throw new IllegalArgumentException( "Can't determine SQL statement type for statement: " + sql );
}
/**
* HHH-4907, I don't know if oracle 8 supports this syntax, so I'd think it is better add this
* method here. Reopen this issue if you found/know 8 supports it.
* <p/>
* {@inheritDoc}
*/
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return false;
}
@Override
public boolean supportsRowValueConstructorSyntaxInInSubquery() {
return getVersion() >= 900;
}
@Override
public boolean supportsTupleDistinctCounts() {
return false;
@ -1118,11 +1031,6 @@ public class OracleDialect extends Dialect {
return getVersion() >= 1000;
}
@Override
public boolean forUpdateOfColumns() {
return true;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return RowLockStrategy.COLUMN;

View File

@ -396,11 +396,6 @@ public class PostgreSQLDialect extends Dialect {
return getVersion() >= 820;
}
@Override
public boolean supportsRowValueConstructorSyntaxInInList() {
return getVersion() >= 820;
}
@Override
public boolean supportsPartitionBy() {
return getVersion() >= 910;
@ -653,11 +648,6 @@ public class PostgreSQLDialect extends Dialect {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public boolean supportsEmptyInList() {
return false;
}
@Override
public boolean supportsLobValueChangePropagation() {
return false;
@ -668,16 +658,6 @@ public class PostgreSQLDialect extends Dialect {
return false;
}
@Override
public boolean supportsRowValueConstructorSyntax() {
return true;
}
@Override
public boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
return true;
}
@Override
public SelectItemReferenceStrategy getGroupBySelectItemReferenceStrategy() {
return SelectItemReferenceStrategy.POSITION;
@ -944,16 +924,6 @@ public class PostgreSQLDialect extends Dialect {
return RowLockStrategy.TABLE;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return getVersion() >= 950 ? GroupBySummarizationRenderingStrategy.FUNCTION : GroupBySummarizationRenderingStrategy.NONE;
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return getVersion() >= 950 ? GroupByConstantRenderingStrategy.EMPTY_GROUPING : GroupByConstantRenderingStrategy.SUBQUERY;
}
@Override
public void augmentRecognizedTableTypes(List<String> tableTypesList) {
super.augmentRecognizedTableTypes( tableTypesList );

View File

@ -79,12 +79,6 @@ public class PostgresPlusDialect extends PostgreSQLDialect {
return "select sysdate";
}
@Override
@SuppressWarnings("deprecation")
public String getCurrentTimestampSQLFunctionName() {
return "sysdate";
}
@Override
public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalType, TemporalType toTemporalType) {
if ( toTemporalType != TemporalType.TIMESTAMP && fromTemporalType != TemporalType.TIMESTAMP && unit == DAY ) {

View File

@ -27,11 +27,6 @@ public class SQLServer2016Dialect extends SQLServerDialect {
return true;
}
@Override
public String getDropSequenceString(String sequenceName) {
return "drop sequence if exists " + sequenceName;
}
@Override
public String[] getDropSchemaCommand(String schemaName) {
return new String[] {"drop schema if exists " + schemaName};

View File

@ -33,7 +33,6 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.CastType;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.NullPrecedence;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
@ -457,11 +456,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
return false;
}
@Override
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
return GroupBySummarizationRenderingStrategy.CLAUSE;
}
@Override
public SequenceSupport getSequenceSupport() {
if ( getVersion() < 11 ) {
@ -529,32 +523,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
return getVersion() >= 11;
}
@Override
public String renderOrderByElement(String expression, String collation, String order, NullPrecedence nulls) {
if ( getVersion() < 10 ) {
return super.renderOrderByElement( expression, collation, order, nulls );
}
final StringBuilder orderByElement = new StringBuilder();
if ( nulls != null && !NullPrecedence.NONE.equals( nulls ) ) {
// Workaround for NULLS FIRST / LAST support.
orderByElement.append( "case when " ).append( expression ).append( " is null then " );
if ( NullPrecedence.FIRST.equals( nulls ) ) {
orderByElement.append( "0 else 1" );
}
else {
orderByElement.append( "1 else 0" );
}
orderByElement.append( " end," );
}
// Nulls precedence has already been handled so passing NONE value.
orderByElement.append( super.renderOrderByElement( expression, collation, order, NullPrecedence.NONE ) );
return orderByElement.toString();
}
@Override
public SQLExceptionConversionDelegate buildSQLExceptionConversionDelegate() {
if ( getVersion() < 9 ) {
@ -833,19 +801,6 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
}
}
@Override
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
}
@Override
protected String getDropSequenceString(String sequenceName) throws MappingException {
if ( getVersion() >= 16 ) {
return "drop sequence if exists " + sequenceName;
}
return super.getDropSequenceString( sequenceName );
}
@Override
public String[] getDropSchemaCommand(String schemaName) {
if ( getVersion() >= 16 ) {

View File

@ -720,45 +720,6 @@ public class SpannerDialect extends Dialect {
return NOOP_UNIQUE_DELEGATE;
}
/**
* The Cloud Spanner Hibernate Dialect does not currently support UNIQUE restrictions.
*
* @return {@code false}.
*/
@Override
@SuppressWarnings("deprecation")
public boolean supportsUnique() {
return false;
}
/**
* The Cloud Spanner Hibernate Dialect does not currently support UNIQUE restrictions.
*
* @return {@code false}.
*/
@Override
@SuppressWarnings("deprecation")
public boolean supportsNotNullUnique() {
return false;
}
/**
* The Cloud Spanner Hibernate Dialect does not currently support UNIQUE restrictions.
*
* @return {@code false}.
*/
@Override
@SuppressWarnings("deprecation")
public boolean supportsUniqueConstraintInCreateAlterTable() {
return false;
}
@Override
@SuppressWarnings("deprecation")
public String getAddUniqueConstraintString(String constraintName) {
return "";
}
@Override
public boolean supportsCircularCascadeDeleteConstraints() {
return false;

View File

@ -15,7 +15,6 @@ import java.util.Map;
import jakarta.persistence.TemporalType;
import org.hibernate.LockOptions;
import org.hibernate.dialect.function.QuantifiedLeastGreatestEmulation;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.TopLimitHandler;
import org.hibernate.engine.jdbc.Size;
@ -28,10 +27,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ForUpdateFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Sybase11JoinFragment;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
@ -110,7 +106,7 @@ public class SybaseASEDialect extends SybaseDialect {
@Override
public Size resolveSize(
JdbcTypeDescriptor jdbcType,
JavaTypeDescriptor javaType,
JavaTypeDescriptor<?> javaType,
Integer precision,
Integer scale,
Long length) {
@ -485,14 +481,6 @@ public class SybaseASEDialect extends SybaseDialect {
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
@SuppressWarnings("deprecation")
public JoinFragment createOuterJoinFragment() {
return getVersion() < 1400
? new Sybase11JoinFragment()
: super.createOuterJoinFragment();
}
@Override
public boolean supportsCascadeDelete() {
return false;
@ -503,17 +491,6 @@ public class SybaseASEDialect extends SybaseDialect {
return 30;
}
@Override
@SuppressWarnings("deprecation")
public String getCurrentTimestampSQLFunctionName() {
return "getdate()";
}
@Override
public String getCrossJoinSeparator() {
return ", ";
}
@Override
public boolean supportsValuesListForInsert() {
return false;
@ -558,11 +535,6 @@ public class SybaseASEDialect extends SybaseDialect {
return false;
}
@Override
public boolean forUpdateOfColumns() {
return getVersion() >= 1570;
}
@Override
public RowLockStrategy getWriteRowLockStrategy() {
return getVersion() >= 1570 ? RowLockStrategy.COLUMN : RowLockStrategy.TABLE;

View File

@ -36,7 +36,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
* @author Scott Marlow
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockMode, String)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
*
* @since 3.5
*/
@ -103,7 +103,7 @@ public class PessimisticReadSelectLockingStrategy extends AbstractSelectLockingS
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getJdbcServices().getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -33,7 +33,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
* This class is a clone of SelectLockingStrategy.
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockMode, String)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
*
* @author Steve Ebersole
* @author Scott Marlow
@ -106,7 +106,7 @@ public class PessimisticWriteSelectLockingStrategy extends AbstractSelectLocking
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( lockTimeout );
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getJdbcServices().getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -29,7 +29,7 @@ import org.hibernate.stat.spi.StatisticsImplementor;
* SELECT ... FOR UPDATE syntax.
*
* @see org.hibernate.dialect.Dialect#getForUpdateString(LockMode)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockMode, String)
* @see org.hibernate.dialect.Dialect#appendLockHint(LockOptions, String)
*
* @author Steve Ebersole
* @since 3.2
@ -102,7 +102,7 @@ public class SelectLockingStrategy extends AbstractSelectLockingStrategy {
final SessionFactoryImplementor factory = getLockable().getFactory();
final LockOptions lockOptions = new LockOptions( getLockMode() );
lockOptions.setTimeOut( timeout );
final SimpleSelect select = new SimpleSelect( factory.getDialect() )
final SimpleSelect select = new SimpleSelect( factory.getJdbcServices().getDialect() )
.setLockOptions( lockOptions )
.setTableName( getLockable().getRootTableName() )
.addColumn( getLockable().getRootTableIdentifierColumnNames()[0] )

View File

@ -1,84 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.dialect.pagination;
import org.hibernate.dialect.Dialect;
import org.hibernate.query.Limit;
/**
* Stub {@link LimitHandler} that delegates all operations
* to the deprecated methods of the {@link Dialect}.
*
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
*
* @deprecated this class exists only as an adaptor supporting
* legacy user-written {@link Dialect}s.
*/
@Deprecated
public class LegacyLimitHandler extends AbstractLimitHandler {
private final Dialect dialect;
public LegacyLimitHandler(Dialect dialect) {
this.dialect = dialect;
}
@Override
public boolean supportsLimit() {
return dialect.supportsLimit();
}
@Override
public boolean supportsLimitOffset() {
return dialect.supportsLimitOffset();
}
@Override
public boolean supportsVariableLimit() {
return dialect.supportsVariableLimit();
}
@Override
public boolean bindLimitParametersInReverseOrder() {
return dialect.bindLimitParametersInReverseOrder();
}
@Override
public boolean bindLimitParametersFirst() {
return dialect.bindLimitParametersFirst();
}
@Override
public boolean useMaxForLimit() {
return dialect.useMaxForLimit();
}
@Override
public boolean forceLimitUsage() {
return dialect.forceLimitUsage();
}
@Override
public int convertToFirstRowValue(int zeroBasedFirstResult) {
return dialect.convertToFirstRowValue( zeroBasedFirstResult );
}
@Override
public String processSql(String sql, Limit limit) {
final boolean useLimitOffset
= supportsOffset()
&& hasFirstRow( limit )
|| supportsLimit()
&& supportsLimitOffset()
&& hasFirstRow( limit )
&& hasMaxRows( limit );
return dialect.getLimitString(
sql,
useLimitOffset ? getFirstRow( limit ) : 0,
getMaxOrLimit( limit )
);
}
}

View File

@ -26,7 +26,7 @@ public final class HSQLSequenceSupport extends ANSISequenceSupport {
/**
* Because of the overridden {@link #getCreateSequenceString(String)}, we must also override
* {@link org.hibernate.dialect.Dialect#getCreateSequenceString(String, int, int)} to prevent
* {@link #getCreateSequenceString(String, int, int)} to prevent
* duplication of {@code start with}.
*/
@Override

View File

@ -21,25 +21,6 @@ import org.hibernate.type.AssociationType;
* @author Gavin King
*/
public final class JoinHelper {
/**
* Get the qualified (prefixed by alias) names of the columns of the owning entity which are to be used in the join
*
* @param type The association type for the association that represents the join
* @param alias The left-hand side table alias
* @param property The index of the property that represents the association/join
* @param lhsPersister The persister for the left-hand side of the association/join
* @param mapping The mapping (typically the SessionFactory).
*
* @return The qualified column names.
*/
public static String[] getAliasedLHSColumnNames(
AssociationType type,
String alias,
int property,
OuterJoinLoadable lhsPersister,
Mapping mapping) {
return getAliasedLHSColumnNames( type, alias, property, 0, lhsPersister, mapping );
}
/**
* Get the unqualified names of the columns of the owning entity which are to be used in the join.
@ -59,63 +40,6 @@ public final class JoinHelper {
return getLHSColumnNames( type, property, 0, lhsPersister, mapping );
}
/**
*
*/
/**
* Get the qualified (prefixed by alias) names of the columns of the owning entity which are to be used in the join
*
* @param associationType The association type for the association that represents the join
* @param columnQualifier The left-hand side table alias
* @param propertyIndex The index of the property that represents the association/join
* @param begin The index for any nested (composites) attributes
* @param lhsPersister The persister for the left-hand side of the association/join
* @param mapping The mapping (typically the SessionFactory).
*
* @return The qualified column names.
*/
public static String[] getAliasedLHSColumnNames(
AssociationType associationType,
String columnQualifier,
int propertyIndex,
int begin,
OuterJoinLoadable lhsPersister,
Mapping mapping) {
if ( associationType.useLHSPrimaryKey() ) {
return StringHelper.qualify( columnQualifier, lhsPersister.getIdentifierColumnNames() );
}
else {
final String propertyName = associationType.getLHSPropertyName();
if ( propertyName == null ) {
return ArrayHelper.slice(
toColumns( lhsPersister, columnQualifier, propertyIndex ),
begin,
associationType.getColumnSpan( mapping )
);
}
else {
//bad cast
return ( (PropertyMapping) lhsPersister ).toColumns( columnQualifier, propertyName );
}
}
}
private static String[] toColumns(OuterJoinLoadable persister, String columnQualifier, int propertyIndex) {
if ( propertyIndex >= 0 ) {
return persister.toColumns( columnQualifier, propertyIndex );
}
else {
final String[] cols = persister.getIdentifierColumnNames();
final String[] result = new String[cols.length];
for ( int j = 0; j < cols.length; j++ ) {
result[j] = StringHelper.qualify( columnQualifier, cols[j] );
}
return result;
}
}
/**
* Get the columns of the owning entity which are to be used in the join
*

View File

@ -23,7 +23,6 @@ import org.hibernate.JDBCException;
* configuration steps prior to first use.
*
* @author Steve Ebersole
* @see SQLExceptionConverterFactory
*/
public interface SQLExceptionConverter extends Serializable {
/**

View File

@ -1,120 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.exception.spi;
import java.lang.reflect.Constructor;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.exception.GenericJDBCException;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.StringHelper;
import org.jboss.logging.Logger;
/**
* A factory for building SQLExceptionConverter instances.
*
* @author Steve Ebersole
*/
public class SQLExceptionConverterFactory {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class, SQLExceptionConverterFactory.class.getName() );
private SQLExceptionConverterFactory() {
// Private constructor - stops checkstyle from complaining.
}
/**
* Build a SQLExceptionConverter instance.
* <p/>
* First, looks for a {@link Environment#SQL_EXCEPTION_CONVERTER} property to see
* if the configuration specified the class of a specific converter to use. If this
* property is set, attempt to construct an instance of that class. If not set, or
* if construction fails, the converter specific to the dialect will be used.
*
* @param dialect The defined dialect.
* @param properties The configuration properties.
* @return An appropriate SQLExceptionConverter instance.
* @throws HibernateException There was an error building the SQLExceptionConverter.
*/
public static SQLExceptionConverter buildSQLExceptionConverter(Dialect dialect, Properties properties) throws HibernateException {
SQLExceptionConverter converter = null;
String converterClassName = (String) properties.get( Environment.SQL_EXCEPTION_CONVERTER );
if ( StringHelper.isNotEmpty( converterClassName ) ) {
converter = constructConverter( converterClassName, dialect.getViolatedConstraintNameExtractor() );
}
if ( converter == null ) {
LOG.trace( "Using dialect defined converter" );
converter = dialect.buildSQLExceptionConverter();
}
if ( converter instanceof Configurable ) {
try {
( (Configurable) converter ).configure( properties );
}
catch (HibernateException e) {
LOG.unableToConfigureSqlExceptionConverter( e );
throw e;
}
}
return converter;
}
/**
* Builds a minimal converter. The instance returned here just always converts to
* {@link GenericJDBCException}.
*
* @return The minimal converter.
*/
public static SQLExceptionConverter buildMinimalSQLExceptionConverter() {
return new SQLExceptionConverter() {
public JDBCException convert(SQLException sqlException, String message, String sql) {
return new GenericJDBCException( message, sqlException, sql );
}
};
}
private static SQLExceptionConverter constructConverter(String converterClassName, ViolatedConstraintNameExtractor violatedConstraintNameExtractor) {
try {
LOG.tracev( "Attempting to construct instance of specified SQLExceptionConverter [{0}]", converterClassName );
final Class converterClass = ReflectHelper.classForName( converterClassName );
// First, try to find a matching constructor accepting a ViolatedConstraintNameExtractor param...
final Constructor[] ctors = converterClass.getDeclaredConstructors();
for ( Constructor ctor : ctors ) {
final Class[] parameterTypes = ctor.getParameterTypes();
if ( parameterTypes != null && ctor.getParameterCount() == 1 ) {
if ( ViolatedConstraintNameExtractor.class.isAssignableFrom( parameterTypes[0] ) ) {
try {
return (SQLExceptionConverter) ctor.newInstance(violatedConstraintNameExtractor);
}
catch (Throwable ignore) {
// eat it and try next
}
}
}
}
// Otherwise, try to use the no-arg constructor
return (SQLExceptionConverter) converterClass.newInstance();
}
catch (Throwable t) {
LOG.unableToConstructSqlExceptionConverter( t );
}
return null;
}
}

View File

@ -15,6 +15,7 @@ import java.util.Properties;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Database;
@ -362,7 +363,7 @@ public class MultipleHiLoPerTableGenerator implements PersistentIdentifierGenera
query = "select " +
valueColumnName +
" from " +
jdbcEnvironment.getDialect().appendLockHint( LockMode.PESSIMISTIC_WRITE, tableName ) +
jdbcEnvironment.getDialect().appendLockHint( new LockOptions( LockMode.PESSIMISTIC_WRITE ), tableName ) +
" where " + segmentColumnName + " = '" + segmentName + "'" +
jdbcEnvironment.getDialect().getForUpdateString();

View File

@ -174,7 +174,7 @@ public class SequenceGenerator
@Override
public String determineBulkInsertionIdentifierGenerationSelectFragment(Dialect dialect) {
return dialect.getSelectSequenceNextValString( getSequenceName() );
return dialect.getSequenceSupport().getSelectSequenceNextValString( getSequenceName() );
}
@Override

View File

@ -70,7 +70,7 @@ public class SequenceIdentityGenerator
public Delegate(PostInsertIdentityPersister persister, Dialect dialect, String sequenceName) {
super( persister );
this.dialect = dialect;
this.sequenceNextValFragment = dialect.getSelectSequenceNextValString( sequenceName );
this.sequenceNextValFragment = dialect.getSequenceSupport().getSelectSequenceNextValString( sequenceName );
this.keyColumns = getPersister().getRootTableKeyColumnNames();
if ( keyColumns.length > 1 ) {
throw new HibernateException( "sequence-identity generator cannot be used with multi-column keys" );

View File

@ -564,7 +564,7 @@ public class SequenceStyleGenerator
@Override
public String determineBulkInsertionIdentifierGenerationSelectFragment(Dialect dialect) {
return dialect.getSelectSequenceNextValString( getDatabaseStructure().getName() );
return dialect.getSequenceSupport().getSelectSequenceNextValString( getDatabaseStructure().getName() );
}
@Override

View File

@ -15,6 +15,7 @@ import java.sql.Types;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.boot.model.relational.InitCommand;
@ -272,7 +273,7 @@ public class TableStructure implements DatabaseStructure {
this.selectQuery = "select " + valueColumnNameText + " as id_val" +
" from " + dialect.appendLockHint( LockMode.PESSIMISTIC_WRITE, tableNameText ) +
" from " + dialect.appendLockHint( new LockOptions( LockMode.PESSIMISTIC_WRITE ), tableNameText ) +
dialect.getForUpdateString();
this.updateQuery = "update " + tableNameText +

View File

@ -803,80 +803,6 @@ public final class StringHelper {
}
}
public static final String BATCH_ID_PLACEHOLDER = "$$BATCH_ID_PLACEHOLDER$$";
public static StringBuilder buildBatchFetchRestrictionFragment(
String alias,
String[] columnNames,
Dialect dialect) {
// the general idea here is to just insert a placeholder that we can easily find later...
if ( columnNames.length == 1 ) {
// non-composite key
return new StringBuilder( StringHelper.qualify( alias, columnNames[0] ) )
.append( " in (" ).append( BATCH_ID_PLACEHOLDER ).append( ')' );
}
else {
// composite key - the form to use here depends on what the dialect supports.
if ( dialect.supportsRowValueConstructorSyntaxInInList() ) {
// use : (col1, col2) in ( (?,?), (?,?), ... )
StringBuilder builder = new StringBuilder();
builder.append( '(' );
boolean firstPass = true;
String deliminator = "";
for ( String columnName : columnNames ) {
builder.append( deliminator ).append( StringHelper.qualify( alias, columnName ) );
if ( firstPass ) {
firstPass = false;
deliminator = ",";
}
}
builder.append( ") in (" );
builder.append( BATCH_ID_PLACEHOLDER );
builder.append( ')' );
return builder;
}
else {
// use : ( (col1 = ? and col2 = ?) or (col1 = ? and col2 = ?) or ... )
// unfortunately most of this building needs to be held off until we know
// the exact number of ids :(
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append( '(' )
.append( BATCH_ID_PLACEHOLDER )
.append( ')' );
return stringBuilder;
}
}
}
public static String expandBatchIdPlaceholder(
String sql,
Object[] ids,
String alias,
String[] keyColumnNames,
Dialect dialect) {
if ( keyColumnNames.length == 1 ) {
// non-composite
return StringHelper.replace( sql, BATCH_ID_PLACEHOLDER, repeat( "?", ids.length, "," ) );
}
else {
// composite
if ( dialect.supportsRowValueConstructorSyntaxInInList() ) {
final String tuple = '(' + StringHelper.repeat( "?", keyColumnNames.length, "," ) + ')';
return StringHelper.replace( sql, BATCH_ID_PLACEHOLDER, repeat( tuple, ids.length, "," ) );
}
else {
final String keyCheck = '(' + joinWithQualifierAndSuffix(
keyColumnNames,
alias,
" = ?",
" and "
) + ')';
return replace( sql, BATCH_ID_PLACEHOLDER, repeat( keyCheck, ids.length, " or " ) );
}
}
}
public static String nullIfEmpty(String value) {
return isEmpty( value ) ? null : value;
}

View File

@ -44,7 +44,7 @@ import org.hibernate.sql.results.graph.FetchParent;
*/
public class LoaderSqlAstCreationState
implements SqlAstProcessingState, SqlAstCreationState, DomainResultCreationState, QueryOptions {
interface FetchProcessor {
public interface FetchProcessor {
List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, LoaderSqlAstCreationState creationState);
}

View File

@ -673,7 +673,7 @@ public class PluralAttributeMappingImpl
navigablePath,
fetched,
explicitSourceAlias,
aliasBaseGenerator,
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
sqlExpressionResolver,
creationContext
);
@ -701,7 +701,7 @@ public class PluralAttributeMappingImpl
NavigablePath navigablePath,
boolean fetched,
String sourceAlias,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlAliasBase sqlAliasBase,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final EntityMappingType elementDescriptorEntityMappingType;
@ -721,8 +721,6 @@ public class PluralAttributeMappingImpl
indexDescriptorEntityMappingType = null;
}
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
if ( indexDescriptorEntityMappingType == null || elementDescriptorEntityMappingType == null ) {
final EntityMappingType entityMappingType;
if ( indexDescriptorEntityMappingType == null ) {
@ -842,7 +840,7 @@ public class PluralAttributeMappingImpl
navigablePath,
fetched,
explicitSourceAlias,
aliasBaseGenerator,
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
sqlExpressionResolver,
creationContext
);
@ -870,11 +868,9 @@ public class PluralAttributeMappingImpl
NavigablePath navigablePath,
boolean fetched,
String sourceAlias,
SqlAliasBaseGenerator aliasBaseGenerator,
SqlAliasBase sqlAliasBase,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
assert !getCollectionDescriptor().isOneToMany();
final String collectionTableName = ( (Joinable) collectionDescriptor ).getTableName();
@ -1087,13 +1083,33 @@ public class PluralAttributeMappingImpl
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAstCreationState creationState,
SqlAstCreationContext creationContext) {
return createRootTableGroup(
canUseInnerJoins,
navigablePath,
explicitSourceAlias,
additionalPredicateCollectorAccess,
creationState.getSqlAliasBaseGenerator().createSqlAliasBase( getSqlAliasStem() ),
creationState,
creationContext
);
}
@Override
public TableGroup createRootTableGroup(
boolean canUseInnerJoins,
NavigablePath navigablePath,
String explicitSourceAlias,
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
SqlAliasBase sqlAliasBase,
SqlAstCreationState creationState,
SqlAstCreationContext creationContext) {
if ( getCollectionDescriptor().isOneToMany() ) {
return createOneToManyTableGroup(
canUseInnerJoins,
navigablePath,
false,
explicitSourceAlias,
creationState.getSqlAliasBaseGenerator(),
sqlAliasBase,
creationState.getSqlExpressionResolver(),
creationContext
);
@ -1104,7 +1120,7 @@ public class PluralAttributeMappingImpl
navigablePath,
false,
explicitSourceAlias,
creationState.getSqlAliasBaseGenerator(),
sqlAliasBase,
creationState.getSqlExpressionResolver(),
creationContext
);

View File

@ -10,6 +10,7 @@ import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
@ -21,6 +22,7 @@ import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.Filter;
import org.hibernate.HibernateException;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.QueryException;
@ -62,6 +64,7 @@ import org.hibernate.loader.ast.internal.CollectionLoaderBatchKey;
import org.hibernate.loader.ast.internal.CollectionLoaderNamedQuery;
import org.hibernate.loader.ast.internal.CollectionLoaderSingleKey;
import org.hibernate.loader.ast.internal.CollectionLoaderSubSelectFetch;
import org.hibernate.loader.ast.internal.LoaderSqlAstCreationState;
import org.hibernate.loader.ast.spi.CollectionLoader;
import org.hibernate.mapping.BasicValue;
import org.hibernate.mapping.Collection;
@ -97,17 +100,27 @@ import org.hibernate.persister.walking.spi.CompositeCollectionElementDefinition;
import org.hibernate.persister.walking.spi.CompositionDefinition;
import org.hibernate.persister.walking.spi.EntityDefinition;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.sql.Alias;
import org.hibernate.sql.Delete;
import org.hibernate.sql.Insert;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template;
import org.hibernate.sql.Update;
import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.AliasedExpression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.type.AnyType;
import org.hibernate.type.AssociationType;
import org.hibernate.type.CollectionType;
@ -1181,13 +1194,102 @@ public abstract class AbstractCollectionPersister
*/
@Override
public String selectFragment(String alias, String columnSuffix) {
SelectFragment frag = generateSelectFragment( alias, columnSuffix );
appendElementColumns( frag, alias );
appendIndexColumns( frag, alias );
appendIdentifierColumns( frag, alias );
final PluralAttributeMapping attributeMapping = getAttributeMapping();
final QuerySpec rootQuerySpec = new QuerySpec( true );
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(
rootQuerySpec,
new SqlAliasBaseManager(),
new SimpleFromClauseAccessImpl(),
LockOptions.NONE,
(fetchParent, querySpec, creationState) -> new ArrayList<>(),
true,
getFactory()
);
return frag.toFragmentString()
.substring( 2 ); // strip leading ','
final NavigablePath entityPath = new NavigablePath( attributeMapping.getRootPathName() );
final TableGroup rootTableGroup = attributeMapping.createRootTableGroup(
true,
entityPath,
null,
() -> p -> {},
new SqlAliasBaseConstant( alias ),
sqlAstCreationState,
getFactory()
);
rootQuerySpec.getFromClause().addRoot( rootTableGroup );
sqlAstCreationState.getFromClauseAccess().registerTableGroup( entityPath, rootTableGroup );
attributeMapping.createDomainResult( entityPath, rootTableGroup, null, sqlAstCreationState );
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final java.util.List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
int i = 0;
for ( String keyAlias : keyColumnAliases ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), keyAlias + columnSuffix )
)
);
i++;
}
if ( hasIndex ) {
for ( String indexAlias : indexColumnAliases ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), indexAlias + columnSuffix )
)
);
i++;
}
}
if ( hasIdentifier ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierColumnAlias + columnSuffix )
)
);
i++;
}
for ( int columnIndex = 0; i < sqlSelections.size(); i++, columnIndex++ ) {
final SqlSelection sqlSelection = sqlSelections.get( i );
sqlSelections.set(
i,
new SqlSelectionImpl(
sqlSelection.getValuesArrayPosition(),
sqlSelection.getJdbcResultSetIndex(),
new AliasedExpression( sqlSelection.getExpression(), elementColumnAliases[columnIndex] + columnSuffix )
)
);
}
final String sql = getFactory().getJdbcServices()
.getDialect()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( getFactory(), new SelectStatement( rootQuerySpec ) )
.translate( null, QueryOptions.NONE )
.getSql();
final int fromIndex = sql.lastIndexOf( " from" );
final String expression;
if ( fromIndex != -1 ) {
expression = sql.substring( "select ".length(), fromIndex );
}
else {
expression = sql.substring( "select ".length() );
}
return expression;
}
protected String generateSelectSizeString(boolean isIntegerIndexed) {
@ -1228,42 +1330,6 @@ public abstract class AbstractCollectionPersister
.toStatementString();
}
protected SelectFragment generateSelectFragment(String alias, String columnSuffix) {
return new SelectFragment()
.setSuffix( columnSuffix )
.addColumns( alias, keyColumnNames, keyColumnAliases );
}
protected void appendElementColumns(SelectFragment frag, String elemAlias) {
for ( int i = 0; i < elementColumnIsGettable.length; i++ ) {
if ( elementColumnIsGettable[i] ) {
frag.addColumnTemplate( elemAlias, elementColumnReaderTemplates[i], elementColumnAliases[i] );
}
else {
frag.addFormula( elemAlias, elementFormulaTemplates[i], elementColumnAliases[i] );
}
}
}
protected void appendIndexColumns(SelectFragment frag, String alias) {
if ( hasIndex ) {
for ( int i = 0; i < indexColumnIsGettable.length; i++ ) {
if ( indexColumnIsGettable[i] ) {
frag.addColumn( alias, indexColumnNames[i], indexColumnAliases[i] );
}
else {
frag.addFormula( alias, indexFormulaTemplates[i], indexColumnAliases[i] );
}
}
}
}
protected void appendIdentifierColumns(SelectFragment frag, String alias) {
if ( hasIdentifier ) {
frag.addColumn( alias, identifierColumnName, identifierColumnAlias );
}
}
@Override
public String[] getIndexColumnNames() {
return indexColumnNames;
@ -1811,14 +1877,6 @@ public abstract class AbstractCollectionPersister
return buffer.toString();
}
@Override
public String[] toColumns(String alias, String propertyName) throws QueryException {
if ( "index".equals( propertyName ) ) {
return qualify( alias, indexColumnNames, indexFormulaTemplates );
}
return elementPropertyMapping.toColumns( alias, propertyName );
}
private String[] indexFragments;
@Override

View File

@ -11,7 +11,6 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
@ -26,15 +25,12 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.mapping.Collection;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.Delete;
import org.hibernate.sql.Insert;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.Update;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.type.AssociationType;
/**
* Collection persister for collections of values and many-to-many associations.
@ -325,68 +321,6 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
return count;
}
public String selectFragment(
Joinable rhs,
String rhsAlias,
String lhsAlias,
String entitySuffix,
String collectionSuffix,
boolean includeCollectionColumns) {
// we need to determine the best way to know that two joinables
// represent a single many-to-many...
if ( rhs != null && isManyToMany() && !rhs.isCollection() ) {
AssociationType elementType = ( (AssociationType) getElementType() );
if ( rhs.equals( elementType.getAssociatedJoinable( getFactory() ) ) ) {
return manyToManySelectFragment( rhs, rhsAlias, lhsAlias, collectionSuffix );
}
}
return includeCollectionColumns ? selectFragment( lhsAlias, collectionSuffix ) : "";
}
private String manyToManySelectFragment(
Joinable rhs,
String rhsAlias,
String lhsAlias,
String collectionSuffix) {
SelectFragment frag = generateSelectFragment( lhsAlias, collectionSuffix );
String[] elementColumnNames = rhs.getKeyColumnNames();
frag.addColumns( rhsAlias, elementColumnNames, elementColumnAliases );
appendIndexColumns( frag, lhsAlias );
appendIdentifierColumns( frag, lhsAlias );
return frag.toFragmentString()
.substring( 2 ); //strip leading ','
}
@Override
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
return "";
}
@Override
public String fromJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
return "";
}
@Override
public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
return "";
}
@Override
public String whereJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
return "";
}
@Override
public FilterAliasGenerator getFilterAliasGenerator(String rootAlias) {
return new StaticFilterAliasGenerator( rootAlias );

View File

@ -52,60 +52,6 @@ public class CollectionPropertyMapping implements PropertyMapping {
}
}
public String[] toColumns(String alias, String propertyName) throws QueryException {
if ( propertyName.equals(CollectionPropertyNames.COLLECTION_ELEMENTS) ) {
return memberPersister.getElementColumnNames(alias);
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_INDICES) ) {
if ( !memberPersister.hasIndex() ) {
throw new QueryException("unindexed collection in indices()");
}
return memberPersister.getIndexColumnNames(alias);
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_SIZE) ) {
String[] cols = memberPersister.getKeyColumnNames();
return new String[] { "count(" + alias + '.' + cols[0] + ')' };
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_MAX_INDEX) ) {
if ( !memberPersister.hasIndex() ) {
throw new QueryException("unindexed collection in maxIndex()");
}
String[] cols = memberPersister.getIndexColumnNames(alias);
if ( cols.length!=1 ) {
throw new QueryException("composite collection index in maxIndex()");
}
return new String[] { "max(" + cols[0] + ')' };
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_MIN_INDEX) ) {
if ( !memberPersister.hasIndex() ) {
throw new QueryException("unindexed collection in minIndex()");
}
String[] cols = memberPersister.getIndexColumnNames(alias);
if ( cols.length!=1 ) {
throw new QueryException("composite collection index in minIndex()");
}
return new String[] { "min(" + cols[0] + ')' };
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_MAX_ELEMENT) ) {
String[] cols = memberPersister.getElementColumnNames(alias);
if ( cols.length!=1 ) {
throw new QueryException("composite collection element in maxElement()");
}
return new String[] { "max(" + cols[0] + ')' };
}
else if ( propertyName.equals(CollectionPropertyNames.COLLECTION_MIN_ELEMENT) ) {
String[] cols = memberPersister.getElementColumnNames(alias);
if ( cols.length!=1 ) {
throw new QueryException("composite collection element in minElement()");
}
return new String[] { "min(" + cols[0] + ')' };
}
else {
//return memberPersister.toColumns(alias, propertyName);
throw new QueryException("illegal syntax near collection: " + propertyName);
}
}
/**
* Given a property path, return the corresponding column name(s).
*/

View File

@ -7,7 +7,6 @@
package org.hibernate.persister.collection;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.persister.entity.PropertyMapping;
import org.hibernate.type.Type;
@ -34,15 +33,6 @@ public class ElementPropertyMapping implements PropertyMapping {
}
}
public String[] toColumns(String alias, String propertyName) throws QueryException {
if (propertyName==null || "id".equals(propertyName) ) {
return StringHelper.qualify( alias, elementColumns );
}
else {
throw new QueryException("cannot dereference scalar collection element: " + propertyName);
}
}
/**
* Given a property path, return the corresponding column name(s).
*/

View File

@ -478,62 +478,6 @@ public class OneToManyPersister extends AbstractCollectionPersister {
}
}
public String selectFragment(
Joinable rhs,
String rhsAlias,
String lhsAlias,
String entitySuffix,
String collectionSuffix,
boolean includeCollectionColumns) {
StringBuilder buf = new StringBuilder();
if ( includeCollectionColumns ) {
// buf.append( selectFragment( lhsAlias, "" ) )//ignore suffix for collection columns!
buf.append( selectFragment( lhsAlias, collectionSuffix ) )
.append( ", " );
}
OuterJoinLoadable ojl = (OuterJoinLoadable) getElementPersister();
return buf.append( ojl.selectFragment( lhsAlias, entitySuffix ) )//use suffix for the entity columns
.toString();
}
@Override
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
return ( (Joinable) getElementPersister() ).fromJoinFragment( alias, innerJoin, includeSubclasses );
}
@Override
public String fromJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
return ( (Joinable) getElementPersister() ).fromJoinFragment(
alias,
innerJoin,
includeSubclasses,
treatAsDeclarations
);
}
@Override
public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
return ( (Joinable) getElementPersister() ).whereJoinFragment( alias, innerJoin, includeSubclasses );
}
@Override
public String whereJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
return ( (Joinable) getElementPersister() ).whereJoinFragment(
alias,
innerJoin,
includeSubclasses,
treatAsDeclarations
);
}
@Override
public String getTableName() {
return ( (Joinable) getElementPersister() ).getTableName();

View File

@ -116,6 +116,7 @@ import org.hibernate.jdbc.Expectation;
import org.hibernate.jdbc.Expectations;
import org.hibernate.jdbc.TooManyRowsAffectedException;
import org.hibernate.loader.ast.internal.LoaderSelectBuilder;
import org.hibernate.loader.ast.internal.LoaderSqlAstCreationState;
import org.hibernate.loader.ast.internal.MultiIdLoaderStandard;
import org.hibernate.loader.ast.internal.Preparable;
import org.hibernate.loader.ast.internal.SingleIdArrayLoadPlan;
@ -147,18 +148,23 @@ import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.RepresentationMode;
import org.hibernate.metamodel.mapping.Association;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.AttributeMetadata;
import org.hibernate.metamodel.mapping.AttributeMetadataAccess;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.Queryable;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
@ -187,33 +193,33 @@ import org.hibernate.persister.walking.internal.EntityIdentifierDefinitionHelper
import org.hibernate.persister.walking.spi.AttributeDefinition;
import org.hibernate.persister.walking.spi.EntityIdentifierDefinition;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.property.access.spi.Setter;
import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.named.NamedQueryMemento;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.sql.internal.SQLQueryParser;
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.sql.Alias;
import org.hibernate.sql.Delete;
import org.hibernate.sql.Insert;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.JoinType;
import org.hibernate.sql.Select;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template;
import org.hibernate.sql.Update;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.spi.SqlAliasBaseManager;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.AliasedExpression;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
@ -224,11 +230,15 @@ import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.Junction;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.ast.tree.select.SelectClause;
import org.hibernate.sql.ast.tree.select.SelectStatement;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.sql.results.internal.SqlSelectionImpl;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.IdentifierProperty;
@ -367,7 +377,6 @@ public abstract class AbstractEntityPersister
// SQL strings
private String sqlVersionSelectString;
private String sqlSnapshotSelectString;
private Map<String, SingleIdArrayLoadPlan> sqlLazySelectStringsByFetchGroup;
private String sqlIdentityInsertString;
@ -415,9 +424,6 @@ public abstract class AbstractEntityPersister
protected void addDiscriminatorToInsert(Insert insert) {
}
protected void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
}
protected abstract int[] getSubclassColumnTableNumberClosure();
protected abstract int[] getSubclassFormulaTableNumberClosure();
@ -547,10 +553,6 @@ public abstract class AbstractEntityPersister
return result;
}
public String getSQLSnapshotSelectString() {
return sqlSnapshotSelectString;
}
public String getSQLLazySelectString(String fetchGroup) {
final SingleIdArrayLoadPlan singleIdLoadPlan = sqlLazySelectStringsByFetchGroup.get( fetchGroup );
return singleIdLoadPlan == null ? null : singleIdLoadPlan.getJdbcSelect().getSql();
@ -613,18 +615,10 @@ public abstract class AbstractEntityPersister
return deleteCallable[j];
}
protected boolean isSubclassPropertyDeferred(String propertyName, String entityName) {
return false;
}
protected boolean isSubclassTableSequentialSelect(int j) {
return false;
}
public boolean hasSequentialSelect() {
return false;
}
/**
* Decide which tables need to be updated.
* <p/>
@ -1838,8 +1832,173 @@ public abstract class AbstractEntityPersister
}
public String selectFragment(String alias, String suffix) {
return identifierSelectFragment( alias, suffix ) +
propertySelectFragment( alias, suffix, false );
final QuerySpec rootQuerySpec = new QuerySpec( true );
final String rootTableName = getRootTableName();
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(
rootQuerySpec,
new SqlAliasBaseManager(),
new SimpleFromClauseAccessImpl(),
LockOptions.NONE,
(fetchParent, querySpec, creationState) -> {
final List<Fetch> fetches = new ArrayList<>();
fetchParent.getReferencedMappingContainer().visitFetchables(
fetchable -> {
// Ignore plural attributes
if ( fetchable instanceof PluralAttributeMapping ) {
return;
}
FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
final boolean selectable;
if ( fetchable instanceof StateArrayContributorMapping ) {
final int propertyNumber = ( (StateArrayContributorMapping) fetchable ).getStateArrayPosition();
final int tableNumber = getSubclassPropertyTableNumber( propertyNumber );
selectable = !isSubclassTableSequentialSelect( tableNumber )
&& propertySelectable[propertyNumber];
}
else {
selectable = true;
}
if ( fetchable instanceof BasicValuedModelPart ) {
// Ignore lazy basic columns
if ( fetchTiming == FetchTiming.DELAYED ) {
return;
}
}
else if ( fetchable instanceof Association ) {
final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
if ( association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET ) {
return;
}
// Ensure the FK comes from the root table
if ( !rootTableName.equals( association.getForeignKeyDescriptor().getKeyTable() ) ) {
return;
}
fetchTiming = FetchTiming.DELAYED;
}
if ( selectable ) {
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
navigablePath,
fetchTiming,
true,
null,
creationState
);
fetches.add( fetch );
}
},
null
);
return fetches;
},
true,
getFactory()
);
final NavigablePath entityPath = new NavigablePath( getRootPathName() );
final TableGroup rootTableGroup = createRootTableGroup(
true,
entityPath,
null,
() -> p -> {},
new SqlAliasBaseConstant( alias ),
sqlAstCreationState,
getFactory()
);
rootQuerySpec.getFromClause().addRoot( rootTableGroup );
sqlAstCreationState.getFromClauseAccess().registerTableGroup( entityPath, rootTableGroup );
createDomainResult( entityPath, rootTableGroup, null, sqlAstCreationState );
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
int i = 0;
for ( String identifierAlias : identifierAliases ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierAlias + suffix )
)
);
i++;
}
if ( entityMetamodel.hasSubclasses() ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), getDiscriminatorAlias() + suffix )
)
);
i++;
}
if ( hasRowId() ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
i + 1,
new AliasedExpression( sqlSelections.get( i ).getExpression(), ROWID_ALIAS + suffix )
)
);
i++;
}
final String[] columnAliases = getSubclassColumnAliasClosure();
final String[] formulaAliases = getSubclassFormulaAliasClosure();
int columnIndex = 0;
int formulaIndex = 0;
for ( ; i < sqlSelections.size(); i++ ) {
final SqlSelection sqlSelection = sqlSelections.get( i );
final ColumnReference columnReference = (ColumnReference) sqlSelection.getExpression();
final String selectAlias;
if ( !columnReference.isColumnExpressionFormula() ) {
// Skip over columns that are not selectable like in the fetch generation
while ( !subclassColumnSelectableClosure[columnIndex] ) {
columnIndex++;
}
selectAlias = columnAliases[columnIndex++] + suffix;
}
else {
selectAlias = formulaAliases[formulaIndex++] + suffix;
}
sqlSelections.set(
i,
new SqlSelectionImpl(
sqlSelection.getValuesArrayPosition(),
sqlSelection.getJdbcResultSetIndex(),
new AliasedExpression( sqlSelection.getExpression(), selectAlias )
)
);
}
final String sql = getFactory().getJdbcServices()
.getDialect()
.getSqlAstTranslatorFactory()
.buildSelectTranslator( getFactory(), new SelectStatement( rootQuerySpec ) )
.translate( null, QueryOptions.NONE )
.getSql();
final int fromIndex = sql.lastIndexOf( " from" );
final String expression;
if ( fromIndex != -1 ) {
expression = sql.substring( "select ".length(), fromIndex );
}
else {
expression = sql.substring( "select ".length() );
}
return expression;
}
public String[] getIdentifierAliases(String suffix) {
@ -1863,63 +2022,6 @@ public abstract class AbstractEntityPersister
null;
}
public String identifierSelectFragment(String name, String suffix) {
return new SelectFragment()
.setSuffix( suffix )
.addColumns( name, getIdentifierColumnNames(), getIdentifierAliases() )
.toFragmentString()
.substring( 2 ); //strip leading ", "
}
public String propertySelectFragment(String tableAlias, String suffix, boolean allProperties) {
return propertySelectFragmentFragment( tableAlias, suffix, allProperties ).toFragmentString();
}
public SelectFragment propertySelectFragmentFragment(
String tableAlias,
String suffix,
boolean allProperties) {
SelectFragment select = new SelectFragment()
.setSuffix( suffix )
.setUsedAliases( getIdentifierAliases() );
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
String[] columnAliases = getSubclassColumnAliasClosure();
String[] columnReaderTemplates = getSubclassColumnReaderTemplateClosure();
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
boolean selectable = ( allProperties || !subclassColumnLazyClosure[i] ) &&
!isSubclassTableSequentialSelect( columnTableNumbers[i] ) &&
subclassColumnSelectableClosure[i];
if ( selectable ) {
String subalias = generateTableAlias( tableAlias, columnTableNumbers[i] );
select.addColumnTemplate( subalias, columnReaderTemplates[i], columnAliases[i] );
}
}
int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure();
String[] formulaTemplates = getSubclassFormulaTemplateClosure();
String[] formulaAliases = getSubclassFormulaAliasClosure();
for ( int i = 0; i < getSubclassFormulaTemplateClosure().length; i++ ) {
boolean selectable = ( allProperties || !subclassFormulaLazyClosure[i] )
&& !isSubclassTableSequentialSelect( formulaTableNumbers[i] );
if ( selectable ) {
String subalias = generateTableAlias( tableAlias, formulaTableNumbers[i] );
select.addFormula( subalias, formulaTemplates[i], formulaAliases[i] );
}
}
if ( entityMetamodel.hasSubclasses() ) {
addDiscriminatorToSelect( select, tableAlias, suffix );
}
if ( hasRowId() ) {
select.addColumn( tableAlias, rowIdName, ROWID_ALIAS );
}
return select;
}
public Object[] getDatabaseSnapshot(Object id, SharedSessionContractImplementor session) throws HibernateException {
return singleIdEntityLoader.loadDatabaseSnapshot( id, session );
}
@ -1964,120 +2066,10 @@ public abstract class AbstractEntityPersister
return new GeneratedValuesProcessor( this, timing, getFactory() );
}
private String generateGeneratedValuesSelectString(final GenerationTiming generationTimingToMatch) {
Select select = new Select( getFactory().getJdbcServices().getDialect() );
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( "get generated state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
// Here we render the select column list based on the properties defined as being generated.
// For partial component generation, we currently just re-select the whole component
// rather than trying to handle the individual generated portions.
String selectClause = concretePropertySelectFragment(
getRootAlias(),
propertyNumber -> {
final InDatabaseValueGenerationStrategy generationStrategy
= entityMetamodel.getInDatabaseValueGenerationStrategies()[propertyNumber];
GenerationTiming timing = generationStrategy.getGenerationTiming();
return generationStrategy != null
&& (generationTimingToMatch == GenerationTiming.INSERT && timing.includesInsert()
|| generationTimingToMatch == GenerationTiming.ALWAYS && timing.includesUpdate());
}
);
selectClause = selectClause.substring( 2 );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuilder()
.append( String.join( "=? and ", aliasedIdColumns ) )
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
return select.setSelectClause( selectClause )
.setFromClause( fromClause )
.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
}
protected interface InclusionChecker {
boolean includeProperty(int propertyNumber);
}
protected String concretePropertySelectFragment(String alias, final boolean[] includeProperty) {
return concretePropertySelectFragment(
alias,
propertyNumber -> includeProperty[propertyNumber]
);
}
protected String concretePropertySelectFragment(String alias, InclusionChecker inclusionChecker) {
int propertyCount = getPropertyNames().length;
int[] propertyTableNumbers = getPropertyTableNumbersInSelect();
SelectFragment frag = new SelectFragment();
for ( int i = 0; i < propertyCount; i++ ) {
if ( inclusionChecker.includeProperty( i ) ) {
frag.addColumnTemplates(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnReaderTemplates[i],
propertyColumnAliases[i]
);
frag.addFormulas(
generateTableAlias( alias, propertyTableNumbers[i] ),
propertyColumnFormulaTemplates[i],
propertyColumnAliases[i]
);
}
}
return frag.toFragmentString();
}
public String generateSnapshotSelectString() {
//TODO: should we use SELECT .. FOR UPDATE?
Select select = new Select( getFactory().getJdbcServices().getDialect() );
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( "get current state " + getEntityName() );
}
String[] aliasedIdColumns = StringHelper.qualify( getRootAlias(), getIdentifierColumnNames() );
String selectClause = String.join( ", ", aliasedIdColumns ) +
concretePropertySelectFragment( getRootAlias(), getPropertyUpdateability() );
String fromClause = fromTableFragment( getRootAlias() ) +
fromJoinFragment( getRootAlias(), true, false );
String whereClause = new StringBuilder()
.append(
String.join(
"=? and ",
aliasedIdColumns
)
)
.append( "=?" )
.append( whereJoinFragment( getRootAlias(), true, false ) )
.toString();
/*if ( isVersioned() ) {
where.append(" and ")
.append( getVersionColumnName() )
.append("=?");
}*/
return select.setSelectClause( selectClause )
.setFromClause( fromClause )
.setOuterJoins( "", "" )
.setWhereClause( whereClause )
.toStatementString();
}
public Object forceVersionIncrement(Object id, Object currentVersion, SharedSessionContractImplementor session) {
if ( !isVersioned() ) {
throw new AssertionFailure( "cannot force version increment on non-versioned entity" );
@ -2225,21 +2217,6 @@ public abstract class AbstractEntityPersister
return getRootTableKeyColumnNames();
}
/**
* {@inheritDoc}
*
* Warning:
* When there are duplicated property names in the subclasses
* then this method may return the wrong results.
* To ensure correct results, this method should only be used when
* {@literal this} is the concrete EntityPersister (since the
* concrete EntityPersister cannot have duplicated property names).
*/
@Override
public String[] toColumns(String alias, String propertyName) throws QueryException {
return propertyMapping.toColumns( alias, propertyName );
}
/**
* {@inheritDoc}
*
@ -2346,10 +2323,8 @@ public abstract class AbstractEntityPersister
private DiscriminatorMetadata buildTypeDiscriminatorMetadata() {
return new DiscriminatorMetadata() {
public String getSqlFragment(String sqlQualificationAlias) {
return toColumns( sqlQualificationAlias, ENTITY_CLASS )[0];
}
@Override
public Type getResolutionType() {
return new DiscriminatorType( (BasicType) getDiscriminatorType(), AbstractEntityPersister.this );
}
@ -3215,116 +3190,6 @@ public abstract class AbstractEntityPersister
return 0;
}
/**
* Unmarshal the fields of a persistent instance from a result set,
* without resolving associations or collections. Question: should
* this really be here, or should it be sent back to Loader?
*/
@Override
public Object[] hydrate(
final ResultSet rs,
final Object id,
final Object object,
final Loadable rootLoadable,
final String[][] suffixedPropertyColumns,
final boolean forceEager,
final boolean[] propertiesForceEager,
final SharedSessionContractImplementor session) throws SQLException, HibernateException {
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Hydrating entity: {0}", MessageHelper.infoString( this, id, getFactory() ) );
}
final AbstractEntityPersister rootPersister = (AbstractEntityPersister) rootLoadable;
final boolean hasDeferred = rootPersister.hasSequentialSelect();
PreparedStatement sequentialSelect = null;
ResultSet sequentialResultSet = null;
boolean sequentialSelectEmpty = false;
try {
if ( hasDeferred ) {
final String sql = rootPersister.getSequentialSelect( getEntityName() );
if ( sql != null ) {
//TODO: I am not so sure about the exception handling in this bit!
sequentialSelect = session
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql );
rootPersister.getIdentifierType().nullSafeSet( sequentialSelect, id, 1, session );
sequentialResultSet = session.getJdbcCoordinator().getResultSetReturn().extract( sequentialSelect );
if ( !sequentialResultSet.next() ) {
// TODO: Deal with the "optional" attribute in the <join> mapping;
// this code assumes that optional defaults to "true" because it
// doesn't actually seem to work in the fetch="join" code
//
// Note that actual proper handling of optional-ality here is actually
// more involved than this patch assumes. Remember that we might have
// multiple <join/> mappings associated with a single entity. Really
// a couple of things need to happen to properly handle optional here:
// 1) First and foremost, when handling multiple <join/>s, we really
// should be using the entity root table as the driving table;
// another option here would be to choose some non-optional joined
// table to use as the driving table. In all likelihood, just using
// the root table is much simpler
// 2) Need to add the FK columns corresponding to each joined table
// to the generated select list; these would then be used when
// iterating the result set to determine whether all non-optional
// data is present
// My initial thoughts on the best way to deal with this would be
// to introduce a new SequentialSelect abstraction that actually gets
// generated in the persisters (ok, SingleTable...) and utilized here.
// It would encapsulated all this required optional-ality checking...
sequentialSelectEmpty = true;
}
}
}
final String[] propNames = getPropertyNames();
final Type[] types = getPropertyTypes();
final Object[] values = new Object[types.length];
final boolean[] laziness = getPropertyLaziness();
final String[] propSubclassNames = getSubclassPropertySubclassNameClosure();
for ( int i = 0; i < types.length; i++ ) {
if ( !propertySelectable[i] ) {
values[i] = PropertyAccessStrategyBackRefImpl.UNKNOWN;
}
else if ( forceEager || !laziness[i] || propertiesForceEager != null && propertiesForceEager[i] ) {
//decide which ResultSet to get the property value from:
final boolean propertyIsDeferred = hasDeferred &&
rootPersister.isSubclassPropertyDeferred( propNames[i], propSubclassNames[i] );
if ( propertyIsDeferred && sequentialSelectEmpty ) {
values[i] = null;
}
else {
final ResultSet propertyResultSet = propertyIsDeferred ? sequentialResultSet : rs;
final String[] cols = propertyIsDeferred ?
propertyColumnAliases[i] :
suffixedPropertyColumns[i];
values[i] = types[i].hydrate( propertyResultSet, cols, session, object );
}
}
else {
values[i] = LazyPropertyInitializer.UNFETCHED_PROPERTY;
}
}
if ( sequentialResultSet != null ) {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( sequentialResultSet, sequentialSelect );
}
return values;
}
finally {
if ( sequentialSelect != null ) {
session.getJdbcCoordinator().getLogicalConnection().getResourceRegistry().release( sequentialSelect );
session.getJdbcCoordinator().afterStatementExecution();
}
}
}
public boolean useInsertSelectIdentity() {
return !useGetGeneratedKeys()
&& getFactory().getJdbcServices().getDialect().getIdentityColumnSupport().supportsInsertSelectIdentity();
@ -3334,10 +3199,6 @@ public abstract class AbstractEntityPersister
return getFactory().getSessionFactoryOptions().isGetGeneratedKeysEnabled();
}
protected String getSequentialSelect(String entityName) {
throw new UnsupportedOperationException( "no sequential selects" );
}
/**
* Perform an SQL INSERT, and then retrieve a generated identifier.
* <p/>
@ -4098,9 +3959,6 @@ public abstract class AbstractEntityPersister
if ( sqlVersionSelectString != null ) {
LOG.debugf( " Version select: %s", sqlVersionSelectString );
}
if ( sqlSnapshotSelectString != null ) {
LOG.debugf( " Snapshot select: %s", sqlSnapshotSelectString );
}
for ( int j = 0; j < getTableSpan(); j++ ) {
LOG.debugf( " Insert %s: %s", j, getSQLInsertStrings()[j] );
LOG.debugf( " Update %s: %s", j, getSQLUpdateStrings()[j] );
@ -4167,115 +4025,10 @@ public abstract class AbstractEntityPersister
return oneToManyFilterFragment( alias );
}
@Override
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
// NOTE : Not calling createJoin here is just a performance optimization
return getSubclassTableSpan() == 1
? ""
: createJoin(
alias,
innerJoin,
includeSubclasses,
Collections.emptySet(),
null
).toFromFragmentString();
}
@Override
public String fromJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
// NOTE : Not calling createJoin here is just a performance optimization
return getSubclassTableSpan() == 1
? ""
: createJoin( alias, innerJoin, includeSubclasses, treatAsDeclarations, null ).toFromFragmentString();
}
@Override
public String fromJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations,
Set<String> referencedTables) {
return getSubclassTableSpan() == 1
? ""
: createJoin( alias, innerJoin, includeSubclasses, treatAsDeclarations, referencedTables ).toFromFragmentString();
}
@Override
public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) {
// NOTE : Not calling createJoin here is just a performance optimization
return getSubclassTableSpan() == 1
? ""
: createJoin(
alias,
innerJoin,
includeSubclasses,
Collections.emptySet(),
null
).toWhereFragmentString();
}
@Override
public String whereJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
// NOTE : Not calling createJoin here is just a performance optimization
return getSubclassTableSpan() == 1
? ""
: createJoin( alias, innerJoin, includeSubclasses, treatAsDeclarations, null ).toWhereFragmentString();
}
protected boolean isSubclassTableLazy(int j) {
return false;
}
protected JoinFragment createJoin(
String name,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations) {
return createJoin(name, innerJoin, includeSubclasses, treatAsDeclarations, null);
}
protected JoinFragment createJoin(
String name,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations,
Set<String> referencedTables) {
// IMPL NOTE : all joins join to the pk of the driving table
final String[] idCols = StringHelper.qualify( name, getIdentifierColumnNames() );
final JoinFragment join = getFactory().getJdbcServices().getDialect().createOuterJoinFragment();
final int tableSpan = getSubclassTableSpan();
// IMPL NOTE : notice that we skip the first table; it is the driving table!
for ( int j = 1; j < tableSpan; j++ ) {
final JoinType joinType = determineSubclassTableJoinType(
j,
innerJoin,
includeSubclasses,
treatAsDeclarations,
referencedTables
);
if ( joinType != null && joinType != JoinType.NONE ) {
join.addJoin(
getSubclassTableName( j ),
generateTableAlias( name, j ),
idCols,
getSubclassTableKeyColumns( j ),
joinType
);
}
}
return join;
}
protected SqlAstJoinType determineSubclassTableJoinType(
int subclassTableNumber,
Set<String> treatAsDeclarations) {
@ -4300,155 +4053,12 @@ public abstract class AbstractEntityPersister
return SqlAstJoinType.LEFT;
}
protected JoinType determineSubclassTableJoinType(
int subclassTableNumber,
boolean canInnerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations,
Set<String> referencedTables) {
if ( isClassOrSuperclassJoin( subclassTableNumber ) ) {
String superclassTableName = getSubclassTableName( subclassTableNumber );
if ( referencedTables != null && canOmitSuperclassTableJoin() && !referencedTables.contains(
superclassTableName ) ) {
return JoinType.NONE;
}
final boolean shouldInnerJoin = canInnerJoin
&& !isInverseTable( subclassTableNumber )
&& !isNullableTable( subclassTableNumber );
// the table is either this persister's driving table or (one of) its super class persister's driving
// tables which can be inner joined as long as the `shouldInnerJoin` condition resolves to true
return shouldInnerJoin ? JoinType.INNER_JOIN : JoinType.LEFT_OUTER_JOIN;
}
// otherwise we have a subclass table and need to look a little deeper...
// IMPL NOTE : By default includeSubclasses indicates that all subclasses should be joined and that each
// subclass ought to be joined by outer-join. However, TREAT-AS always requires that an inner-join be used
// so we give TREAT-AS higher precedence...
if ( isSubclassTableIndicatedByTreatAsDeclarations( subclassTableNumber, treatAsDeclarations ) ) {
return JoinType.INNER_JOIN;
}
if ( includeSubclasses
&& !isSubclassTableSequentialSelect( subclassTableNumber )
&& !isSubclassTableLazy( subclassTableNumber ) ) {
return JoinType.LEFT_OUTER_JOIN;
}
return JoinType.NONE;
}
protected boolean isSubclassTableIndicatedByTreatAsDeclarations(
int subclassTableNumber,
Set<String> treatAsDeclarations) {
return false;
}
protected JoinFragment createJoin(int[] tableNumbers, String drivingAlias) {
final String[] keyCols = StringHelper.qualify( drivingAlias, getSubclassTableKeyColumns( tableNumbers[0] ) );
final JoinFragment jf = getFactory().getJdbcServices().getDialect().createOuterJoinFragment();
// IMPL NOTE : notice that we skip the first table; it is the driving table!
for ( int i = 1; i < tableNumbers.length; i++ ) {
final int j = tableNumbers[i];
jf.addJoin(
getSubclassTableName( j ),
generateTableAlias( getRootAlias(), j ),
keyCols,
getSubclassTableKeyColumns( j ),
isInverseSubclassTable( j ) || isNullableSubclassTable( j )
? JoinType.LEFT_OUTER_JOIN
: JoinType.INNER_JOIN
);
}
return jf;
}
protected SelectFragment createSelect(
final int[] subclassColumnNumbers,
final int[] subclassFormulaNumbers) {
SelectFragment selectFragment = new SelectFragment();
int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
String[] columnAliases = getSubclassColumnAliasClosure();
String[] columnReaderTemplates = getSubclassColumnReaderTemplateClosure();
for ( int i = 0; i < subclassColumnNumbers.length; i++ ) {
int columnNumber = subclassColumnNumbers[i];
if ( subclassColumnSelectableClosure[columnNumber] ) {
final String subalias = generateTableAlias( getRootAlias(), columnTableNumbers[columnNumber] );
selectFragment.addColumnTemplate(
subalias,
columnReaderTemplates[columnNumber],
columnAliases[columnNumber]
);
}
}
int[] formulaTableNumbers = getSubclassFormulaTableNumberClosure();
String[] formulaTemplates = getSubclassFormulaTemplateClosure();
String[] formulaAliases = getSubclassFormulaAliasClosure();
for ( int i = 0; i < subclassFormulaNumbers.length; i++ ) {
int formulaNumber = subclassFormulaNumbers[i];
final String subalias = generateTableAlias( getRootAlias(), formulaTableNumbers[formulaNumber] );
selectFragment.addFormula( subalias, formulaTemplates[formulaNumber], formulaAliases[formulaNumber] );
}
return selectFragment;
}
protected String createFrom(int tableNumber, String alias) {
return getSubclassTableName( tableNumber ) + ' ' + alias;
}
protected String createWhereByKey(int tableNumber, String alias) {
//TODO: move to .sql package, and refactor with similar things!
return String.join(
"=? and ",
StringHelper.qualify( alias, getSubclassTableKeyColumns( tableNumber ) )
) + "=?";
}
protected String renderSelect(
final int[] tableNumbers,
final int[] columnNumbers,
final int[] formulaNumbers) {
Arrays.sort( tableNumbers ); //get 'em in the right order (not that it really matters)
//render the where and from parts
int drivingTable = tableNumbers[0];
final String drivingAlias = generateTableAlias(
getRootAlias(),
drivingTable
); //we *could* regenerate this inside each called method!
final String where = createWhereByKey( drivingTable, drivingAlias );
final String from = createFrom( drivingTable, drivingAlias );
//now render the joins
JoinFragment jf = createJoin( tableNumbers, drivingAlias );
//now render the select clause
SelectFragment selectFragment = createSelect( columnNumbers, formulaNumbers );
//now tie it all together
Select select = new Select( getFactory().getJdbcServices().getDialect() );
select.setSelectClause( selectFragment.toFragmentString().substring( 2 ) );
select.setFromClause( from );
select.setWhereClause( where );
select.setOuterJoins( jf.toFromFragmentString(), jf.toWhereFragmentString() );
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( "sequential select " + getEntityName() );
}
return select.toStatementString();
}
private String getRootAlias() {
return StringHelper.generateAlias( getEntityName() );
}
/**
* Post-construct is a callback for AbstractEntityPersister subclasses to call after they are all done with their
* constructor processing. It allows AbstractEntityPersister to extend its construction after all subclass-specific
@ -4501,7 +4111,6 @@ public abstract class AbstractEntityPersister
}
//select SQL
sqlSnapshotSelectString = generateSnapshotSelectString();
sqlLazySelectStringsByFetchGroup = generateLazySelectStringsByFetchGroup();
sqlVersionSelectString = generateSelectVersionString();
if ( isIdentifierAssignedByInsert() ) {
@ -5162,16 +4771,6 @@ public abstract class AbstractEntityPersister
'(' + entityMetamodel.getName() + ')';
}
public final String selectFragment(
Joinable rhs,
String rhsAlias,
String lhsAlias,
String entitySuffix,
String collectionSuffix,
boolean includeCollectionColumns) {
return selectFragment( lhsAlias, entitySuffix );
}
public boolean isInstrumented() {
return entityMetamodel.getBytecodeEnhancementMetadata().isEnhancedForLazyLoading();
}
@ -6829,37 +6428,6 @@ public abstract class AbstractEntityPersister
return attributeDefinitions;
}
public String[][] getPolymorphicJoinColumns(String lhsTableAlias, String propertyPath) {
Set<String> subclassEntityNames = getEntityMetamodel().getSubclassEntityNames();
// We will collect all the join columns from the LHS subtypes here
List<String[]> polymorphicJoinColumns = new ArrayList<>( subclassEntityNames.size() );
String[] joinColumns;
OUTER:
for ( String subclassEntityName : subclassEntityNames ) {
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) getFactory()
.getMetamodel()
.entityPersister( subclassEntityName );
joinColumns = subclassPersister.toColumns( lhsTableAlias, propertyPath );
if ( joinColumns.length == 0 ) {
// The subtype does not have a "concrete" mapping for the property path
continue;
}
// Check for duplicates like this since we will mostly have just a few candidates
for ( String[] existingColumns : polymorphicJoinColumns ) {
if ( Arrays.deepEquals( existingColumns, joinColumns ) ) {
continue OUTER;
}
}
polymorphicJoinColumns.add( joinColumns );
}
return ArrayHelper.to2DStringArray( polymorphicJoinColumns );
}
/**
* If true, persister can omit superclass tables during joining if they are not needed in the query.
*

View File

@ -85,26 +85,6 @@ public abstract class AbstractPropertyMapping implements PropertyMapping {
return cols;
}
public String[] toColumns(String alias, String propertyName) throws QueryException {
//TODO: *two* hashmap lookups here is one too many...
String[] columns = columnsByPropertyPath.get( propertyName );
if ( columns == null ) {
throw propertyException( propertyName );
}
String[] formulaTemplates = formulaTemplatesByPropertyPath.get( propertyName );
String[] columnReaderTemplates = columnReaderTemplatesByPropertyPath.get( propertyName );
String[] result = new String[columns.length];
for ( int i = 0; i < columns.length; i++ ) {
if ( columnReaderTemplates[i] == null ) {
result[i] = StringHelper.replace( formulaTemplates[i], Template.TEMPLATE, alias );
}
else {
result[i] = StringHelper.replace( columnReaderTemplates[i], Template.TEMPLATE, alias );
}
}
return result;
}
public String[] toColumns(String propertyName) throws QueryException {
String[] columns = columnsByPropertyPath.get( propertyName );
if ( columns == null ) {

View File

@ -6,8 +6,6 @@
*/
package org.hibernate.persister.entity;
import org.hibernate.QueryException;
/**
* @author Gavin King
*/
@ -35,15 +33,5 @@ public class BasicEntityPropertyMapping extends AbstractPropertyMapping {
return persister.getEntityName();
}
public String[] toColumns(final String alias, final String propertyName) throws QueryException {
return super.toColumns(
AbstractEntityPersister.generateTableAlias(
alias,
persister.getSubclassPropertyTableNumber( propertyName )
),
propertyName
);
}
}

View File

@ -14,19 +14,9 @@ import org.hibernate.type.Type;
* @author Steve Ebersole
*/
public interface DiscriminatorMetadata {
/**
* Get the sql fragment that is used to determine the actual discriminator value for a row.
*
* @param sqlQualificationAlias The qualification alias to append to any columns references in
* the generated fragment.
*
* @return The fragment
*/
public String getSqlFragment(String sqlQualificationAlias);
/**
* Get the type used to resolve the actual discriminator value resulting from
* {@link #getSqlFragment} back into a {@link Class} reference.
* Get the type used to resolve the actual discriminator value.
*
* @return The resolution type.
*/

View File

@ -31,48 +31,6 @@ public interface Joinable {
*/
public String getTableName();
/**
* All columns to select, when loading.
*/
public String selectFragment(Joinable rhs, String rhsAlias, String lhsAlias, String currentEntitySuffix, String currentCollectionSuffix, boolean includeCollectionColumns);
/**
* Get the where clause part of any joins
* (optional operation)
*/
public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses);
/**
* Get the where clause part of any joins
* (optional operation)
*/
public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses, Set<String> treatAsDeclarations);
/**
* Get the from clause part of any joins
* (optional operation)
*/
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses);
/**
* Get the from clause part of any joins
* (optional operation)
*/
public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses, Set<String> treatAsDeclarations);
/**
* Get the from clause part of any joins
* (optional operation)
*/
default String fromJoinFragment(
String alias,
boolean innerJoin,
boolean includeSubclasses,
Set<String> treatAsDeclarations,
Set<String> referencedTables) {
return fromJoinFragment( alias, innerJoin, includeSubclasses, treatAsDeclarations );
}
/**
* The columns to join on
*/

View File

@ -18,7 +18,6 @@ import java.util.Set;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.QueryException;
import org.hibernate.boot.model.relational.Database;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.access.NaturalIdDataAccess;
@ -28,7 +27,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.DynamicFilterAliasGenerator;
import org.hibernate.internal.FilterAliasGenerator;
import org.hibernate.internal.util.MarkerObject;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Column;
@ -53,10 +51,8 @@ import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.CaseFragment;
import org.hibernate.sql.InFragment;
import org.hibernate.sql.Insert;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
@ -959,20 +955,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
return tableNames[0];
}
public void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
if ( hasSubclasses() ) {
if ( explicitDiscriminatorColumnName == null ) {
select.setExtraSelectList( discriminatorFragment( name ), getDiscriminatorAlias() );
}
else {
if ( getEntityMetamodel().getSuperclass() != null ) {
name = generateTableAlias( name, getRootHierarchyClassTableIndex() );
}
select.addColumn( name, explicitDiscriminatorColumnName, discriminatorAlias );
}
}
}
private int getRootHierarchyClassTableIndex() {
final String rootHierarchyClassTableName = naturalOrderTableNames[0];
for ( int i = 0; i < subclassTableNameClosure.length; i++ ) {
@ -983,20 +965,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
return 0;
}
private CaseFragment discriminatorFragment(String alias) {
CaseFragment cases = getFactory().getJdbcServices().getDialect().createCaseFragment();
for ( int i = 0; i < discriminatorValues.length; i++ ) {
cases.addWhenColumnNotNull(
generateTableAlias( alias, notNullColumnTableNumbers[i] ),
notNullColumnNames[i],
discriminatorValues[i]
);
}
return cases;
}
@Override
protected String filterFragment(String alias) {
return hasWhere() ? getSQLWhereString( generateFilterConditionAlias( alias ) ) : "";
@ -1028,20 +996,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
return tableKeyColumnReaders[0];
}
public String[] toColumns(String alias, String propertyName) throws QueryException {
if ( ENTITY_CLASS.equals( propertyName ) ) {
if ( explicitDiscriminatorColumnName == null ) {
return new String[] { discriminatorFragment( alias ).toFragmentString() };
}
else {
return new String[] { StringHelper.qualify( alias, explicitDiscriminatorColumnName ) };
}
}
else {
return super.toColumns( alias, propertyName );
}
}
protected int[] getPropertyTableNumbersInSelect() {
return propertyTableNumbers;
}

View File

@ -17,7 +17,6 @@ import org.hibernate.type.Type;
* Implemented by a <tt>EntityPersister</tt> that may be loaded
* using <tt>Loader</tt>.
*
* @see org.hibernate.loader.Loader
* @author Gavin King
*/
public interface Loadable extends EntityPersister {
@ -79,33 +78,6 @@ public interface Loadable extends EntityPersister {
*/
boolean hasRowId();
/**
* Retrieve property values from one row of a result set
*/
default Object[] hydrate(
ResultSet rs,
Object id,
Object object,
Loadable rootLoadable,
String[][] suffixedPropertyColumns,
boolean forceEager,
SharedSessionContractImplementor session) throws SQLException, HibernateException {
return hydrate( rs, id, object, rootLoadable, suffixedPropertyColumns, forceEager, null, session );
}
/**
* Retrieve property values from one row of a result set
*/
Object[] hydrate(
ResultSet rs,
Object id,
Object object,
Loadable rootLoadable,
String[][] suffixedPropertyColumns,
boolean forceEager,
boolean[] propertiesForceEager,
SharedSessionContractImplementor session) throws SQLException, HibernateException;
boolean isAbstract();
/**

View File

@ -63,11 +63,6 @@ public interface PropertyMapping {
*/
public Type toType(String propertyName) throws QueryException;
/**
* Obtain aliased column/formula fragments for the specified property path.
*/
public String[] toColumns(String alias, String propertyName) throws QueryException;
/**
* Given a property path, return the corresponding column name(s).
*/

View File

@ -5,7 +5,6 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.persister.entity;
import org.hibernate.sql.SelectFragment;
/**
* Extends the generic <tt>EntityPersister</tt> contract to add
@ -37,16 +36,6 @@ public interface Queryable extends Loadable, PropertyMapping, Joinable {
*/
public String getDiscriminatorSQLValue();
/**
* Given a query alias and an identifying suffix, render the identifier select fragment.
*/
public String identifierSelectFragment(String name, String suffix);
/**
* Given a query alias and an identifying suffix, render the property select fragment.
*/
public String propertySelectFragment(String alias, String suffix, boolean allProperties);
public SelectFragment propertySelectFragmentFragment(String alias, String suffix, boolean allProperties);
/**
* Get the names of columns used to persist the identifier
*/

View File

@ -9,7 +9,6 @@ package org.hibernate.persister.entity;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -46,7 +45,6 @@ import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.InFragment;
import org.hibernate.sql.Insert;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -66,8 +64,6 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.DiscriminatorType;
import org.hibernate.type.Type;
import static java.util.Collections.emptyMap;
/**
* The default implementation of the <tt>EntityPersister</tt> interface.
* Implements the "table-per-class-hierarchy" or "roll-up" mapping strategy
@ -86,7 +82,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
private final boolean[] isNullableTable;
private final String[][] keyColumnNames;
private final boolean[] cascadeDeleteEnabled;
private final boolean hasSequentialSelects;
private final String[] spaces;
@ -131,9 +126,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
//private final Map propertyTableNumbersByName = new HashMap();
private final Map<String, Integer> propertyTableNumbersByNameAndSubclass;
//Efficiency note: try to not allocate an HashMap if we're not going to need it.
private final Map<String, String> sequentialSelectStringsByEntityName;
private static final Object NULL_DISCRIMINATOR = new MarkerObject( "<null discriminator>" );
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject( "<not null discriminator>" );
@ -299,9 +291,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
isClassOrSuperclassJoin = ArrayHelper.toBooleanArray( isClassOrSuperclassJoins );
isInverseSubclassTable = ArrayHelper.toBooleanArray( isInverses );
isNullableSubclassTable = ArrayHelper.toBooleanArray( isNullables );
hasSequentialSelects = hasDeferred;
sequentialSelectStringsByEntityName = hasSequentialSelects ? new HashMap<>() : emptyMap();
// DISCRIMINATOR
@ -722,15 +711,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return subclassTableNameClosure[subclassPropertyTableNumberClosure[i]];
}
protected void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
if ( isDiscriminatorFormula() ) {
select.addFormula( name, getDiscriminatorFormulaTemplate(), getDiscriminatorAlias() );
}
else {
select.addColumn( name, getDiscriminatorColumnName(), getDiscriminatorAlias() );
}
}
protected int[] getPropertyTableNumbersInSelect() {
return propertyTableNumbers;
}
@ -763,15 +743,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return propertyTableNumbers;
}
protected boolean isSubclassPropertyDeferred(String propertyName, String entityName) {
return hasSequentialSelects &&
isSubclassTableSequentialSelect( getSubclassPropertyTableNumber( propertyName, entityName ) );
}
public boolean hasSequentialSelect() {
return hasSequentialSelects;
}
private int getSubclassPropertyTableNumber(String propertyName, String entityName) {
// When there are duplicated property names in the subclasses
// then propertyMapping.toType( propertyName ) may return an
@ -793,58 +764,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return tabnum == null ? 0 : tabnum;
}
protected String getSequentialSelect(String entityName) {
return sequentialSelectStringsByEntityName.get( entityName );
}
private String generateSequentialSelect(Loadable persister) {
//if ( this==persister || !hasSequentialSelects ) return null;
//note that this method could easily be moved up to BasicEntityPersister,
//if we ever needed to reuse it from other subclasses
//figure out which tables need to be fetched
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
HashSet<Integer> tableNumbers = new HashSet<>();
String[] props = subclassPersister.getPropertyNames();
String[] classes = subclassPersister.getPropertySubclassNames();
for ( int i = 0; i < props.length; i++ ) {
int propTableNumber = getSubclassPropertyTableNumber( props[i], classes[i] );
if ( isSubclassTableSequentialSelect( propTableNumber ) && !isSubclassTableLazy( propTableNumber ) ) {
tableNumbers.add( propTableNumber );
}
}
if ( tableNumbers.isEmpty() ) {
return null;
}
//figure out which columns are needed
ArrayList<Integer> columnNumbers = new ArrayList<>();
final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
for ( int i = 0; i < getSubclassColumnClosure().length; i++ ) {
if ( tableNumbers.contains( columnTableNumbers[i] ) ) {
columnNumbers.add( i );
}
}
//figure out which formulas are needed
ArrayList<Integer> formulaNumbers = new ArrayList<>();
final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
for ( int i = 0; i < getSubclassFormulaTemplateClosure().length; i++ ) {
if ( tableNumbers.contains( formulaTableNumbers[i] ) ) {
formulaNumbers.add( i );
}
}
//render the SQL
return renderSelect(
ArrayHelper.toIntArray( tableNumbers ),
ArrayHelper.toIntArray( columnNumbers ),
ArrayHelper.toIntArray( formulaNumbers )
);
}
protected String[] getSubclassTableKeyColumns(int j) {
return subclassTableKeyColumnClosure[j];
}
@ -891,19 +810,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return qualifiedTableNames[propertyTableNumbers[index]];
}
protected void doPostInstantiate() {
if ( hasSequentialSelects ) {
String[] entityNames = getSubclassClosure();
for ( int i = 1; i < entityNames.length; i++ ) {
Loadable loadable = (Loadable) getFactory().getMetamodel().entityPersister( entityNames[i] );
if ( !loadable.isAbstract() ) { //perhaps not really necessary...
String sequentialSelect = generateSequentialSelect( loadable );
sequentialSelectStringsByEntityName.put( entityNames[i], sequentialSelect );
}
}
}
}
@Override
public boolean canOmitSuperclassTableJoin() {
return true;

View File

@ -45,7 +45,6 @@ import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.SelectFragment;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -365,11 +364,6 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
return getTableName();//ie. the subquery! yuck!
}
@Override
protected void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
select.addColumn( name, getDiscriminatorColumnName(), getDiscriminatorAlias() );
}
@Override
protected int[] getPropertyTableNumbersInSelect() {
return new int[getPropertySpan()];

View File

@ -1,43 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.Map;
/**
* An ANSI SQL CASE expression : {@code case when ... then ... end as ..}
*
* @author Gavin King
* @author Simon Harris
*/
public class ANSICaseFragment extends CaseFragment {
@Override
public String toFragmentString() {
final StringBuilder buf = new StringBuilder( cases.size() * 15 + 10 )
.append("case");
for ( Object o : cases.entrySet() ) {
Map.Entry me = (Map.Entry) o;
buf.append( " when " )
.append( me.getKey() )
.append( " is not null then " )
.append( me.getValue() );
}
buf.append(" end");
if (returnColumnName!=null) {
buf.append(" as ")
.append(returnColumnName);
}
return buf.toString();
}
}

View File

@ -1,218 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.AssertionFailure;
/**
* An ANSI-style join.
*
* @author Gavin King
*/
public class ANSIJoinFragment extends JoinFragment {
private StringBuilder buffer = new StringBuilder();
private StringBuilder conditions = new StringBuilder();
/**
* Adds a join, represented by the given information, to the fragment.
*
* @param tableName The name of the table being joined.
* @param alias The alias applied to the table being joined.
* @param fkColumns The columns (from the table being joined) used to define the join-restriction (the ON)
* @param pkColumns The columns (from the table being joined to) used to define the join-restriction (the ON)
* @param joinType The type of join to produce (INNER, etc).
*/
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType) {
addJoin( tableName, alias, fkColumns, pkColumns, joinType, null );
}
/**
* Adds a join, represented by the given information, to the fragment.
*
* @param rhsTableName The name of the table being joined (the RHS table).
* @param rhsAlias The alias applied to the table being joined (the alias for the RHS table).
* @param lhsColumns The columns (from the table being joined) used to define the join-restriction (the ON). These
* are the LHS columns, and are expected to be qualified.
* @param rhsColumns The columns (from the table being joined to) used to define the join-restriction (the ON). These
* are the RHS columns and are expected to *not* be qualified.
* @param joinType The type of join to produce (INNER, etc).
* @param on Any extra join restrictions
*/
public void addJoin(
String rhsTableName,
String rhsAlias,
String[] lhsColumns,
String[] rhsColumns,
JoinType joinType,
String on) {
final String joinString;
switch (joinType) {
case INNER_JOIN:
joinString = " inner join ";
break;
case LEFT_OUTER_JOIN:
joinString = " left outer join ";
break;
case RIGHT_OUTER_JOIN:
joinString = " right outer join ";
break;
case FULL_JOIN:
joinString = " full outer join ";
break;
default:
throw new AssertionFailure("undefined join type");
}
this.buffer.append(joinString)
.append(rhsTableName)
.append(' ')
.append(rhsAlias)
.append(" on ");
for ( int j=0; j<lhsColumns.length; j++) {
this.buffer.append( lhsColumns[j] )
.append('=')
.append(rhsAlias)
.append('.')
.append( rhsColumns[j] );
if ( j < lhsColumns.length-1 ) {
this.buffer.append( " and " );
}
}
addCondition( buffer, on );
}
public void addJoin(
String rhsTableName,
String rhsAlias,
String[][] lhsColumns,
String[] rhsColumns,
JoinType joinType,
String on) {
final String joinString;
switch (joinType) {
case INNER_JOIN:
joinString = " inner join ";
break;
case LEFT_OUTER_JOIN:
joinString = " left outer join ";
break;
case RIGHT_OUTER_JOIN:
joinString = " right outer join ";
break;
case FULL_JOIN:
joinString = " full outer join ";
break;
default:
throw new AssertionFailure("undefined join type");
}
this.buffer.append(joinString)
.append(rhsTableName)
.append(' ')
.append(rhsAlias)
.append(" on ");
if ( lhsColumns.length > 1 ) {
this.buffer.append( "(" );
}
for ( int i = 0; i < lhsColumns.length; i++ ) {
for ( int j=0; j<lhsColumns[i].length; j++) {
this.buffer.append( lhsColumns[i][j] )
.append('=')
.append(rhsAlias)
.append('.')
.append( rhsColumns[j] );
if ( j < lhsColumns[i].length-1 ) {
this.buffer.append( " and " );
}
}
if ( i < lhsColumns.length - 1 ) {
this.buffer.append( " or " );
}
}
if ( lhsColumns.length > 1 ) {
this.buffer.append( ")" );
}
addCondition( buffer, on );
}
@Override
public String toFromFragmentString() {
return this.buffer.toString();
}
@Override
public String toWhereFragmentString() {
return this.conditions.toString();
}
@Override
public void addJoins(String fromFragment, String whereFragment) {
this.buffer.append( fromFragment );
//where fragment must be empty!
}
@Override
public JoinFragment copy() {
final ANSIJoinFragment copy = new ANSIJoinFragment();
copy.buffer = new StringBuilder( this.buffer.toString() );
return copy;
}
/**
* Adds a condition to the join fragment. For each given column a predicate is built in the form:
* {@code [alias.[column] = [condition]}
*
* @param alias The alias to apply to column(s)
* @param columns The columns to apply restriction
* @param condition The restriction condition
*/
public void addCondition(String alias, String[] columns, String condition) {
for ( String column : columns ) {
this.conditions.append( " and " )
.append( alias )
.append( '.' )
.append( column )
.append( condition );
}
}
@Override
public void addCrossJoin(String tableName, String alias) {
this.buffer.append(", ")
.append(tableName)
.append(' ')
.append(alias);
}
@Override
public void addCondition(String alias, String[] fkColumns, String[] pkColumns) {
throw new UnsupportedOperationException();
}
@Override
public boolean addCondition(String condition) {
return addCondition(conditions, condition);
}
/**
* Adds an externally built join fragment.
*
* @param fromFragmentString The join fragment string
*/
public void addFromFragmentString(String fromFragmentString) {
this.buffer.append(fromFragmentString);
}
}

View File

@ -1,39 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.internal.util.StringHelper;
/**
* Abstract SQL case fragment renderer
*
* @author Gavin King, Simon Harris
*/
public abstract class CaseFragment {
public abstract String toFragmentString();
protected String returnColumnName;
protected Map cases = new LinkedHashMap();
public CaseFragment setReturnColumnName(String returnColumnName) {
this.returnColumnName = returnColumnName;
return this;
}
public CaseFragment setReturnColumnName(String returnColumnName, String suffix) {
return setReturnColumnName( new Alias(suffix).toAliasString(returnColumnName) );
}
public CaseFragment addWhenColumnNotNull(String alias, String columnName, String value) {
cases.put( StringHelper.qualify( alias, columnName ), value );
return this;
}
}

View File

@ -1,65 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.internal.util.collections.ArrayHelper;
/**
* @author Gavin King
*/
public class ConditionFragment {
private String tableAlias;
private String[] lhs;
private String[] rhs;
private String op = "=";
/**
* Sets the op.
* @param op The op to set
*/
public ConditionFragment setOp(String op) {
this.op = op;
return this;
}
/**
* Sets the tableAlias.
* @param tableAlias The tableAlias to set
*/
public ConditionFragment setTableAlias(String tableAlias) {
this.tableAlias = tableAlias;
return this;
}
public ConditionFragment setCondition(String[] lhs, String[] rhs) {
this.lhs = lhs;
this.rhs = rhs;
return this;
}
public ConditionFragment setCondition(String[] lhs, String rhs) {
this.lhs = lhs;
this.rhs = ArrayHelper.fillArray(rhs, lhs.length);
return this;
}
public String toFragmentString() {
StringBuilder buf = new StringBuilder( lhs.length * 10 );
for ( int i=0; i<lhs.length; i++ ) {
buf.append(tableAlias)
.append('.')
.append( lhs[i] )
.append(op)
.append( rhs[i] );
if (i<lhs.length-1) {
buf.append(" and ");
}
}
return buf.toString();
}
}

View File

@ -1,51 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.Iterator;
import java.util.Map;
/**
* An Oracle-style DECODE function.
* <br>
* <code>decode(pkvalue, key1, 1, key2, 2, ..., 0)</code>
*
* @author Simon Harris
*/
public class DecodeCaseFragment extends CaseFragment {
public String toFragmentString() {
StringBuilder buf = new StringBuilder( cases.size() * 15 + 10 )
.append("decode(");
Iterator iter = cases.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = (Map.Entry) iter.next();
if ( iter.hasNext() ) {
buf.append(", ")
.append( me.getKey() )
.append(", ")
.append( me.getValue() );
}
else {
buf.insert( 7, me.getKey() )
.append(", ")
.append( me.getValue() );
}
}
buf.append(')');
if (returnColumnName!=null) {
buf.append(" as ")
.append(returnColumnName);
}
return buf.toString();
}
}

View File

@ -1,43 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.Iterator;
import java.util.Map;
/**
* @author Simon Johnston
* @see org.hibernate.dialect.DerbyDialect
*/
public class DerbyCaseFragment extends CaseFragment {
/**
* From http://www.jroller.com/comments/kenlars99/Weblog/cloudscape_soon_to_be_derby
* <p/>
* The problem we had, was when Hibernate does a select with a case statement, for joined subclasses.
* This seems to be because there was no else at the end of the case statement (other dbs seem to not mind).
*/
public String toFragmentString() {
StringBuilder buf = new StringBuilder( cases.size() * 15 + 10 );
buf.append( "case" ); //$NON-NLS-1
Iterator iter = cases.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = ( Map.Entry ) iter.next();
buf.append( " when " )//$NON-NLS-1
.append( me.getKey() )
.append( " is not null then " )//$NON-NLS-1
.append( me.getValue() );
}
// null is not considered the same type as Integer.
buf.append( " else -1" ); //$NON-NLS-1
buf.append( " end" ); //$NON-NLS-1
if ( returnColumnName != null ) {
buf.append( " as " )//$NON-NLS-1
.append( returnColumnName );
}
return buf.toString();
}
}

View File

@ -1,35 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
/**
* A disjunctive string of conditions
* @author Gavin King
*/
public class DisjunctionFragment {
private StringBuilder buffer = new StringBuilder();
public DisjunctionFragment addCondition(ConditionFragment fragment) {
addCondition( fragment.toFragmentString() );
return this;
}
public DisjunctionFragment addCondition(String fragment) {
if ( buffer.length() > 0 ) {
buffer.append(" or ");
}
buffer.append( '(' )
.append( fragment )
.append( ')' );
return this;
}
public String toFragmentString() {
return buffer.toString();
}
}

View File

@ -13,6 +13,7 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.QueryException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.RowLockStrategy;
import org.hibernate.internal.util.StringHelper;
/**
@ -41,7 +42,7 @@ public class ForUpdateFragment {
final LockMode lockMode = me.getValue();
if ( LockMode.READ.lessThan( lockMode ) ) {
final String tableAlias = me.getKey();
if ( dialect.forUpdateOfColumns() ) {
if ( dialect.getWriteRowLockStrategy() == RowLockStrategy.COLUMN ) {
String[] keyColumns = keyColumnNames.get( tableAlias ); //use the id column alias
if ( keyColumns == null ) {
throw new IllegalArgumentException( "alias not found: " + tableAlias );

View File

@ -1,44 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.Iterator;
import java.util.Map;
/**
* The HSQL CASEWHEN function.
* <br>
* <code>casewhen(..., ..., ...) as ...</code>
* <br>
* @author Wolfgang Jung
*/
public class HSQLCaseFragment extends CaseFragment {
public String toFragmentString() {
StringBuilder buf = new StringBuilder( cases.size() * 15 + 10 );
StringBuilder buf2 = new StringBuilder( cases.size() );
Iterator iter = cases.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry me = (Map.Entry) iter.next();
buf.append(" casewhen(")
.append( me.getKey() )
.append(" is not null")
.append(", ")
.append( me.getValue() )
.append(", ");
buf2.append(")");
}
buf.append("-1"); //null caused some problems
buf.append( buf2.toString() );
if ( returnColumnName!=null ) {
buf.append(" as ")
.append(returnColumnName);
}
return buf.toString();
}
}

View File

@ -1,91 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.sql.ast.tree.insert.InsertStatement;
/**
* Implementation of InsertSelect.
*
* @author Steve Ebersole
*
* @deprecated (since 6.0) Use {@link InsertStatement} instead
*/
@Deprecated
public class InsertSelect {
protected String tableName;
protected String comment;
protected List<String> columnNames = new ArrayList<>();
protected Select select;
public InsertSelect(Dialect dialect) {
//This is no longer used. Deprecate & remove?
// this.dialect = dialect;
}
public InsertSelect setTableName(String tableName) {
this.tableName = tableName;
return this;
}
public InsertSelect setComment(String comment) {
this.comment = comment;
return this;
}
public InsertSelect addColumn(String columnName) {
columnNames.add( columnName );
return this;
}
public InsertSelect addColumns(String[] columnNames) {
Collections.addAll( this.columnNames, columnNames );
return this;
}
public InsertSelect setSelect(Select select) {
this.select = select;
return this;
}
public String toStatementString() {
if ( tableName == null ) {
throw new HibernateException( "no table name defined for insert-select" );
}
if ( select == null ) {
throw new HibernateException( "no select defined for insert-select" );
}
StringBuilder buf = new StringBuilder( (columnNames.size() * 15) + tableName.length() + 10 );
if ( comment!=null ) {
buf.append( "/* " ).append( Dialect.escapeComment( comment ) ).append( " */ " );
}
buf.append( "insert into " ).append( tableName );
if ( !columnNames.isEmpty() ) {
buf.append( " (" );
Iterator<String> itr = columnNames.iterator();
while ( itr.hasNext() ) {
buf.append( itr.next() );
if ( itr.hasNext() ) {
buf.append( ", " );
}
}
buf.append( ")" );
}
buf.append( ' ' ).append( select.toStatementString() );
return buf.toString();
}
}

View File

@ -1,209 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.internal.util.StringHelper;
/**
* An abstract SQL join fragment renderer
*
* @author Gavin King
*/
public abstract class JoinFragment {
/**
* Specifies an inner join.
*
* @deprecated use {@link JoinType#INNER_JOIN} instead.
*/
@Deprecated
public static final int INNER_JOIN = JoinType.INNER_JOIN.getJoinTypeValue();
/**
* Specifies a full join
*
* @deprecated use {@link JoinType#FULL_JOIN} instead.
*/
@Deprecated
@SuppressWarnings("UnusedDeclaration")
public static final int FULL_JOIN = JoinType.FULL_JOIN.getJoinTypeValue();
/**
* Specifies a left join.
*
* @deprecated use {@link JoinType#LEFT_OUTER_JOIN} instead.
*/
@Deprecated
public static final int LEFT_OUTER_JOIN = JoinType.LEFT_OUTER_JOIN.getJoinTypeValue();
/**
* Specifies a right join.
*
* @deprecated use {@link JoinType#RIGHT_OUTER_JOIN} instead.
*/
@Deprecated
@SuppressWarnings("UnusedDeclaration")
public static final int RIGHT_OUTER_JOIN = JoinType.RIGHT_OUTER_JOIN.getJoinTypeValue();
private boolean hasFilterCondition;
private boolean hasThetaJoins;
/**
* Adds a join.
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
* @param joinType The type of join
*/
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType);
/**
* Adds a join, with an additional ON clause fragment
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
* @param joinType The type of join
* @param on The additional ON fragment
*/
public abstract void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on);
/**
* Adds a join, with an additional ON clause fragment
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
* @param joinType The type of join
* @param on The additional ON fragment
*/
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType, String on) {
if ( fkColumns.length > 1 ) {
throw new UnsupportedOperationException( "The join fragment does not support multiple foreign key columns: " + getClass() );
}
addJoin( tableName, alias, fkColumns[0], pkColumns, joinType, on );
}
/**
* Adds a cross join to the specified table.
*
* @param tableName The name of the table to be joined
* @param alias The alias to apply to the joined table
*/
public abstract void addCrossJoin(String tableName, String alias);
/**
* Free-form form of adding theta-style joins taking the necessary FROM and WHERE clause fragments
*
* @param fromFragment The FROM clause fragment
* @param whereFragment The WHERE clause fragment
*/
public abstract void addJoins(String fromFragment, String whereFragment);
/**
* Render this fragment to its FROM clause portion
*
* @return The FROM clause portion of this fragment
*/
public abstract String toFromFragmentString();
/**
* Render this fragment to its WHERE clause portion
*
* @return The WHERE clause portion of this fragment
*/
public abstract String toWhereFragmentString();
/**
* Adds a condition to the join fragment.
*
* @param alias The alias of the joined table
* @param fkColumns The names of the columns which reference the joined table
* @param pkColumns The columns in the joined table being referenced
*/
public abstract void addCondition(String alias, String[] fkColumns, String[] pkColumns);
/**
* Adds a free-form condition fragment
*
* @param condition The fragment
*
* @return {@code true} if the condition was added
*/
public abstract boolean addCondition(String condition);
/**
* Make a copy.
*
* @return The copy.
*/
public abstract JoinFragment copy();
/**
* Adds another join fragment to this one.
*
* @param ojf The other join fragment
*/
public void addFragment(JoinFragment ojf) {
if ( ojf.hasThetaJoins() ) {
hasThetaJoins = true;
}
addJoins( ojf.toFromFragmentString(), ojf.toWhereFragmentString() );
}
/**
* Appends the 'on' condition to the buffer, returning true if the condition was added.
* Returns false if the 'on' condition was empty.
*
* @param buffer The buffer to append the 'on' condition to.
* @param on The 'on' condition.
* @return Returns true if the condition was added, false if the condition was already in 'on' string.
*/
protected boolean addCondition(StringBuilder buffer, String on) {
if ( StringHelper.isNotEmpty( on ) ) {
if ( !on.startsWith( " and" ) ) {
buffer.append( " and " );
}
buffer.append( on );
return true;
}
else {
return false;
}
}
/**
* True if the where fragment is from a filter condition.
*
* @return True if the where fragment is from a filter condition.
*/
public boolean hasFilterCondition() {
return hasFilterCondition;
}
public void setHasFilterCondition(boolean b) {
this.hasFilterCondition = b;
}
/**
* Determine if the join fragment contained any theta-joins.
*
* @return {@code true} if the fragment contained theta joins
*/
public boolean hasThetaJoins() {
return hasThetaJoins;
}
public void setHasThetaJoins(boolean hasThetaJoins) {
this.hasThetaJoins = hasThetaJoins;
}
}

View File

@ -1,48 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.HibernateException;
/**
* @author Strong Liu
*/
public enum JoinType {
NONE( -666 ),
INNER_JOIN( 0 ),
LEFT_OUTER_JOIN( 1 ),
RIGHT_OUTER_JOIN( 2 ),
FULL_JOIN( 4 );
private int joinTypeValue;
JoinType(int joinTypeValue) {
this.joinTypeValue = joinTypeValue;
}
public int getJoinTypeValue() {
return joinTypeValue;
}
public static JoinType parse(int joinType) {
if ( joinType < 0 ) {
return NONE;
}
switch ( joinType ) {
case 0:
return INNER_JOIN;
case 1:
return LEFT_OUTER_JOIN;
case 2:
return RIGHT_OUTER_JOIN;
case 4:
return FULL_JOIN;
default:
throw new HibernateException( "unknown join type: " + joinType );
}
}
}

View File

@ -1,181 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.HashSet;
import java.util.Set;
/**
* An Oracle-style (theta) join
*
* @author Jon Lipsky, Gavin King
*/
public class OracleJoinFragment extends JoinFragment {
private StringBuilder afterFrom = new StringBuilder();
private StringBuilder afterWhere = new StringBuilder();
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType) {
addCrossJoin( tableName, alias );
for ( int j = 0; j < fkColumns.length; j++ ) {
setHasThetaJoins( true );
afterWhere.append( " and " )
.append( fkColumns[j] );
if ( joinType == JoinType.RIGHT_OUTER_JOIN || joinType == JoinType.FULL_JOIN ) {
afterWhere.append( "(+)" );
}
afterWhere.append( '=' )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
if ( joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.FULL_JOIN ) {
afterWhere.append( "(+)" );
}
}
}
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType) {
addCrossJoin( tableName, alias );
if ( fkColumns.length > 1 ) {
afterWhere.append( "(" );
}
for ( int i = 0; i < fkColumns.length; i++ ) {
afterWhere.append( " and " );
for ( int j = 0; j < fkColumns[i].length; j++ ) {
setHasThetaJoins( true );
afterWhere.append( fkColumns[i][j] );
if ( joinType == JoinType.RIGHT_OUTER_JOIN || joinType == JoinType.FULL_JOIN ) {
afterWhere.append( "(+)" );
}
afterWhere.append( '=' )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
if ( joinType == JoinType.LEFT_OUTER_JOIN || joinType == JoinType.FULL_JOIN ) {
afterWhere.append( "(+)" );
}
if ( j < fkColumns[i].length - 1 ) {
afterWhere.append( " and " );
}
}
if ( i < fkColumns.length - 1 ) {
afterWhere.append( " or " );
}
}
if ( fkColumns.length > 1 ) {
afterWhere.append( ")" );
}
}
public String toFromFragmentString() {
return afterFrom.toString();
}
public String toWhereFragmentString() {
return afterWhere.toString();
}
public void addJoins(String fromFragment, String whereFragment) {
afterFrom.append( fromFragment );
afterWhere.append( whereFragment );
}
public JoinFragment copy() {
OracleJoinFragment copy = new OracleJoinFragment();
copy.afterFrom = new StringBuilder( afterFrom.toString() );
copy.afterWhere = new StringBuilder( afterWhere.toString() );
return copy;
}
public void addCondition(String alias, String[] columns, String condition) {
for ( String column : columns ) {
afterWhere.append( " and " )
.append( alias )
.append( '.' )
.append( column )
.append( condition );
}
}
public void addCrossJoin(String tableName, String alias) {
afterFrom.append( ", " )
.append( tableName )
.append( ' ' )
.append( alias );
}
public void addCondition(String alias, String[] fkColumns, String[] pkColumns) {
throw new UnsupportedOperationException();
}
public boolean addCondition(String condition) {
return addCondition( afterWhere, condition );
}
public void addFromFragmentString(String fromFragmentString) {
afterFrom.append( fromFragmentString );
}
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on) {
//arbitrary on clause ignored!!
addJoin( tableName, alias, fkColumns, pkColumns, joinType );
if ( joinType == JoinType.INNER_JOIN ) {
addCondition( on );
}
else if ( joinType == JoinType.LEFT_OUTER_JOIN ) {
addLeftOuterJoinCondition( on );
}
else {
throw new UnsupportedOperationException( "join type not supported by OracleJoinFragment (use Oracle9iDialect/Oracle10gDialect)" );
}
}
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType, String on) {
//arbitrary on clause ignored!!
addJoin( tableName, alias, fkColumns, pkColumns, joinType );
if ( joinType == JoinType.INNER_JOIN ) {
addCondition( on );
}
else if ( joinType == JoinType.LEFT_OUTER_JOIN ) {
addLeftOuterJoinCondition( on );
}
else {
throw new UnsupportedOperationException( "join type not supported by OracleJoinFragment (use Oracle9iDialect/Oracle10gDialect)" );
}
}
/**
* This method is a bit of a hack, and assumes
* that the column on the "right" side of the
* join appears on the "left" side of the
* operator, which is extremely weird if this
* was a normal join condition, but is natural
* for a filter.
*/
private void addLeftOuterJoinCondition(String on) {
StringBuilder buf = new StringBuilder( on );
for ( int i = 0; i < buf.length(); i++ ) {
char character = buf.charAt( i );
final boolean isInsertPoint = OPERATORS.contains( Character.valueOf( character ) )
|| ( character == ' ' && buf.length() > i + 3 && "is ".equals( buf.substring( i + 1, i + 4 ) ) );
if ( isInsertPoint ) {
buf.insert( i, "(+)" );
i += 3;
}
}
addCondition( buf.toString() );
}
private static final Set OPERATORS = new HashSet();
static {
OPERATORS.add( Character.valueOf( '=' ) );
OPERATORS.add( Character.valueOf( '<' ) );
OPERATORS.add( Character.valueOf( '>' ) );
}
}

View File

@ -1,175 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.StringHelper;
/**
* A join that appears in a translated HQL query
*
* @author Gavin King
*/
public class QueryJoinFragment extends JoinFragment {
private StringBuilder afterFrom = new StringBuilder();
private StringBuilder afterWhere = new StringBuilder();
private Dialect dialect;
private boolean useThetaStyleInnerJoins;
public QueryJoinFragment(Dialect dialect, boolean useThetaStyleInnerJoins) {
this.dialect = dialect;
this.useThetaStyleInnerJoins = useThetaStyleInnerJoins;
}
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType) {
addJoin( tableName, alias, alias, fkColumns, pkColumns, joinType, null );
}
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on) {
addJoin( tableName, alias, alias, fkColumns, pkColumns, joinType, on );
}
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType) {
addJoin( tableName, alias, alias, fkColumns, pkColumns, joinType, null );
}
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType, String on) {
addJoin( tableName, alias, alias, fkColumns, pkColumns, joinType, on );
}
private void addJoin(String tableName, String alias, String concreteAlias, String[] fkColumns, String[] pkColumns, JoinType joinType, String on) {
if ( !useThetaStyleInnerJoins || joinType != JoinType.INNER_JOIN ) {
JoinFragment jf = dialect.createOuterJoinFragment();
jf.addJoin( tableName, alias, fkColumns, pkColumns, joinType, on );
addFragment( jf );
}
else {
addCrossJoin( tableName, alias );
addCondition( concreteAlias, fkColumns, pkColumns );
addCondition( on );
}
}
private void addJoin(String tableName, String alias, String concreteAlias, String[][] fkColumns, String[] pkColumns, JoinType joinType, String on) {
if ( !useThetaStyleInnerJoins || joinType != JoinType.INNER_JOIN ) {
JoinFragment jf = dialect.createOuterJoinFragment();
jf.addJoin( tableName, alias, fkColumns, pkColumns, joinType, on );
addFragment( jf );
}
else {
addCrossJoin( tableName, alias );
addCondition( concreteAlias, fkColumns, pkColumns );
addCondition( on );
}
}
public String toFromFragmentString() {
return afterFrom.toString();
}
public String toWhereFragmentString() {
return afterWhere.toString();
}
public void addJoins(String fromFragment, String whereFragment) {
afterFrom.append( fromFragment );
afterWhere.append( whereFragment );
}
public JoinFragment copy() {
QueryJoinFragment copy = new QueryJoinFragment( dialect, useThetaStyleInnerJoins );
copy.afterFrom = new StringBuilder( afterFrom.toString() );
copy.afterWhere = new StringBuilder( afterWhere.toString() );
return copy;
}
public void addCondition(String alias, String[] columns, String condition) {
for ( String column : columns ) {
afterWhere.append( " and " )
.append( alias )
.append( '.' )
.append( column )
.append( condition );
}
}
public void addCrossJoin(String tableName, String alias) {
afterFrom.append( ", " )
.append( tableName )
.append( ' ' )
.append( alias );
}
public void addCondition(String alias, String[] fkColumns, String[] pkColumns) {
for ( int j = 0; j < fkColumns.length; j++ ) {
afterWhere.append( " and " )
.append( fkColumns[j] )
.append( '=' )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
}
}
public void addCondition(String alias, String[][] fkColumns, String[] pkColumns) {
afterWhere.append( " and " );
if ( fkColumns.length > 1 ) {
afterWhere.append( "(" );
}
for ( int i = 0; i < fkColumns.length; i++ ) {
for ( int j = 0; j < fkColumns[i].length; j++ ) {
afterWhere.append( fkColumns[i][j] )
.append( '=' )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
if ( j < fkColumns[i].length - 1 ) {
afterWhere.append( " and " );
}
}
if ( i < fkColumns.length - 1 ) {
afterWhere.append( " or " );
}
}
if ( fkColumns.length > 1 ) {
afterWhere.append( ")" );
}
}
/**
* Add the condition string to the join fragment.
*
* @param condition
* @return true if the condition was added, false if it was already in the fragment.
*/
public boolean addCondition(String condition) {
// if the condition is not already there...
if (
!StringHelper.isEmpty( condition ) &&
afterFrom.toString().indexOf( condition.trim() ) < 0 &&
afterWhere.toString().indexOf( condition.trim() ) < 0
) {
if ( !condition.startsWith( " and " ) ) {
afterWhere.append( " and " );
}
afterWhere.append( condition );
return true;
}
else {
return false;
}
}
public void addFromFragmentString(String fromFragmentString) {
afterFrom.append( fromFragmentString );
}
public void clearWherePart() {
afterWhere.setLength( 0 );
}
}

View File

@ -1,215 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.HashSet;
import java.util.Iterator;
import org.hibernate.dialect.Dialect;
/**
* A translated HQL query
*
* @author Gavin King
*/
public class QuerySelect {
private Dialect dialect;
private JoinFragment joins;
private StringBuilder select = new StringBuilder();
private StringBuilder where = new StringBuilder();
private StringBuilder groupBy = new StringBuilder();
private StringBuilder orderBy = new StringBuilder();
private StringBuilder having = new StringBuilder();
private String comment;
private boolean distinct;
private static final HashSet<String> DONT_SPACE_TOKENS = new HashSet<>();
static {
//dontSpace.add("'");
DONT_SPACE_TOKENS.add( "." );
DONT_SPACE_TOKENS.add( "+" );
DONT_SPACE_TOKENS.add( "-" );
DONT_SPACE_TOKENS.add( "/" );
DONT_SPACE_TOKENS.add( "*" );
DONT_SPACE_TOKENS.add( "<" );
DONT_SPACE_TOKENS.add( ">" );
DONT_SPACE_TOKENS.add( "=" );
DONT_SPACE_TOKENS.add( "#" );
DONT_SPACE_TOKENS.add( "~" );
DONT_SPACE_TOKENS.add( "|" );
DONT_SPACE_TOKENS.add( "&" );
DONT_SPACE_TOKENS.add( "<=" );
DONT_SPACE_TOKENS.add( ">=" );
DONT_SPACE_TOKENS.add( "=>" );
DONT_SPACE_TOKENS.add( "=<" );
DONT_SPACE_TOKENS.add( "!=" );
DONT_SPACE_TOKENS.add( "<>" );
DONT_SPACE_TOKENS.add( "!#" );
DONT_SPACE_TOKENS.add( "!~" );
DONT_SPACE_TOKENS.add( "!<" );
DONT_SPACE_TOKENS.add( "!>" );
DONT_SPACE_TOKENS.add( "(" ); //for MySQL
DONT_SPACE_TOKENS.add( ")" );
}
public QuerySelect(Dialect dialect) {
this.dialect = dialect;
joins = new QueryJoinFragment( dialect, false );
}
public JoinFragment getJoinFragment() {
return joins;
}
public void addSelectFragmentString(String fragment) {
if ( fragment.length() > 0 && fragment.charAt( 0 ) == ',' ) {
fragment = fragment.substring( 1 );
}
fragment = fragment.trim();
if ( fragment.length() > 0 ) {
if ( select.length() > 0 ) {
select.append( ", " );
}
select.append( fragment );
}
}
public void addSelectColumn(String columnName, String alias) {
addSelectFragmentString( columnName + ' ' + alias );
}
public void setDistinct(boolean distinct) {
this.distinct = distinct;
}
public void setWhereTokens(Iterator tokens) {
//if ( conjunctiveWhere.length()>0 ) conjunctiveWhere.append(" and ");
appendTokens( where, tokens );
}
public void prependWhereConditions(String conditions) {
if ( where.length() > 0 ) {
where.insert( 0, conditions + " and " );
}
else {
where.append( conditions );
}
}
public void setGroupByTokens(Iterator tokens) {
//if ( groupBy.length()>0 ) groupBy.append(" and ");
appendTokens( groupBy, tokens );
}
public void setOrderByTokens(Iterator tokens) {
//if ( orderBy.length()>0 ) orderBy.append(" and ");
appendTokens( orderBy, tokens );
}
public void setHavingTokens(Iterator tokens) {
//if ( having.length()>0 ) having.append(" and ");
appendTokens( having, tokens );
}
public void addOrderBy(String orderByString) {
if ( orderBy.length() > 0 ) {
orderBy.append( ", " );
}
orderBy.append( orderByString );
}
public String toQueryString() {
StringBuilder buf = new StringBuilder( 50 );
if ( comment != null ) {
buf.append( "/* " ).append( Dialect.escapeComment( comment ) ).append( " */ " );
}
buf.append( "select " );
if ( distinct ) {
buf.append( "distinct " );
}
String from = joins.toFromFragmentString();
if ( from.startsWith( "," ) ) {
from = from.substring( 1 );
}
else if ( from.startsWith( " inner join" ) ) {
from = from.substring( 11 );
}
buf.append( select.toString() )
.append( " from" )
.append( from );
String outerJoinsAfterWhere = joins.toWhereFragmentString().trim();
String whereConditions = where.toString().trim();
boolean hasOuterJoinsAfterWhere = outerJoinsAfterWhere.length() > 0;
boolean hasWhereConditions = whereConditions.length() > 0;
if ( hasOuterJoinsAfterWhere || hasWhereConditions ) {
buf.append( " where " );
if ( hasOuterJoinsAfterWhere ) {
buf.append( outerJoinsAfterWhere.substring( 4 ) );
}
if ( hasWhereConditions ) {
if ( hasOuterJoinsAfterWhere ) {
buf.append( " and (" );
}
buf.append( whereConditions );
if ( hasOuterJoinsAfterWhere ) {
buf.append( ")" );
}
}
}
if ( groupBy.length() > 0 ) {
buf.append( " group by " ).append( groupBy.toString() );
}
if ( having.length() > 0 ) {
buf.append( " having " ).append( having.toString() );
}
if ( orderBy.length() > 0 ) {
buf.append( " order by " ).append( orderBy.toString() );
}
return dialect.transformSelectString( buf.toString() );
}
private static void appendTokens(StringBuilder buf, Iterator iter) {
boolean lastSpaceable = true;
boolean lastQuoted = false;
while ( iter.hasNext() ) {
String token = (String) iter.next();
boolean spaceable = !DONT_SPACE_TOKENS.contains( token );
boolean quoted = token.startsWith( "'" );
if ( spaceable && lastSpaceable ) {
if ( !quoted || !lastQuoted ) {
buf.append( ' ' );
}
}
lastSpaceable = spaceable;
buf.append( token );
lastQuoted = token.endsWith( "'" );
}
}
public void setComment(String comment) {
this.comment = comment;
}
public QuerySelect copy() {
QuerySelect copy = new QuerySelect( dialect );
copy.joins = this.joins.copy();
copy.select.append( this.select.toString() );
copy.where.append( this.where.toString() );
copy.groupBy.append( this.groupBy.toString() );
copy.orderBy.append( this.orderBy.toString() );
copy.having.append( this.having.toString() );
copy.comment = this.comment;
copy.distinct = this.distinct;
return copy;
}
}

View File

@ -1,198 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.dialect.Dialect;
import org.hibernate.internal.util.StringHelper;
/**
* A simple SQL <tt>SELECT</tt> statement
* @author Gavin King
*/
public class Select {
protected String selectClause;
protected String fromClause;
protected String outerJoinsAfterFrom;
protected String whereClause;
protected String outerJoinsAfterWhere;
protected String orderByClause;
protected String groupByClause;
protected String comment;
protected LockOptions lockOptions = new LockOptions();
public final Dialect dialect;
private int guesstimatedBufferSize = 20;
public Select(Dialect dialect) {
this.dialect = dialect;
}
/**
* Construct an SQL <tt>SELECT</tt> statement from the given clauses
*/
public String toStatementString() {
StringBuilder buf = new StringBuilder(guesstimatedBufferSize);
if ( StringHelper.isNotEmpty(comment) ) {
buf.append( "/* " ).append( Dialect.escapeComment( comment ) ).append( " */ " );
}
buf.append("select ").append(selectClause)
.append(" from ").append(fromClause);
if ( StringHelper.isNotEmpty(outerJoinsAfterFrom) ) {
buf.append(outerJoinsAfterFrom);
}
if ( StringHelper.isNotEmpty(whereClause) || StringHelper.isNotEmpty(outerJoinsAfterWhere) ) {
buf.append(" where " );
// the outerJoinsAfterWhere needs to come before where clause to properly
// handle dynamic filters
if ( StringHelper.isNotEmpty(outerJoinsAfterWhere) ) {
buf.append(outerJoinsAfterWhere);
if ( StringHelper.isNotEmpty(whereClause) ) {
buf.append( " and " );
}
}
if ( StringHelper.isNotEmpty( whereClause ) ) {
buf.append(whereClause);
}
}
if ( StringHelper.isNotEmpty(groupByClause) ) {
buf.append(" group by ").append(groupByClause);
}
if ( StringHelper.isNotEmpty(orderByClause) ) {
buf.append(" order by ").append(orderByClause);
}
if (lockOptions.getLockMode() != LockMode.NONE) {
buf.append(dialect.getForUpdateString(lockOptions));
}
return dialect.transformSelectString( buf.toString() );
}
/**
* Sets the fromClause.
* @param fromClause The fromClause to set
*/
public Select setFromClause(String fromClause) {
this.fromClause = fromClause;
this.guesstimatedBufferSize += fromClause.length();
return this;
}
public Select setFromClause(String tableName, String alias) {
this.fromClause = tableName + ' ' + alias;
this.guesstimatedBufferSize += fromClause.length();
return this;
}
public Select setOrderByClause(String orderByClause) {
this.orderByClause = orderByClause;
this.guesstimatedBufferSize += orderByClause.length();
return this;
}
public Select setGroupByClause(String groupByClause) {
this.groupByClause = groupByClause;
this.guesstimatedBufferSize += groupByClause.length();
return this;
}
public Select setOuterJoins(String outerJoinsAfterFrom, String outerJoinsAfterWhere) {
this.outerJoinsAfterFrom = outerJoinsAfterFrom;
// strip off any leading 'and' token
String tmpOuterJoinsAfterWhere = outerJoinsAfterWhere.trim();
if ( tmpOuterJoinsAfterWhere.startsWith("and") ) {
tmpOuterJoinsAfterWhere = tmpOuterJoinsAfterWhere.substring(4);
}
this.outerJoinsAfterWhere = tmpOuterJoinsAfterWhere;
this.guesstimatedBufferSize += outerJoinsAfterFrom.length() + outerJoinsAfterWhere.length();
return this;
}
/**
* Sets the selectClause.
* @param selectClause The selectClause to set
*/
public Select setSelectClause(String selectClause) {
this.selectClause = selectClause;
this.guesstimatedBufferSize += selectClause.length();
return this;
}
public Select setSelectClause(SelectFragment selectFragment) {
setSelectClause( selectFragment.toFragmentString().substring( 2 ) );
return this;
}
/**
* Sets the whereClause.
* @param whereClause The whereClause to set
*/
public Select setWhereClause(String whereClause) {
this.whereClause = whereClause;
this.guesstimatedBufferSize += whereClause.length();
return this;
}
public Select setComment(String comment) {
this.comment = comment;
this.guesstimatedBufferSize += comment.length();
return this;
}
/**
* Get the current lock mode
* @return LockMode
* @deprecated Instead use getLockOptions
*/
@Deprecated
public LockMode getLockMode() {
return lockOptions.getLockMode();
}
/**
* Set the lock mode
* @param lockMode
* @return this object
* @deprecated Instead use setLockOptions
*/
@Deprecated
public Select setLockMode(LockMode lockMode) {
lockOptions.setLockMode(lockMode);
return this;
}
/**
* Get the current lock options
* @return LockOptions
*/
public LockOptions getLockOptions() {
return lockOptions;
}
/**
* Set the lock options
* @param lockOptions
* @return this object
*/
public Select setLockOptions(LockOptions lockOptions) {
LockOptions.copy(lockOptions, this.lockOptions);
return this;
}
}

View File

@ -1,161 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import org.hibernate.internal.util.StringHelper;
/**
* A fragment of an SQL <tt>SELECT</tt> clause
*
* @author Gavin King
*/
public class SelectFragment {
private String suffix;
private List<String> columns = new ArrayList<>();
//private List aliases = new ArrayList();
private List<String> columnAliases = new ArrayList<>();
private String extraSelectList;
private String[] usedAliases;
public SelectFragment() {}
public List<String> getColumns() {
return columns;
}
public String getExtraSelectList() {
return extraSelectList;
}
public SelectFragment setUsedAliases(String[] aliases) {
usedAliases = aliases;
return this;
}
public SelectFragment setExtraSelectList(String extraSelectList) {
this.extraSelectList = extraSelectList;
return this;
}
public SelectFragment setExtraSelectList(CaseFragment caseFragment, String fragmentAlias) {
setExtraSelectList( caseFragment.setReturnColumnName(fragmentAlias, suffix).toFragmentString() );
return this;
}
public SelectFragment setSuffix(String suffix) {
this.suffix = suffix;
return this;
}
public SelectFragment addColumn(String columnName) {
addColumn(null, columnName);
return this;
}
public SelectFragment addColumns(String[] columnNames) {
for ( String columnName : columnNames ) {
addColumn( columnName );
}
return this;
}
public SelectFragment addColumn(String tableAlias, String columnName) {
return addColumn(tableAlias, columnName, columnName);
}
public SelectFragment addColumn(String tableAlias, String columnName, String columnAlias) {
columns.add( StringHelper.qualify(tableAlias, columnName) );
//columns.add(columnName);
//aliases.add(tableAlias);
columnAliases.add(columnAlias);
return this;
}
public SelectFragment addColumns(String tableAlias, String[] columnNames) {
for ( String columnName : columnNames ) {
addColumn( tableAlias, columnName );
}
return this;
}
public SelectFragment addColumns(String tableAlias, String[] columnNames, String[] columnAliases) {
for (int i=0; i<columnNames.length; i++) {
if ( columnNames[i]!=null ) {
addColumn( tableAlias, columnNames[i], columnAliases[i] );
}
}
return this;
}
public SelectFragment addFormulas(String tableAlias, String[] formulas, String[] formulaAliases) {
for ( int i=0; i<formulas.length; i++ ) {
if ( formulas[i]!=null ) {
addFormula( tableAlias, formulas[i], formulaAliases[i] );
}
}
return this;
}
public SelectFragment addFormula(String tableAlias, String formula, String formulaAlias) {
columns.add( StringHelper.replace( formula, Template.TEMPLATE, tableAlias ) );
columnAliases.add(formulaAlias);
return this;
}
public SelectFragment addColumnTemplate(String tableAlias, String columnTemplate, String columnAlias) {
// In this context, there's no difference between a column template and a formula.
return addFormula( tableAlias, columnTemplate, columnAlias );
}
public SelectFragment addColumnTemplates(String tableAlias, String[] columnTemplates, String[] columnAliases) {
// In this context, there's no difference between a column template and a formula.
return addFormulas( tableAlias, columnTemplates, columnAliases );
}
public String toFragmentString() {
StringBuilder buf = new StringBuilder( columns.size() * 10 );
Iterator<String> iter = columns.iterator();
Iterator<String> columnAliasIter = columnAliases.iterator();
//HashMap columnsUnique = new HashMap();
HashSet<String> columnsUnique = new HashSet<>();
if (usedAliases!=null) {
columnsUnique.addAll( Arrays.asList(usedAliases) );
}
while ( iter.hasNext() ) {
String column = iter.next();
String columnAlias = columnAliasIter.next();
//TODO: eventually put this back in, once we think all is fixed
//Object otherAlias = columnsUnique.put(qualifiedColumn, columnAlias);
/*if ( otherAlias!=null && !columnAlias.equals(otherAlias) ) {
throw new AssertionFailure("bug in Hibernate SQL alias generation");
}*/
if ( columnsUnique.add(columnAlias) ) {
buf.append(", ")
.append(column)
.append(" as ");
if (suffix==null) {
buf.append(columnAlias);
}
else {
buf.append( new Alias(suffix).toAliasString(columnAlias) );
}
}
}
if (extraSelectList!=null) {
buf.append(", ")
.append(extraSelectList);
}
return buf.toString();
}
}

View File

@ -1,166 +0,0 @@
/*
* 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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.sql;
/**
* An old Sybase-style join (before Sybase supported the ANSI style "inner join" etc syntax)
* This is needed for Sybase 11.9.2 and earlier, using the HQL 2.* syntax with Collections.
*
* @author Colm O' Flaherty
*/
public class Sybase11JoinFragment extends JoinFragment {
private StringBuilder afterFrom = new StringBuilder();
private StringBuilder afterWhere = new StringBuilder();
public void addJoin(String tableName, String alias, String[] fkColumns, String[] pkColumns, JoinType joinType) {
addCrossJoin( tableName, alias );
for ( int j = 0; j < fkColumns.length; j++ ) {
//full joins are not supported.. yet!
if ( joinType == JoinType.FULL_JOIN ) {
throw new UnsupportedOperationException();
}
afterWhere.append( " and " )
.append( fkColumns[j] )
.append( " " );
if ( joinType == JoinType.LEFT_OUTER_JOIN ) {
afterWhere.append( '*' );
}
afterWhere.append( '=' );
if ( joinType == JoinType.RIGHT_OUTER_JOIN ) {
afterWhere.append( "*" );
}
afterWhere.append( " " )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
}
}
public void addJoin(String tableName, String alias, String[][] fkColumns, String[] pkColumns, JoinType joinType) {
addCrossJoin( tableName, alias );
if ( fkColumns.length > 1 ) {
afterWhere.append( "(" );
}
for ( int i = 0; i < fkColumns.length; i++ ) {
afterWhere.append( " and " );
for ( int j = 0; j < fkColumns[i].length; j++ ) {
//full joins are not supported.. yet!
if ( joinType == JoinType.FULL_JOIN ) {
throw new UnsupportedOperationException();
}
afterWhere.append( fkColumns[i][j] )
.append( " " );
if ( joinType == JoinType.LEFT_OUTER_JOIN ) {
afterWhere.append( '*' );
}
afterWhere.append( '=' );
if ( joinType == JoinType.RIGHT_OUTER_JOIN ) {
afterWhere.append( "*" );
}
afterWhere.append( " " )
.append( alias )
.append( '.' )
.append( pkColumns[j] );
if ( j < fkColumns[i].length - 1 ) {
afterWhere.append( " and " );
}
}
if ( i < fkColumns.length - 1 ) {
afterWhere.append( " or " );
}
}
if ( fkColumns.length > 1 ) {
afterWhere.append( ")" );
}
}
public String toFromFragmentString() {
return afterFrom.toString();
}
public String toWhereFragmentString() {
return afterWhere.toString();
}
public void addJoins(String fromFragment, String whereFragment) {
afterFrom.append( fromFragment );
afterWhere.append( whereFragment );
}
public JoinFragment copy() {
Sybase11JoinFragment copy = new Sybase11JoinFragment();
copy.afterFrom = new StringBuilder( afterFrom.toString() );
copy.afterWhere = new StringBuilder( afterWhere.toString() );
return copy;
}
public void addCondition(String alias, String[] columns, String condition) {
for ( String column : columns ) {
afterWhere.append( " and " )
.append( alias )
.append( '.' )
.append( column )
.append( condition );
}
}
public void addCrossJoin(String tableName, String alias) {
afterFrom.append( ", " )
.append( tableName )
.append( ' ' )
.append( alias );
}
public void addCondition(String alias, String[] fkColumns, String[] pkColumns) {
throw new UnsupportedOperationException();
}
public boolean addCondition(String condition) {
return addCondition( afterWhere, condition );
}
public void addFromFragmentString(String fromFragmentString) {
afterFrom.append( fromFragmentString );
}
public void addJoin(
String tableName,
String alias,
String[] fkColumns,
String[] pkColumns,
JoinType joinType,
String on) {
addJoin( tableName, alias, fkColumns, pkColumns, joinType );
addCondition( on );
}
public void addJoin(
String tableName,
String alias,
String[][] fkColumns,
String[] pkColumns,
JoinType joinType,
String on) {
addJoin( tableName, alias, fkColumns, pkColumns, joinType );
addCondition( on );
}
}

View File

@ -0,0 +1,41 @@
/*
* 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 http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.JdbcMappingContainer;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
/**
* A wrapper for an expression that also renders an alias.
*
* @author Christian Beikov
*/
public class AliasedExpression implements SelfRenderingExpression {
private final Expression expression;
private final String alias;
public AliasedExpression(Expression expression, String alias) {
this.expression = expression;
this.alias = alias;
}
@Override
public void renderToSql(SqlAppender sqlAppender, SqlAstTranslator<?> walker, SessionFactoryImplementor sessionFactory) {
expression.accept( walker );
sqlAppender.appendSql( ' ' );
sqlAppender.appendSql( alias );
}
@Override
public JdbcMappingContainer getExpressionType() {
return expression.getExpressionType();
}
}

View File

@ -16,7 +16,7 @@ import org.hibernate.sql.ast.spi.SqlAppender;
*
* @see org.hibernate.sql.ast.spi.AbstractSqlAstTranslator
*
* @author Christian beikov
* @author Christian Beikov
*/
public class LiteralAsParameter<T> implements SelfRenderingExpression {

View File

@ -294,7 +294,7 @@ public class OrderByTest extends BaseCoreFunctionalTestCase {
try {
final QueryableCollection queryableCollection = (QueryableCollection) transactionsPersister;
SimpleSelect select = new SimpleSelect( getDialect() )
SimpleSelect select = new SimpleSelect( sessionFactory().getJdbcServices().getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "code" )
.addColumn( "transactions_index" );

View File

@ -446,59 +446,4 @@ public class OneToOneTest extends BaseNonConfigCoreFunctionalTestCase {
return new String[] { "org/hibernate/orm/test/annotations/onetoone/orm.xml" };
}
/**
* Verifies that generated 'select' statement has desired number of joins
* @author Sharath Reddy
*
*/
class JoinCounter extends EmptyInterceptor {
private static final long serialVersionUID = -3689681272273261051L;
private int expectedNumberOfJoins = 0;
private String nextValRegex;
public JoinCounter(int val) {
super();
this.expectedNumberOfJoins = val;
try {
nextValRegex = ".*" + getDialect().getSelectSequenceNextValString(".*") + ".*";
nextValRegex = nextValRegex.replace( "(", "\\(" );
nextValRegex = nextValRegex.replace( ")", "\\)" );
} catch (MappingException ex) {
nextValRegex = "nextval";
}
}
public String onPrepareStatement(String sql) {
int numberOfJoins = 0;
if (sql.startsWith("select") & !sql.matches(nextValRegex)) {
numberOfJoins = count(sql, "join");
assertEquals( sql, expectedNumberOfJoins, numberOfJoins );
}
return sql;
}
/**
* Count the number of instances of substring within a string.
*
* @param string String to look for substring in.
* @param substring Sub-string to look for.
* @return Count of substrings in string.
*/
private int count(final String string, final String substring)
{
int count = 0;
int idx = 0;
while ((idx = string.indexOf(substring, idx)) != -1)
{
idx++;
count++;
}
return count;
}
}
}

View File

@ -71,7 +71,7 @@ public class PersistentListTest {
session2.doWork(
connection -> {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( sessionFactory.getDialect() )
SimpleSelect select = new SimpleSelect( sessionFactory.getJdbcServices().getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "NAME" )
.addColumn( "LIST_INDEX" )
@ -131,7 +131,7 @@ public class PersistentListTest {
session2.doWork(
connection -> {
final QueryableCollection queryableCollection = (QueryableCollection) collectionPersister;
SimpleSelect select = new SimpleSelect( sessionFactory.getDialect() )
SimpleSelect select = new SimpleSelect( sessionFactory.getJdbcServices().getDialect() )
.setTableName( queryableCollection.getTableName() )
.addColumn( "order_id" )
.addColumn( "INDX" )

View File

@ -16,6 +16,9 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.sequence.ANSISequenceSupport;
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.id.OptimizableGenerator;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.enhanced.DatabaseStructure;
@ -310,10 +313,6 @@ public class SequenceStyleConfigUnitTest {
public int getVersion() {
return 0;
}
@Override
public boolean supportsSequences() {
return false;
}
}
public static class SequenceDialect extends Dialect {
@ -323,22 +322,20 @@ public class SequenceStyleConfigUnitTest {
}
@Override
public boolean supportsSequences() {
return true;
}
public SequenceSupport getSequenceSupport() {
return new ANSISequenceSupport() {
@Override
public boolean supportsPooledSequences() {
return false;
}
@Override
public String getSequenceNextValString(String sequenceName) throws MappingException {
return "";
};
}
}
public static class PooledSequenceDialect extends SequenceDialect {
public boolean supportsPooledSequences() {
return true;
@Override
public SequenceSupport getSequenceSupport() {
return ANSISequenceSupport.INSTANCE;
}
}

View File

@ -14,7 +14,6 @@ import jakarta.persistence.criteria.Path;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.hibernate.dialect.CockroachDialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.jpa.test.metamodel.AbstractMetamodelSpecificTest;
import org.hibernate.jpa.test.metamodel.CreditCard;
@ -22,8 +21,6 @@ import org.hibernate.jpa.test.metamodel.CreditCard_;
import org.hibernate.jpa.test.metamodel.Customer_;
import org.hibernate.jpa.test.metamodel.Order;
import org.hibernate.jpa.test.metamodel.Order_;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.Before;
@ -298,8 +295,6 @@ public class PredicateTest extends AbstractMetamodelSpecificTest {
@Test
@TestForIssue( jiraKey = "HHH-8901" )
@RequiresDialectFeature( DialectChecks.NotSupportsEmptyInListCheck.class )
@SkipForDialect(value = DerbyDialect.class, comment = "Derby doesn't like `x in (null)`")
public void testEmptyInPredicate() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();

View File

@ -31,6 +31,7 @@ import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.annotations.Nationalized;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.dialect.AbstractHANADialect;
import org.hibernate.dialect.AbstractTransactSQLDialect;
import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
@ -128,6 +129,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
@SkipForDialect(value = DerbyDialect.class, comment = "No support for the tinyint datatype so we use smallint")
@SkipForDialect(value = DB2Dialect.class, comment = "No support for the tinyint datatype so we use smallint")
@SkipForDialect(value = AbstractTransactSQLDialect.class, comment = "No support for the tinyint datatype so we use smallint")
@SkipForDialect(value = AbstractHANADialect.class, comment = "No support for the tinyint datatype so we use smallint")
public void tinyintType() {
createEntityManagerFactory( TinyintEntity.class );
doTest( TinyintEntity.class, (byte)127 );
@ -154,6 +156,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
@SkipForDialect(value = DB2Dialect.class, comment = "Value is too big for the maximum allowed precision of DB2")
@SkipForDialect(value = OracleDialect.class, comment = "Value is too big for the maximum allowed precision of Oracle")
@SkipForDialect(value = AbstractTransactSQLDialect.class, comment = "Value is too big for the maximum allowed precision of SQL Server and Sybase")
@SkipForDialect(value = AbstractHANADialect.class, comment = "Value is too big for the maximum allowed precision of HANA")
public void numericType() {
createEntityManagerFactory(
NumericEntity.class
@ -166,6 +169,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
@SkipForDialect(value = DB2Dialect.class, comment = "Value is too big for the maximum allowed precision of DB2")
@SkipForDialect(value = OracleDialect.class, comment = "Value is too big for the maximum allowed precision of Oracle")
@SkipForDialect(value = AbstractTransactSQLDialect.class, comment = "Value is too big for the maximum allowed precision of SQL Server and Sybase")
@SkipForDialect(value = AbstractHANADialect.class, comment = "Value is too big for the maximum allowed precision of HANA")
public void decimalType() {
createEntityManagerFactory( DecimalEntity.class );
doTest( DecimalEntity.class, new BigDecimal( "5464384284258458485484848458.48465843584584684" ) );
@ -186,6 +190,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
@SkipForDialect(value = OracleDialect.class, comment = "Oracle maps LONGVARCHAR to CLOB")
@SkipForDialect(value = DB2Dialect.class, comment = "DB2 maps LONGVARCHAR to CLOB")
@SkipForDialect(value = SybaseDialect.class, comment = "Sybase maps LONGVARCHAR to CLOB")
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA maps LONGVARCHAR to CLOB")
public void longCharType() {
createEntityManagerFactory(
LongvarcharEntity.class
@ -223,6 +228,7 @@ public class NativeQueryResultTypeAutoDiscoveryTest {
@SkipForDialect(value = OracleDialect.class, comment = "Oracle maps LONGVARBINARY to BLOB")
@SkipForDialect(value = DB2Dialect.class, comment = "DB2 maps LONGVARBINARY to BLOB")
@SkipForDialect(value = SybaseDialect.class, comment = "Sybase maps LONGVARBINARY to BLOB")
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA maps LONGVARCHAR to BLOB")
public void longBinaryType() {
createEntityManagerFactory(
LongvarbinaryEntity.class

View File

@ -712,8 +712,6 @@ public class ASTParserLoadingTest extends BaseCoreFunctionalTestCase {
@Test
@TestForIssue( jiraKey = "HHH-8901" )
@RequiresDialectFeature(DialectChecks.NotSupportsEmptyInListCheck.class)
@SkipForDialect(value = DerbyDialect.class, comment = "Derby doesn't like `x in (null)`")
public void testEmptyInListForDialectsNotSupportsEmptyInList() {
Session session = openSession();
session.beginTransaction();

View File

@ -7,14 +7,16 @@
package org.hibernate.test.hql;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.annotations.NaturalId;
import org.hibernate.query.Query;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@ -26,11 +28,9 @@ import jakarta.persistence.JoinTable;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@ -38,16 +38,20 @@ import static org.junit.Assert.assertFalse;
* @author Jan-Willem Gmelig Meyling
* @author Christian Beikov
*/
public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Book.class, BookRef.class, BookRefRef.class };
@DomainModel(
annotatedClasses = {
NaturalIdDereferenceTest.Book.class,
NaturalIdDereferenceTest.BookRef.class,
NaturalIdDereferenceTest.BookRefRef.class
}
)
@SessionFactory(statementInspectorClass = SQLStatementInspector.class)
public class NaturalIdDereferenceTest {
@Before
public void setUp() {
doInHibernate( this::sessionFactory, session -> {
@BeforeEach
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Book book = new Book();
book.isbn = "abcd";
session.persist( book );
@ -58,56 +62,76 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
session.flush();
session.clear();
} );
}
);
}
@Test
public void naturalIdDereferenceTest() {
doInHibernate( this::sessionFactory, session -> {
public void naturalIdDereferenceTest(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r.normalBook.isbn FROM BookRef r" );
List resultList = query.getResultList();
assertFalse( resultList.isEmpty() );
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void normalIdDereferenceFromAlias() {
doInHibernate( this::sessionFactory, session -> {
public void normalIdDereferenceFromAlias(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r.normalBook.id FROM BookRef r" );
List resultList = query.getResultList();
assertFalse( resultList.isEmpty() );
assertEquals( 0, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 0, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void naturalIdDereferenceFromAlias() {
doInHibernate( this::sessionFactory, session -> {
public void naturalIdDereferenceFromAlias(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r.naturalBook.isbn FROM BookRef r" );
List resultList = query.getResultList();
assertFalse( resultList.isEmpty() );
assertEquals( 0, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 0, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void normalIdDereferenceFromImplicitJoin() {
doInHibernate( this::sessionFactory, session -> {
public void normalIdDereferenceFromImplicitJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.normalBookRef.normalBook.id FROM BookRefRef r2" );
query.getResultList();
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void naturalIdDereferenceFromImplicitJoin() {
doInHibernate( this::sessionFactory, session -> {
public void naturalIdDereferenceFromImplicitJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.normalBookRef.naturalBook.isbn FROM BookRefRef r2" );
query.getResultList();
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
@ -116,43 +140,59 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
* can be dereferenced without a single join.
*/
@Test
public void nestedNaturalIdDereferenceFromImplicitJoin() {
doInHibernate( this::sessionFactory, session -> {
public void nestedNaturalIdDereferenceFromImplicitJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.naturalBookRef.naturalBook.isbn FROM BookRefRef r2" );
query.getResultList();
assertEquals( 0, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 0, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
* Adjustment of {@link #nestedNaturalIdDereferenceFromImplicitJoin()}, that instead selects the {@code id} property,
* Adjustment of {@link #nestedNaturalIdDereferenceFromImplicitJoin(SessionFactoryScope)}, that instead selects the {@code id} property,
* which requires a single join to {@code Book}.
*/
@Test
public void nestedNaturalIdDereferenceFromImplicitJoin2() {
doInHibernate( this::sessionFactory, session -> {
public void nestedNaturalIdDereferenceFromImplicitJoin2(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.naturalBookRef.naturalBook.id FROM BookRefRef r2" );
query.getResultList();
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void doNotDereferenceNaturalIdIfIsReferenceToPrimaryKey() {
doInHibernate( this::sessionFactory, session -> {
public void doNotDereferenceNaturalIdIfIsReferenceToPrimaryKey(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.normalBookRef.normalBook.isbn FROM BookRefRef r2" );
query.getResultList();
assertEquals( 2, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 2, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
public void selectedEntityIsNotDereferencedForPrimaryKey() {
doInHibernate( this::sessionFactory, session -> {
public void selectedEntityIsNotDereferencedForPrimaryKey(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.normalBookRef.normalBook FROM BookRefRef r2" );
query.getResultList();
assertEquals( 2, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 2, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
@ -167,47 +207,59 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
* so bookRefRef.naturalBookRef.naturalBook yields null which is expected.
*/
@Test
public void selectedEntityIsNotDereferencedForNaturalId() {
doInHibernate( this::sessionFactory, session -> {
public void selectedEntityIsNotDereferencedForNaturalId(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT r2.naturalBookRef.naturalBook FROM BookRefRef r2" );
query.getResultList();
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
* {@code r2.normalBookRef.normalBook.id} requires 1 join as seen in {@link #normalIdDereferenceFromImplicitJoin}.
* {@code r3.naturalBookRef.naturalBook.isbn} requires 1 join as seen in {@link #selectedEntityIsNotDereferencedForNaturalId()}.
* {@code r3.naturalBookRef.naturalBook.isbn} requires 1 join as seen in {@link #selectedEntityIsNotDereferencedForNaturalId(SessionFactoryScope)} .
* An additional join is added to join BookRef once more on {@code r2.normalBookRef.normalBook.isbn = r3.naturalBookRef.naturalBook.isbn}.
* This results in three joins in total.
*/
@Test
public void dereferenceNaturalIdInJoin() {
doInHibernate( this::sessionFactory, session -> {
public void dereferenceNaturalIdInJoin(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery(
"SELECT r2.normalBookRef.normalBook.id, r3.naturalBookRef.naturalBook.isbn " +
"FROM BookRefRef r2 JOIN BookRefRef r3 ON r2.normalBookRef.normalBook.isbn = r3.naturalBookRef.naturalBook.isbn" );
query.getResultList();
sqlStatementInterceptor.assertExecutedCount( 1 );
// r2.normalBookRef.normalBook.id requires
assertEquals( 3, getSQLJoinCount( query ) );
} );
assertEquals( 3, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
* {@code BookRefRef} is joined with {@code BookRef} on {@code b.naturalBook.isbn = a.naturalBookRef.naturalBook.isbn}.
* {@code b.naturalBook.isbn} can be dereferenced without any join ({@link #naturalIdDereferenceFromAlias()}).
* {@code a.naturalBookRef.naturalBook.isbn} can be dereferenced without any join ({@link #nestedNaturalIdDereferenceFromImplicitJoin()}).
* {@code b.naturalBook.isbn} can be dereferenced without any join ({@link #naturalIdDereferenceFromAlias(SessionFactoryScope)} .
* {@code a.naturalBookRef.naturalBook.isbn} can be dereferenced without any join ({@link #nestedNaturalIdDereferenceFromImplicitJoin(SessionFactoryScope)} .
* We finally select all properties of {@code b.normalBook}, which requires {@code Book} to be joined.
* This results in two joins in total.
*/
@Test
public void dereferenceNaturalIdInJoin2() {
doInHibernate( this::sessionFactory, session -> {
public void dereferenceNaturalIdInJoin2(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery( "SELECT b.normalBook FROM BookRefRef a " +
"JOIN BookRef b ON b.naturalBook.isbn = a.naturalBookRef.naturalBook.isbn" );
query.getResultList();
assertEquals( 2, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 2, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
@ -217,13 +269,17 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
* As a result, only a single join is required.
*/
@Test
public void dereferenceNaturalIdInJoin3() {
doInHibernate( this::sessionFactory, session -> {
public void dereferenceNaturalIdInJoin3(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery(
"SELECT r.normalBook.isbn FROM BookRef r JOIN r.normalBook b ON b.isbn = r.normalBook.isbn" );
query.getResultList();
assertEquals( 1, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 1, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
/**
@ -234,89 +290,29 @@ public class NaturalIdDereferenceTest extends BaseCoreFunctionalTestCase {
* As a result, 2 joins are required.
*/
@Test
public void dereferenceNaturalIdInJoin4() {
doInHibernate( this::sessionFactory, session -> {
public void dereferenceNaturalIdInJoin4(SessionFactoryScope scope) {
SQLStatementInspector sqlStatementInterceptor = (SQLStatementInspector) scope.getStatementInspector();
scope.inTransaction(
session -> {
Query query = session.createQuery(
"SELECT r.normalBook.isbn FROM BookRef r JOIN Book b ON b.isbn = r.normalBook.isbn" );
query.getResultList();
assertEquals( 2, getSQLJoinCount( query ) );
} );
sqlStatementInterceptor.assertExecutedCount( 1 );
assertEquals( 2, sqlStatementInterceptor.getNumberOfJoins( 0 ) );
}
);
}
@Test
@TestForIssue(jiraKey = "HHH-13752")
public void deleteWithNaturalIdBasedJoinTable() {
doInHibernate( this::sessionFactory, session -> {
public void deleteWithNaturalIdBasedJoinTable(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
Query query = session.createQuery(
"DELETE FROM Book b WHERE 1=0" );
query.executeUpdate();
} );
}
private int getSQLJoinCount(Query query) {
String sqlQuery = getSQLQuery( query ).toLowerCase();
int lastIndex = 0;
int count = 0;
while ( lastIndex != -1 ) {
lastIndex = sqlQuery.indexOf( " join ", lastIndex );
if ( lastIndex != -1 ) {
count++;
lastIndex += " join ".length();
}
}
// we also have to deal with different cross join operators: in the case of Sybase, it's ", "
String crossJoinOperator = getDialect().getCrossJoinSeparator();
if ( !crossJoinOperator.contains( " join " ) ) {
int fromIndex = sqlQuery.indexOf( " from " );
if ( fromIndex == -1 ) {
return count;
}
int whereIndex = sqlQuery.indexOf( " where " );
lastIndex = fromIndex + " from ".length();
int endIndex = whereIndex > 0 ? whereIndex : sqlQuery.length();
while ( lastIndex != -1 && lastIndex <= endIndex ) {
lastIndex = sqlQuery.indexOf( crossJoinOperator, lastIndex );
if ( lastIndex != -1 ) {
count++;
lastIndex += crossJoinOperator.length();
}
}
}
return count;
}
private String getSQLQuery(Query query) {
// FilterTranslator naturalIdJoinGenerationTest1 = this.sessionFactory()
// .getSettings()
// .getQueryTranslatorFactory()
// .createFilterTranslator(
// "nid",
// query.getQueryString(),
// Collections.emptyMap(),
// this.sessionFactory()
// );
// naturalIdJoinGenerationTest1.compile( Collections.emptyMap(), false );
// return naturalIdJoinGenerationTest1.getSQLString();
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
protected boolean isCleanupTestDataRequired() {
return true;
}
@Override
protected boolean isCleanupTestDataUsingBulkDelete() {
return true;
);
}
@Entity(name = "Book")

View File

@ -18,8 +18,6 @@ import org.hibernate.cfg.Configuration;
import org.hibernate.query.sqm.mutation.internal.inline.InlineStrategy;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.testing.DialectChecks;
import org.hibernate.testing.RequiresDialectFeature;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Before;
@ -32,7 +30,6 @@ import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
/**
* @author Andrea Boriero
*/
@RequiresDialectFeature(DialectChecks.SupportsRowValueConstructorSyntaxInInListCheck.class)
@TestForIssue(jiraKey = "HHH-13214")
public class InheritanceDeleteBatchTest extends BaseCoreFunctionalTestCase {

View File

@ -12,6 +12,7 @@ import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.MySQLDialect;
import org.hibernate.dialect.NationalizationSupport;
import org.hibernate.dialect.PostgreSQLDialect;
/**
@ -51,18 +52,6 @@ abstract public class DialectChecks {
}
}
public static class SupportsEmptyInListCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsEmptyInList();
}
}
public static class NotSupportsEmptyInListCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return !dialect.supportsEmptyInList();
}
}
public static class SupportsResultSetPositioningOnForwardOnlyCursorCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsResultSetPositionQueryMethodsOnForwardOnlyCursor();
@ -95,13 +84,13 @@ abstract public class DialectChecks {
public static class SupportLimitCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsLimit();
return dialect.getLimitHandler().supportsLimit();
}
}
public static class SupportLimitAndOffsetCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsLimit() && dialect.supportsLimitOffset();
return dialect.getLimitHandler().supportsLimit() && dialect.getLimitHandler().supportsLimitOffset();
}
}
@ -126,12 +115,6 @@ abstract public class DialectChecks {
}
}
public static class SupportsRowValueConstructorSyntaxInInListCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsRowValueConstructorSyntaxInInList();
}
}
public static class DoesReadCommittedCauseWritersToBlockReadersCheck implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.doesReadCommittedCauseWritersToBlockReaders();
@ -211,28 +194,6 @@ abstract public class DialectChecks {
}
}
public static class SupportNonQueryValuesListWithCTE implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsValuesList() &&
dialect.supportsNonQueryWithCTE() &&
dialect.supportsRowValueConstructorSyntaxInInList();
}
}
public static class SupportValuesListAndRowValueConstructorSyntaxInInList
implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsValuesList() &&
dialect.supportsRowValueConstructorSyntaxInInList();
}
}
public static class SupportRowValueConstructorSyntaxInInList implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsRowValueConstructorSyntaxInInList();
}
}
public static class SupportSkipLocked implements DialectCheck {
public boolean isMatch(Dialect dialect) {
return dialect.supportsSkipLocked();
@ -278,7 +239,7 @@ abstract public class DialectChecks {
public static class SupportsNClob implements DialectCheck {
@Override
public boolean isMatch(Dialect dialect) {
return dialect.supportsNationalizedTypes();
return dialect.getNationalizationSupport() == NationalizationSupport.EXPLICIT;
// return !(
// dialect instanceof DB2Dialect ||
// dialect instanceof PostgreSQL81Dialect ||

View File

@ -74,12 +74,6 @@ abstract public class DialectFeatureChecks {
}
}
public static class SupportsEmptyInListCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsEmptyInList();
}
}
public static class SupportsNoColumnInsert implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsNoColumnsInsert();
@ -118,13 +112,13 @@ abstract public class DialectFeatureChecks {
public static class SupportLimitCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsLimit();
return dialect.getLimitHandler().supportsLimit();
}
}
public static class SupportLimitAndOffsetCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsLimit() && dialect.supportsLimitOffset();
return dialect.getLimitHandler().supportsLimit() && dialect.getLimitHandler().supportsLimitOffset();
}
}
@ -155,12 +149,6 @@ abstract public class DialectFeatureChecks {
}
}
public static class SupportsRowValueConstructorSyntaxInInListCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.supportsRowValueConstructorSyntaxInInList();
}
}
public static class DoesReadCommittedCauseWritersToBlockReadersCheck implements DialectFeatureCheck {
public boolean apply(Dialect dialect) {
return dialect.doesReadCommittedCauseWritersToBlockReaders();