Get rid of deprecated dialect methods, JoinFragment, LegacyLimitHandler, LegacySequenceSupport, CaseFragment, SelectFragment etc.
This commit is contained in:
parent
f416b728a9
commit
40ccad1db2
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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é 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 );
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -418,13 +418,6 @@ public class SQLiteDialect extends Dialect {
|
|||
};
|
||||
}
|
||||
|
||||
// Overridden informational metadata ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
public boolean supportsEmptyInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// DDL support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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] )
|
||||
|
|
|
@ -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] )
|
||||
|
|
|
@ -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] )
|
||||
|
|
|
@ -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 )
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.hibernate.JDBCException;
|
|||
* configuration steps prior to first use.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
* @see SQLExceptionConverterFactory
|
||||
*/
|
||||
public interface SQLExceptionConverter extends Serializable {
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ public class SequenceGenerator
|
|||
|
||||
@Override
|
||||
public String determineBulkInsertionIdentifierGenerationSelectFragment(Dialect dialect) {
|
||||
return dialect.getSelectSequenceNextValString( getSequenceName() );
|
||||
return dialect.getSequenceSupport().getSelectSequenceNextValString( getSequenceName() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 +
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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).
|
||||
*/
|
||||
|
|
|
@ -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).
|
||||
*/
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
/**
|
||||
|
|
|
@ -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).
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()];
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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( '>' ) );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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" );
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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" )
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 ||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue