From ff57a6ced03846da684014f4d193a24532d3a457 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Mon, 12 Aug 2024 17:21:32 +0200 Subject: [PATCH] HHH-18447 Try using native cast for string to boolean --- .../community/dialect/AltibaseDialect.java | 22 ++- .../dialect/AltibaseSqlAstTranslator.java | 10 -- .../community/dialect/CUBRIDDialect.java | 12 ++ .../dialect/CUBRIDSqlAstTranslator.java | 12 -- .../community/dialect/DB2LegacyDialect.java | 21 +++ .../dialect/DB2LegacySqlAstTranslator.java | 10 -- .../community/dialect/DerbyDialect.java | 15 ++ .../community/dialect/DerbyLegacyDialect.java | 15 ++ .../dialect/DerbyLegacySqlAstTranslator.java | 10 -- .../dialect/DerbySqlAstTranslator.java | 10 -- .../community/dialect/FirebirdDialect.java | 26 ++- .../dialect/FirebirdSqlAstTranslator.java | 10 -- .../community/dialect/H2LegacyDialect.java | 21 +++ .../dialect/H2LegacySqlAstTranslator.java | 5 - .../community/dialect/HSQLLegacyDialect.java | 26 ++- .../dialect/HSQLLegacySqlAstTranslator.java | 5 - .../community/dialect/InformixDialect.java | 10 ++ .../dialect/InformixSqlAstTranslator.java | 10 -- .../community/dialect/IngresDialect.java | 11 ++ .../dialect/IngresSqlAstTranslator.java | 11 -- .../dialect/MariaDBLegacyDialect.java | 10 ++ .../MariaDBLegacySqlAstTranslator.java | 10 -- .../community/dialect/MaxDBDialect.java | 10 ++ .../dialect/MaxDBSqlAstTranslator.java | 10 -- .../community/dialect/MimerSQLDialect.java | 5 + .../dialect/MimerSQLSqlAstTranslator.java | 5 - .../community/dialect/MySQLLegacyDialect.java | 10 ++ .../dialect/MySQLLegacySqlAstTranslator.java | 10 -- .../dialect/OracleLegacyDialect.java | 29 +++- .../dialect/OracleLegacySqlAstTranslator.java | 10 -- .../dialect/PostgreSQLLegacyDialect.java | 11 ++ .../community/dialect/RDMSOS2200Dialect.java | 10 ++ .../dialect/RDMSOS2200SqlAstTranslator.java | 10 -- .../community/dialect/SingleStoreDialect.java | 5 + .../dialect/SingleStoreSqlAstTranslator.java | 5 - .../dialect/SybaseASELegacyDialect.java | 5 + .../SybaseASELegacySqlAstTranslator.java | 5 - .../dialect/SybaseAnywhereDialect.java | 10 ++ .../SybaseAnywhereSqlAstTranslator.java | 10 -- .../org/hibernate/dialect/DB2Dialect.java | 21 +++ .../dialect/DB2SqlAstTranslator.java | 10 -- .../java/org/hibernate/dialect/Dialect.java | 155 +++++++++++++++++- .../java/org/hibernate/dialect/H2Dialect.java | 21 +++ .../hibernate/dialect/H2SqlAstTranslator.java | 5 - .../org/hibernate/dialect/HANADialect.java | 10 ++ .../dialect/HANASqlAstTranslator.java | 10 -- .../org/hibernate/dialect/HSQLDialect.java | 26 ++- .../dialect/HSQLSqlAstTranslator.java | 5 - .../org/hibernate/dialect/MariaDBDialect.java | 5 + .../dialect/MariaDBSqlAstTranslator.java | 5 - .../org/hibernate/dialect/MySQLDialect.java | 5 + .../dialect/MySQLSqlAstTranslator.java | 5 - .../org/hibernate/dialect/OracleDialect.java | 26 ++- .../dialect/OracleSqlAstTranslator.java | 10 -- .../hibernate/dialect/PostgreSQLDialect.java | 11 ++ .../hibernate/dialect/SybaseASEDialect.java | 5 + .../dialect/SybaseASESqlAstTranslator.java | 5 - .../org/hibernate/dialect/TiDBDialect.java | 5 + .../dialect/TiDBSqlAstTranslator.java | 5 - .../sql/ast/spi/AbstractSqlAstTranslator.java | 4 +- .../orm/test/query/hql/FunctionTests.java | 45 +++++ 61 files changed, 595 insertions(+), 256 deletions(-) diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseDialect.java index 2f8737e010..94ae2b48aa 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseDialect.java @@ -393,20 +393,26 @@ public class AltibaseDialect extends Dialect { } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case BOOLEAN: case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -702,4 +708,14 @@ public class AltibaseDialect extends Dialect { }; } + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseSqlAstTranslator.java index 141b79af82..731bf873f3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/AltibaseSqlAstTranslator.java @@ -218,16 +218,6 @@ public class AltibaseSqlAstTranslator extends AbstractS emulateQueryPartTableReferenceColumnAliasing( tableReference ); } - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - @Override protected boolean needsRecursiveKeywordInWithClause() { return false; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java index a83a40f758..4f818ac8b8 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDDialect.java @@ -515,4 +515,16 @@ public class CUBRIDDialect extends Dialect { sqlAppender.append( diffUnit.conversionFactor( toUnit, this ) ); } + @Override + public String getDual() { + //TODO: is this really needed? + //TODO: would "from table({0})" be better? + return "db_root"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDSqlAstTranslator.java index e54bb926cb..12590f845d 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/CUBRIDSqlAstTranslator.java @@ -77,16 +77,4 @@ public class CUBRIDSqlAstTranslator extends AbstractSql protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; } - - @Override - protected String getDual() { - //TODO: is this really needed? - //TODO: would "from table({0})" be better? - return "db_root"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java index e1cc404687..8b4827f883 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacyDialect.java @@ -68,6 +68,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.procedure.internal.DB2CallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; @@ -1134,6 +1135,16 @@ public class DB2LegacyDialect extends Dialect { return super.extractPattern( unit ); } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + @Override public int getInExpressionCountLimit() { return BIND_PARAMETERS_NUMBER_LIMIT; @@ -1201,4 +1212,14 @@ public class DB2LegacyDialect extends Dialect { public boolean supportsFromClauseInUpdate() { return getDB2Version().isSameOrAfter( 11 ); } + + @Override + public String getDual() { + return "sysibm.dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacySqlAstTranslator.java index f6ab94261c..07687aa07f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DB2LegacySqlAstTranslator.java @@ -604,16 +604,6 @@ public class DB2LegacySqlAstTranslator extends Abstract return false; } - @Override - protected String getDual() { - return "sysibm.dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - @Override protected void visitReturningColumns(List returningColumns) { // For DB2 we use #renderReturningClause to render a wrapper around the DML statement diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java index 7e79e2a6ae..7485263944 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java @@ -1040,6 +1040,11 @@ public class DerbyDialect extends Dialect { return true; } + @Override + public boolean supportsValuesList() { + return true; + } + @Override public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) throws SQLException { @@ -1057,4 +1062,14 @@ public class DerbyDialect extends Dialect { return DmlTargetColumnQualifierSupport.TABLE_ALIAS; } + @Override + public String getDual() { + return "(values 0)"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual() + " dual"; + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java index 47549c0745..412e4a6941 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java @@ -1051,6 +1051,11 @@ public class DerbyLegacyDialect extends Dialect { return getVersion().isSameOrAfter( 10, 4 ); } + @Override + public boolean supportsValuesList() { + return true; + } + @Override public IdentifierHelper buildIdentifierHelper(IdentifierHelperBuilder builder, DatabaseMetaData dbMetaData) throws SQLException { @@ -1062,4 +1067,14 @@ public class DerbyLegacyDialect extends Dialect { public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() { return DmlTargetColumnQualifierSupport.TABLE_ALIAS; } + + @Override + public String getDual() { + return "(values 0)"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual() + " dual"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacySqlAstTranslator.java index 80439a572d..8988e01b84 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacySqlAstTranslator.java @@ -298,16 +298,6 @@ public class DerbyLegacySqlAstTranslator extends Abstra return false; } - @Override - protected String getDual() { - return "(values 0)"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual() + " dual"; - } - @Override protected boolean needsRowsToSkip() { return !supportsOffsetFetchClause(); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbySqlAstTranslator.java index d2e68a6679..2a03d4f7de 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbySqlAstTranslator.java @@ -298,16 +298,6 @@ public class DerbySqlAstTranslator extends AbstractSqlA return false; } - @Override - protected String getDual() { - return "(values 0)"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual() + " dual"; - } - @Override protected boolean needsRowsToSkip() { return !supportsOffsetFetchClause(); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java index b6779f06d1..5a526a1fda 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdDialect.java @@ -401,25 +401,33 @@ public class FirebirdDialect extends Dialect { } break; case BOOLEAN: - result = BooleanDecoder.toBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "true", "false" ) + : BooleanDecoder.toBoolean( from ); if ( result != null ) { return result; } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -1094,4 +1102,14 @@ public class FirebirdDialect extends Dialect { } } + + @Override + public String getDual() { + return "rdb$database"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java index 78312f9f91..31882f1df8 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/FirebirdSqlAstTranslator.java @@ -260,16 +260,6 @@ public class FirebirdSqlAstTranslator extends AbstractS return false; } - @Override - protected String getDual() { - return "rdb$database"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - private boolean supportsOffsetFetchClause() { return getDialect().getVersion().isSameOrAfter( 3 ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java index 361661f62c..4f66824055 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacyDialect.java @@ -47,6 +47,7 @@ import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.FetchClauseType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.dialect.NullOrdering; @@ -513,6 +514,16 @@ public class H2LegacyDialect extends Dialect { : super.extractPattern(unit); } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + @Override public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) { if ( intervalType != null ) { @@ -991,4 +1002,14 @@ public class H2LegacyDialect extends Dialect { public boolean supportsCaseInsensitiveLike() { return getVersion().isSameOrAfter( 1, 4, 194 ); } + + @Override + public boolean supportsValuesList() { + return true; + } + + @Override + public String getDual() { + return "dual"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacySqlAstTranslator.java index 4db8a901a8..308048f8e3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/H2LegacySqlAstTranslator.java @@ -386,11 +386,6 @@ public class H2LegacySqlAstTranslator extends AbstractS return getClauseStack().getCurrent() != Clause.WITHIN_GROUP || getDialect().getVersion().isSameOrAfter( 2 ); } - @Override - protected String getDual() { - return "dual"; - } - private boolean supportsOffsetFetchClause() { return getDialect().getVersion().isSameOrAfter( 1, 4, 195 ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java index 30cb4f8cc5..cb6c043da3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacyDialect.java @@ -315,25 +315,33 @@ public class HSQLLegacyDialect extends Dialect { } break; case BOOLEAN: - result = BooleanDecoder.toBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "true", "false" ) + : BooleanDecoder.toBoolean( from ); if ( result != null ) { return result; } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -825,6 +833,11 @@ public class HSQLLegacyDialect extends Dialect { return true; } + @Override + public boolean supportsValuesList() { + return true; + } + @Override public IdentityColumnSupport getIdentityColumnSupport() { return identityColumnSupport; @@ -900,4 +913,9 @@ public class HSQLLegacyDialect extends Dialect { public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() { return DmlTargetColumnQualifierSupport.TABLE_ALIAS; } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacySqlAstTranslator.java index 18d00068a3..385555241a 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/HSQLLegacySqlAstTranslator.java @@ -339,11 +339,6 @@ public class HSQLLegacySqlAstTranslator extends Abstrac return false; } - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - private boolean supportsOffsetFetchClause() { return getDialect().getVersion().isSameOrAfter( 2, 5 ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java index 54fc83e84e..f426e74de9 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixDialect.java @@ -854,4 +854,14 @@ public class InformixDialect extends Dialect { jdbcTypeRegistry.addDescriptor( Types.NCLOB, ClobJdbcType.DEFAULT ); typeContributions.contributeJdbcType( VarcharUUIDJdbcType.INSTANCE ); } + + @Override + public String getDual() { + return "(select 0 from systables where tabid=1)"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual() + " dual"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java index 6c6aa273df..79f6504be0 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/InformixSqlAstTranslator.java @@ -151,16 +151,6 @@ public class InformixSqlAstTranslator extends AbstractS return false; } - @Override - protected String getDual() { - return "(select 0 from systables where tabid=1)"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual() + " dual"; - } - @Override protected void renderNull(Literal literal) { if ( getParameterRenderingMode() == SqlAstNodeRenderingMode.NO_UNTYPED ) { diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java index 1482c0d260..d010ccd973 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresDialect.java @@ -557,4 +557,15 @@ public class IngresDialect extends Dialect { public boolean supportsFetchClause(FetchClauseType type) { return getVersion().isSameOrAfter( 9, 3 ); } + + @Override + public String getDual() { + return "(select 0)"; + } + + @Override + public String getFromDualForSelectOnly() { + //this is only necessary if the query has a where clause + return " from " + getDual() + " dual"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java index 88b7c1ce6f..47cadd9770 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/IngresSqlAstTranslator.java @@ -135,17 +135,6 @@ public class IngresSqlAstTranslator extends AbstractSql return false; } - @Override - protected String getDual() { - return "(select 0)"; - } - - @Override - protected String getFromDualForSelectOnly() { - //this is only necessary if the query has a where clause - return " from " + getDual() + " dual"; - } - @Override protected boolean needsRowsToSkip() { return !supportsOffsetFetchClause(); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacyDialect.java index 0dbc1f986b..e1967f5184 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacyDialect.java @@ -262,4 +262,14 @@ public class MariaDBLegacyDialect extends MySQLLegacyDialect { return super.buildIdentifierHelper( builder, dbMetaData ); } + + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return getVersion().isBefore( 10, 4 ) ? ( " from " + getDual() ) : ""; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java index a6a9b16107..ec288bf0f7 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MariaDBLegacySqlAstTranslator.java @@ -364,16 +364,6 @@ public class MariaDBLegacySqlAstTranslator extends Abst return true; } - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return getDialect().getVersion().isBefore( 10, 4 ) ? ( " from " + getDual() ) : ""; - } - @Override public MariaDBLegacyDialect getDialect() { return this.dialect; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java index fde7a7ece4..dc68105b42 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBDialect.java @@ -328,4 +328,14 @@ public class MaxDBDialect extends Dialect { public boolean supportsJdbcConnectionLobCreation(DatabaseMetaData databaseMetaData) { return false; } + + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java index ac6f27a008..eb94eabf35 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MaxDBSqlAstTranslator.java @@ -89,14 +89,4 @@ public class MaxDBSqlAstTranslator extends AbstractSqlA protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; } - - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java index 474352cc2b..a154734e54 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLDialect.java @@ -341,4 +341,9 @@ public class MimerSQLDialect extends Dialect { public IdentityColumnSupport getIdentityColumnSupport() { return MimerSQLIdentityColumnSupport.INSTANCE; } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLSqlAstTranslator.java index a745a3e208..c23d0f47f3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MimerSQLSqlAstTranslator.java @@ -78,9 +78,4 @@ public class MimerSQLSqlAstTranslator extends AbstractS protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java index 77e6710fa1..7f9ac7cb1f 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacyDialect.java @@ -1436,4 +1436,14 @@ public class MySQLLegacyDialect extends Dialect { } return sqlCheckConstraint; } + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return getVersion().isSameOrAfter( 8 ) ? "" : ( " from " + getDual() ); + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java index 3036b681b3..8d9d6a65d3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/MySQLLegacySqlAstTranslator.java @@ -387,16 +387,6 @@ public class MySQLLegacySqlAstTranslator extends Abstra return getDialect().getVersion().isSameOrAfter( 8 ); } - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return getDialect().getVersion().isSameOrAfter( 8 ) ? "" : ( " from " + getDual() ); - } - @Override public MySQLLegacyDialect getDialect() { return (MySQLLegacyDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() ); diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java index 6302f3c8c9..65dfa3705c 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacyDialect.java @@ -397,20 +397,33 @@ public class OracleLegacyDialect extends Dialect { } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case BOOLEAN: + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "true", "false" ) + : BooleanDecoder.toBoolean( from ); + if ( result != null ) { + return result; + } + break; case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -1577,4 +1590,14 @@ public class OracleLegacyDialect extends Dialect { } return sqlCheckConstraint; } + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java index b98b192bad..ac4442f508 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java @@ -672,16 +672,6 @@ public class OracleLegacySqlAstTranslator extends Abstr return getDialect().getVersion().isSameOrAfter( 9 ); } - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - private boolean supportsOffsetFetchClause() { return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java index ec88b5a786..d53e041d09 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/PostgreSQLLegacyDialect.java @@ -58,6 +58,7 @@ import org.hibernate.procedure.internal.PostgreSQLCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.query.SemanticException; import org.hibernate.query.spi.QueryOptions; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.FetchClauseType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.TemporalUnit; @@ -416,6 +417,16 @@ public class PostgreSQLLegacyDialect extends Dialect { } } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + /** * {@code microsecond} is the smallest unit for an {@code interval}, * and the highest precision for a {@code timestamp}, so we could diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java index 9376d7e23e..f35f50d783 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200Dialect.java @@ -432,4 +432,14 @@ public class RDMSOS2200Dialect extends Dialect { public String trimPattern(TrimSpec specification, boolean isWhitespace) { return AbstractTransactSQLDialect.replaceLtrimRtrim( specification, isWhitespace ); } + + @Override + public String getDual() { + return "rdms.rdms_dummy"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual() + " where key_col=1"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200SqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200SqlAstTranslator.java index b669928014..c067088fe3 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200SqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/RDMSOS2200SqlAstTranslator.java @@ -122,14 +122,4 @@ public class RDMSOS2200SqlAstTranslator extends Abstrac protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; } - - @Override - protected String getDual() { - return "rdms.rdms_dummy"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual() + " where key_col=1"; - } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java index 57222592a4..513cfb11a8 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreDialect.java @@ -1410,4 +1410,9 @@ public class SingleStoreDialect extends Dialect { * @settingDefault {@code false} */ public static final String SINGLE_STORE_FOR_UPDATE_LOCK_ENABLED = "hibernate.dialect.singlestore.for_update_lock_enabled"; + + @Override + public String getDual() { + return "dual"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreSqlAstTranslator.java index 2a806e4b4d..fb6129e66c 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SingleStoreSqlAstTranslator.java @@ -435,11 +435,6 @@ public class SingleStoreSqlAstTranslator extends Abstra return false; } - @Override - protected String getDual() { - return "dual"; - } - @Override public SingleStoreDialect getDialect() { return this.dialect; diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java index 784488b85c..5c665b637b 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacyDialect.java @@ -694,4 +694,9 @@ public class SybaseASELegacyDialect extends SybaseLegacyDialect { } return new TopLimitHandler(false); } + + @Override + public String getDual() { + return "(select 1 c1)"; + } } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacySqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacySqlAstTranslator.java index 186d78cca7..b6f594e417 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacySqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseASELegacySqlAstTranslator.java @@ -527,11 +527,6 @@ public class SybaseASELegacySqlAstTranslator extends Ab return false; } - @Override - protected String getDual() { - return "(select 1 c1)"; - } - private boolean supportsTopClause() { return getDialect().getVersion().isSameOrAfter( 12, 5 ); } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java index ae693e73cb..71879f917e 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereDialect.java @@ -213,4 +213,14 @@ public class SybaseAnywhereDialect extends SybaseDialect { return TopLimitHandler.INSTANCE; } + @Override + public String getDual() { + return "sys.dummy"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } + } diff --git a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java index 057b1f73fb..ea414f5110 100644 --- a/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java +++ b/hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/SybaseAnywhereSqlAstTranslator.java @@ -235,14 +235,4 @@ public class SybaseAnywhereSqlAstTranslator extends Abs protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() { return false; } - - @Override - protected String getDual() { - return "sys.dummy"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java index c414465e79..af2f7a4b3b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2Dialect.java @@ -58,6 +58,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.procedure.internal.DB2CallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.TemporalUnit; import org.hibernate.query.sqm.mutation.internal.cte.CteInsertStrategy; @@ -1215,6 +1216,16 @@ public class DB2Dialect extends Dialect { return super.extractPattern( unit ); } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + @Override public int getInExpressionCountLimit() { return BIND_PARAMETERS_NUMBER_LIMIT; @@ -1282,4 +1293,14 @@ public class DB2Dialect extends Dialect { public boolean supportsFromClauseInUpdate() { return getDB2Version().isSameOrAfter( 11 ); } + + @Override + public String getDual() { + return "sysibm.dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/DB2SqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/DB2SqlAstTranslator.java index f2919b2234..d3d328ab7b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/DB2SqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/DB2SqlAstTranslator.java @@ -585,16 +585,6 @@ public class DB2SqlAstTranslator extends AbstractSqlAst return false; } - @Override - protected String getDual() { - return "sysibm.dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - @Override protected void visitReturningColumns(List returningColumns) { // For DB2 we use #renderReturningClause to render a wrapper around the DML statement diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index a7efa68d55..df858fedeb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -1455,7 +1455,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun case INTEGER_BOOLEAN: switch ( from ) { case STRING: - return "case ?1 when 'T' then 1 when 'Y' then 1 when 'F' then 0 when 'N' then 0 else null end"; + return buildStringToBooleanCast( "1", "0" ); case INTEGER: case LONG: return "abs(sign(?1))"; @@ -1470,7 +1470,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun case YN_BOOLEAN: switch ( from ) { case STRING: - return "case ?1 when 'T' then 'Y' when 'Y' then 'Y' when 'F' then 'N' when 'N' then 'N' else null end"; + return buildStringToBooleanCast( "'Y'", "'N'" ); case INTEGER_BOOLEAN: return "case ?1 when 1 then 'Y' when 0 then 'N' else null end"; case INTEGER: @@ -1485,7 +1485,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun case TF_BOOLEAN: switch ( from ) { case STRING: - return "case ?1 when 'T' then 'T' when 'Y' then 'T' when 'F' then 'F' when 'N' then 'F' else null end"; + return buildStringToBooleanCast( "'T'", "'F'" ); case INTEGER_BOOLEAN: return "case ?1 when 1 then 'T' when 0 then 'F' else null end"; case INTEGER: @@ -1500,7 +1500,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun case BOOLEAN: switch ( from ) { case STRING: - return "case ?1 when 'T' then true when 'Y' then true when 'F' then false when 'N' then false else null end"; + return buildStringToBooleanCast( "true", "false" ); case INTEGER_BOOLEAN: case INTEGER: case LONG: @@ -1515,6 +1515,153 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun return "cast(?1 as ?2)"; } + protected static final String[] TRUE_STRING_VALUES = new String[] { "t", "true", "y", "1" }; + protected static final String[] FALSE_STRING_VALUES = new String[] { "f", "false", "n", "0" }; + + protected String buildStringToBooleanCast(String trueValue, String falseValue) { + final boolean supportsValuesList = supportsValuesList(); + final StringBuilder sb = new StringBuilder(); + sb.append( "(select v.x from (" ); + if ( supportsValuesList ) { + sb.append( "values (" ); + sb.append( trueValue ); + sb.append( "),(" ); + sb.append( falseValue ); + sb.append( ")) v(x)" ); + } + else { + sb.append( "select " ); + sb.append( trueValue ); + sb.append( " x"); + sb.append( getFromDualForSelectOnly() ); + sb.append(" union all select " ); + sb.append( falseValue ); + sb.append( getFromDualForSelectOnly() ); + sb.append( ") v" ); + } + sb.append( " left join (" ); + if ( supportsValuesList ) { + sb.append( "values" ); + char separator = ' '; + for ( String trueStringValue : Dialect.TRUE_STRING_VALUES ) { + sb.append( separator ); + sb.append( "('" ); + sb.append( trueStringValue ); + sb.append( "'," ); + sb.append( trueValue ); + sb.append( ')' ); + separator = ','; + } + for ( String falseStringValue : Dialect.FALSE_STRING_VALUES ) { + sb.append( ",('" ); + sb.append( falseStringValue ); + sb.append( "'," ); + sb.append( falseValue ); + sb.append( ')' ); + } + sb.append( ") t(k,v)" ); + } + else { + sb.append( "select '" ); + sb.append( Dialect.TRUE_STRING_VALUES[0] ); + sb.append( "' k," ); + sb.append( trueValue ); + sb.append( " v" ); + sb.append( getFromDualForSelectOnly() ); + for ( int i = 1; i < Dialect.TRUE_STRING_VALUES.length; i++ ) { + sb.append( " union all select '" ); + sb.append( Dialect.TRUE_STRING_VALUES[i] ); + sb.append( "'," ); + sb.append( trueValue ); + sb.append( getFromDualForSelectOnly() ); + } + for ( String falseStringValue : Dialect.FALSE_STRING_VALUES ) { + sb.append( " union all select '" ); + sb.append( falseStringValue ); + sb.append( "'," ); + sb.append( falseValue ); + sb.append( getFromDualForSelectOnly() ); + } + sb.append( ") t" ); + } + sb.append( " on " ); + sb.append( getLowercaseFunction() ); + sb.append( "(?1)=t.k where t.v is null or v.x=t.v)" ); + return sb.toString(); + } + + protected String buildStringToBooleanCastDecode(String trueValue, String falseValue) { + final boolean supportsValuesList = supportsValuesList(); + final StringBuilder sb = new StringBuilder(); + sb.append( "(select v.x from (" ); + if ( supportsValuesList ) { + sb.append( "values (" ); + sb.append( trueValue ); + sb.append( "),(" ); + sb.append( falseValue ); + sb.append( ")) v(x)" ); + } + else { + sb.append( "select " ); + sb.append( trueValue ); + sb.append( " x"); + sb.append( getFromDualForSelectOnly() ); + sb.append(" union all select " ); + sb.append( falseValue ); + sb.append( getFromDualForSelectOnly() ); + sb.append( ") v" ); + } + sb.append( ", (" ); + if ( supportsValuesList ) { + sb.append( "values (" ); + sb.append( buildStringToBooleanDecode( trueValue, falseValue ) ); + sb.append( ")) t(v)" ); + } + else { + sb.append( "select " ); + sb.append( buildStringToBooleanDecode( trueValue, falseValue ) ); + sb.append( " v"); + sb.append( getFromDualForSelectOnly() ); + sb.append(") t" ); + } + sb.append( " where t.v is null or v.x=t.v)" ); + return sb.toString(); + } + + protected String buildStringToBooleanDecode(String trueValue, String falseValue) { + final StringBuilder sb = new StringBuilder(); + sb.append( "decode(" ); + sb.append( getLowercaseFunction() ); + sb.append( "(?1)" ); + for ( String trueStringValue : TRUE_STRING_VALUES ) { + sb.append( ",'" ); + sb.append( trueStringValue ); + sb.append( "'," ); + sb.append( trueValue ); + } + for ( String falseStringValue : FALSE_STRING_VALUES ) { + sb.append( ",'" ); + sb.append( falseStringValue ); + sb.append( "'," ); + sb.append( falseValue ); + } + sb.append( ",null)" ); + return sb.toString(); + } + + /** + * Returns a table expression that has one row. + * + * @return the SQL equivalent to Oracle's {@code dual}. + */ + public String getDual() { + return "(values(0))"; + } + + public String getFromDualForSelectOnly() { + return ""; + } + /** * Obtain a pattern for the SQL equivalent to a * {@code trim()} function call. The resulting diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index d74c6d36e9..9d762f758c 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -42,6 +42,7 @@ import org.hibernate.internal.util.StringHelper; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.persister.entity.mutation.EntityMutationTarget; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.FetchClauseType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.TemporalUnit; @@ -442,6 +443,16 @@ public class H2Dialect extends Dialect { : super.extractPattern(unit); } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + @Override @SuppressWarnings("deprecation") public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) { if ( intervalType != null ) { @@ -1010,4 +1021,14 @@ public class H2Dialect extends Dialect { return true; } + @Override + public boolean supportsValuesList() { + return true; + } + + @Override + public String getDual() { + return "dual"; + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2SqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2SqlAstTranslator.java index 8dd6df252d..72abf12742 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2SqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2SqlAstTranslator.java @@ -358,11 +358,6 @@ public class H2SqlAstTranslator extends SqlAstTranslato return true; } - @Override - protected String getDual() { - return "dual"; - } - private boolean supportsOffsetFetchClause() { return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java index 71fad2b71c..9c16ff01c9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANADialect.java @@ -1996,4 +1996,14 @@ public class HANADialect extends Dialect { public String getForUpdateString(LockMode lockMode) { return super.getForUpdateString(lockMode); } + + @Override + public String getDual() { + return "sys.dummy"; + } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HANASqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/HANASqlAstTranslator.java index c9e1e3c2a3..ca432a87bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HANASqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HANASqlAstTranslator.java @@ -249,16 +249,6 @@ public class HANASqlAstTranslator extends AbstractSqlAs return false; } - @Override - protected String getDual() { - return "sys.dummy"; - } - - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - @Override protected void renderInsertIntoNoColumns(TableInsertStandard tableInsert) { throw new MappingException( diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java index 5ff07f9d2a..8381efba55 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -250,25 +250,33 @@ public class HSQLDialect extends Dialect { } break; case BOOLEAN: - result = BooleanDecoder.toBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "true", "false" ) + : BooleanDecoder.toBoolean( from ); if ( result != null ) { return result; } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -610,6 +618,11 @@ public class HSQLDialect extends Dialect { return true; } + @Override + public boolean supportsValuesList() { + return true; + } + @Override public IdentityColumnSupport getIdentityColumnSupport() { return identityColumnSupport; @@ -690,4 +703,9 @@ public class HSQLDialect extends Dialect { public DmlTargetColumnQualifierSupport getDmlTargetColumnQualifierSupport() { return DmlTargetColumnQualifierSupport.TABLE_ALIAS; } + + @Override + public String getFromDualForSelectOnly() { + return " from " + getDual(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLSqlAstTranslator.java index cd3431c69c..63546f2528 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLSqlAstTranslator.java @@ -333,11 +333,6 @@ public class HSQLSqlAstTranslator extends AbstractSqlAs return false; } - @Override - protected String getFromDualForSelectOnly() { - return " from " + getDual(); - } - private boolean supportsOffsetFetchClause() { return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java index 6eb4b6252d..c97aaaa16d 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBDialect.java @@ -281,4 +281,9 @@ public class MariaDBDialect extends MySQLDialect { return super.buildIdentifierHelper( builder, dbMetaData ); } + + @Override + public String getDual() { + return "dual"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java index 08c24d6d98..1f769c64fd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MariaDBSqlAstTranslator.java @@ -367,11 +367,6 @@ public class MariaDBSqlAstTranslator extends AbstractSq return true; } - @Override - protected String getDual() { - return "dual"; - } - @Override public MariaDBDialect getDialect() { return this.dialect; diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index 698669d861..db87ca6161 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -1516,4 +1516,9 @@ public class MySQLDialect extends Dialect { public boolean supportsBindingNullSqlTypeForSetNull() { return true; } + + @Override + public String getDual() { + return "dual"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java index bee9c4bd74..542d76dd39 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLSqlAstTranslator.java @@ -433,11 +433,6 @@ public class MySQLSqlAstTranslator extends AbstractSqlA return true; } - @Override - protected String getDual() { - return "dual"; - } - @Override public MySQLDialect getDialect() { return (MySQLDialect) DialectDelegateWrapper.extractRealDialect( super.getDialect() ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java index 74508089fd..e13a23a5b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleDialect.java @@ -462,25 +462,33 @@ public class OracleDialect extends Dialect { } break; case INTEGER_BOOLEAN: - result = BooleanDecoder.toIntegerBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "1", "0" ) + : BooleanDecoder.toIntegerBoolean( from ); if ( result != null ) { return result; } break; case YN_BOOLEAN: - result = BooleanDecoder.toYesNoBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'Y'", "'N'" ) + : BooleanDecoder.toYesNoBoolean( from ); if ( result != null ) { return result; } break; case BOOLEAN: - result = BooleanDecoder.toBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "true", "false" ) + : BooleanDecoder.toBoolean( from ); if ( result != null ) { return result; } break; case TF_BOOLEAN: - result = BooleanDecoder.toTrueFalseBoolean( from ); + result = from == CastType.STRING + ? buildStringToBooleanCastDecode( "'T'", "'F'" ) + : BooleanDecoder.toTrueFalseBoolean( from ); if ( result != null ) { return result; } @@ -1696,4 +1704,14 @@ public class OracleDialect extends Dialect { ? sqlCheckConstraint + " " + checkConstraint.getOptions() : sqlCheckConstraint; } + @Override + public String getDual() { + return "dual"; + } + + @Override + public String getFromDualForSelectOnly() { + return getVersion().isSameOrAfter( 23 ) ? "" : ( " from " + getDual() ); + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java index 5a5c103461..329fc32e96 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java @@ -615,16 +615,6 @@ public class OracleSqlAstTranslator extends SqlAstTrans return false; } - @Override - protected String getDual() { - return "dual"; - } - - @Override - protected String getFromDualForSelectOnly() { - return getDialect().getVersion().isSameOrAfter( 23 ) ? "" : ( " from " + getDual() ); - } - private boolean supportsOffsetFetchClause() { return getDialect().supportsFetchClause( FetchClauseType.ROWS_ONLY ); } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java index e656257d2c..86641fa616 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/PostgreSQLDialect.java @@ -56,6 +56,7 @@ import org.hibernate.procedure.internal.PostgreSQLCallableStatementSupport; import org.hibernate.procedure.spi.CallableStatementSupport; import org.hibernate.query.SemanticException; import org.hibernate.query.spi.QueryOptions; +import org.hibernate.query.sqm.CastType; import org.hibernate.query.sqm.FetchClauseType; import org.hibernate.query.sqm.IntervalType; import org.hibernate.query.sqm.TemporalUnit; @@ -436,6 +437,16 @@ public class PostgreSQLDialect extends Dialect { }; } + @Override + public String castPattern(CastType from, CastType to) { + if ( from == CastType.STRING && to == CastType.BOOLEAN ) { + return "cast(?1 as ?2)"; + } + else { + return super.castPattern( from, to ); + } + } + /** * {@code microsecond} is the smallest unit for an {@code interval}, * and the highest precision for a {@code timestamp}, so we could diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java index a8fd7ecf6f..a0a957578b 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASEDialect.java @@ -710,4 +710,9 @@ public class SybaseASEDialect extends SybaseDialect { public LimitHandler getLimitHandler() { return new TopLimitHandler(false); } + + @Override + public String getDual() { + return "(select 1 c1)"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASESqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASESqlAstTranslator.java index 0dae944d69..a6d4eaf5c8 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASESqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/SybaseASESqlAstTranslator.java @@ -506,11 +506,6 @@ public class SybaseASESqlAstTranslator extends Abstract return false; } - @Override - protected String getDual() { - return "(select 1 c1)"; - } - private boolean supportsParameterOffsetFetchExpression() { return false; } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java index 477ad9dc5a..dd1c2dfb28 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBDialect.java @@ -187,4 +187,9 @@ public class TiDBDialect extends MySQLDialect { ? "timestampadd(microsecond,?2*1e6,?3)" : super.timestampaddPattern(unit, temporalType, intervalType); } + + @Override + public String getDual() { + return "dual"; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java index a858dd4b2e..ade81bf7d9 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/TiDBSqlAstTranslator.java @@ -330,11 +330,6 @@ public class TiDBSqlAstTranslator extends AbstractSqlAs return false; } - @Override - protected String getDual() { - return "dual"; - } - @Override protected String getForShare(int timeoutMillis) { if ( timeoutMillis == LockOptions.NO_WAIT ) { diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java index 4119f82ac2..32ca232afe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java @@ -8579,11 +8579,11 @@ public abstract class AbstractSqlAstTranslator implemen * @return the SQL equivalent to Oracle's {@code dual}. */ protected String getDual() { - return "(values(0))"; + return dialect.getDual(); } protected String getFromDualForSelectOnly() { - return ""; + return dialect.getFromDualForSelectOnly(); } protected enum LockStrategy { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java index cb9bfe8c09..4602e2267d 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/FunctionTests.java @@ -5,6 +5,9 @@ package org.hibernate.orm.test.query.hql; import org.hamcrest.Matchers; + +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; import org.hibernate.QueryException; import org.hibernate.community.dialect.AltibaseDialect; import org.hibernate.community.dialect.InformixDialect; @@ -22,6 +25,8 @@ import org.hibernate.dialect.SQLServerDialect; import org.hibernate.dialect.SybaseDialect; import org.hibernate.dialect.TiDBDialect; import org.hibernate.query.sqm.produce.function.FunctionArgumentException; +import org.hibernate.sql.exec.ExecutionException; + import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.domain.StandardDomainModel; import org.hibernate.testing.orm.domain.gambit.EntityOfBasics; @@ -30,6 +35,7 @@ import org.hibernate.testing.orm.domain.gambit.EntityOfMaps; import org.hibernate.testing.orm.domain.gambit.SimpleEntity; import org.hibernate.testing.orm.junit.DialectFeatureChecks; import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.RequiresDialect; import org.hibernate.testing.orm.junit.RequiresDialectFeature; @@ -63,6 +69,7 @@ import static org.hamcrest.Matchers.isOneOf; import static org.hibernate.testing.orm.domain.gambit.EntityOfBasics.Gender.FEMALE; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -1028,6 +1035,44 @@ public class FunctionTests { ); } + @Test + @Jira("https://hibernate.atlassian.net/browse/HHH-18447") + public void testCastStringToBoolean(SessionFactoryScope scope) { + scope.inTransaction( session -> { + assertThat( session.createQuery("select cast('1' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('0' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('y' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('n' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('Y' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('N' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('t' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('f' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('T' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('F' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('true' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('false' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + assertThat( session.createQuery("select cast('TRUE' as Boolean)", Boolean.class).getSingleResult(), is(true) ); + assertThat( session.createQuery("select cast('FALSE' as Boolean)", Boolean.class).getSingleResult(), is(false) ); + }); + } + + @Test + @Jira("https://hibernate.atlassian.net/browse/HHH-18447") + public void testCastInvalidStringToBoolean(SessionFactoryScope scope) { + scope.inTransaction( session -> { + try { + session.createQuery( "select cast('bla' as Boolean)", Boolean.class ).getSingleResult(); + fail("Casting invalid boolean string should fail"); + } + catch ( HibernateException e ) { + // Expected + if ( !( e instanceof JDBCException || e instanceof ExecutionException ) ) { + throw e; + } + } + } ); + } + @Test @SkipForDialect(dialectClass = DB2Dialect.class, matchSubTypes = true) @SkipForDialect(dialectClass = DerbyDialect.class)