mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-06 19:36:03 +00:00
HHH-11692 Introduce DISTINCT predicate in HQL and implement emulations
This commit is contained in:
parent
e67d10ee6c
commit
06b5eb43c6
@ -415,6 +415,8 @@ comparisonOperator
|
||||
| GREATER_EQUAL
|
||||
| LESS
|
||||
| LESS_EQUAL
|
||||
| IS DISTINCT FROM
|
||||
| IS NOT DISTINCT FROM
|
||||
;
|
||||
|
||||
inList
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -38,4 +46,60 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// CUBRID does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
//TODO: is this really needed?
|
||||
//TODO: would "from table({0})" be better?
|
||||
return " from db_root";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -69,4 +76,48 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Cache does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -68,4 +71,25 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Cockroach does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -10,12 +10,20 @@
|
||||
|
||||
import org.hibernate.query.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.MutationStatement;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.insert.InsertStatement;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
@ -134,6 +142,86 @@ protected boolean renderReturningClause(MutationStatement statement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
if ( getDialect().getVersion() >= 1110 ) {
|
||||
renderComparisonStandard( lhs, operator, rhs );
|
||||
}
|
||||
else {
|
||||
renderComparisonEmulateDecode( lhs, operator, rhs );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectExpression(Expression expression) {
|
||||
// Null literals have to be casted in the select clause
|
||||
if ( expression instanceof Literal ) {
|
||||
final Literal literal = (Literal) expression;
|
||||
if ( literal.getLiteralValue() == null ) {
|
||||
renderCasted( literal );
|
||||
}
|
||||
else {
|
||||
renderLiteral( literal, true );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof NullnessLiteral || expression instanceof JdbcParameter || expression instanceof SqmParameterInterpretation ) {
|
||||
renderCasted( expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from sysibm.dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void visitReturningColumns(MutationStatement mutationStatement) {
|
||||
// For DB2 we use #renderReturningClause to render a wrapper around the DML statement
|
||||
|
@ -7,7 +7,9 @@
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
@ -41,5 +43,9 @@ protected boolean supportsOffsetClause() {
|
||||
return version >= 710;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonStandard( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,9 @@
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
@ -42,4 +44,10 @@ protected boolean supportsOffsetClause() {
|
||||
return version >= 1200;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
// Supported at least since DB2 z/OS 9.0
|
||||
renderComparisonStandard( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,12 +6,22 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteContainer;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -76,6 +86,81 @@ protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectExpression(Expression expression) {
|
||||
// Null literals have to be casted in the select clause
|
||||
if ( expression instanceof Literal ) {
|
||||
final Literal literal = (Literal) expression;
|
||||
if ( literal.getLiteralValue() == null ) {
|
||||
renderCasted( literal );
|
||||
}
|
||||
else {
|
||||
renderLiteral( literal, true );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof NullnessLiteral || expression instanceof JdbcParameter || expression instanceof SqmParameterInterpretation ) {
|
||||
renderCasted( expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from (values 0) as dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return !supportsOffsetFetchClause();
|
||||
|
@ -73,6 +73,7 @@
|
||||
import org.hibernate.sql.*;
|
||||
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
|
||||
import org.hibernate.sql.ast.spi.ANSICaseExpressionWalker;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.CaseExpressionWalker;
|
||||
import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
|
||||
@ -1517,12 +1518,18 @@ public String getSelectGUIDString() {
|
||||
* 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;
|
||||
}
|
||||
@ -1895,12 +1902,6 @@ public String getCreateMultisetTableString() {
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType entityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
if ( entityDescriptor.getIdentifierMapping() instanceof CompositeIdentifierMapping) {
|
||||
if ( !supportsTuplesInSubqueries() ) {
|
||||
return new InlineStrategy( this );
|
||||
}
|
||||
}
|
||||
|
||||
return new PersistentTableStrategy(
|
||||
new IdTable( entityDescriptor, name -> name, this ),
|
||||
AfterUseAction.CLEAN,
|
||||
@ -2836,7 +2837,9 @@ public boolean areStringComparisonsCaseInsensitive() {
|
||||
* @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;
|
||||
@ -2850,7 +2853,9 @@ public boolean supportsRowValueConstructorSyntax() {
|
||||
* "... 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();
|
||||
}
|
||||
@ -2865,7 +2870,9 @@ public boolean supportsRowValueConstructorSyntaxInSet() {
|
||||
* @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;
|
||||
@ -2880,11 +2887,17 @@ public boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
* @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();
|
||||
}
|
||||
@ -2893,7 +2906,9 @@ public boolean supportsRowValueConstructorSyntaxInInSubquery() {
|
||||
* 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;
|
||||
}
|
||||
@ -2902,7 +2917,9 @@ public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStr
|
||||
* 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;
|
||||
}
|
||||
@ -3006,7 +3023,9 @@ public String renderOrderByElement(String expression, String collation, String o
|
||||
*
|
||||
* @return True if select clause parameter must be cast()ed
|
||||
* @since 3.2
|
||||
* @deprecated Moved to {@link AbstractSqlAstTranslator}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean requiresCastingOfParametersInSelectClause() {
|
||||
return false;
|
||||
}
|
||||
@ -3364,7 +3383,9 @@ public ScrollMode defaultScrollMode() {
|
||||
* delete from Table1 where (col1, col2) in (select col1, col2 from Table2)
|
||||
*
|
||||
* @return boolean
|
||||
* @deprecated See {@link #supportsRowValueConstructorSyntaxInInSubquery()}
|
||||
*/
|
||||
@Deprecated
|
||||
public boolean supportsTuplesInSubqueries() {
|
||||
return true;
|
||||
}
|
||||
|
@ -614,7 +614,7 @@ public LimitHandler getLimitHandler() {
|
||||
public String getSelectGUIDString() {
|
||||
return getVersion() < 210
|
||||
? super.getSelectGUIDString()
|
||||
: "select uuid_to_char(gen_uuid()) " + getFromDual();
|
||||
: "select uuid_to_char(gen_uuid()) from rdb$database";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -637,7 +637,7 @@ public boolean supportsCurrentTimestampSelection() {
|
||||
|
||||
@Override
|
||||
public String getCurrentTimestampSelectString() {
|
||||
return "select current_timestamp " + getFromDual();
|
||||
return "select current_timestamp from rdb$database";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,10 +13,13 @@
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.CastTarget;
|
||||
@ -27,6 +30,12 @@
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
||||
import org.hibernate.sql.ast.tree.predicate.SelfRenderingPredicate;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -126,6 +135,75 @@ protected boolean supportsSimpleQueryGrouping() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectExpression(Expression expression) {
|
||||
// Null literals have to be casted in the select clause
|
||||
if ( expression instanceof Literal ) {
|
||||
final Literal literal = (Literal) expression;
|
||||
if ( literal.getLiteralValue() == null ) {
|
||||
renderCasted( literal );
|
||||
}
|
||||
else {
|
||||
renderLiteral( literal, true );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof NullnessLiteral || expression instanceof JdbcParameter || expression instanceof SqmParameterInterpretation ) {
|
||||
renderCasted( expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from rdb$database";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 300;
|
||||
}
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -55,6 +63,50 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// H2 does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from dual";
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 104195;
|
||||
}
|
||||
|
@ -7,9 +7,13 @@
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -69,4 +73,37 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// HANA does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from sys.dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,21 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.sqm.sql.internal.SqmParameterInterpretation;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.NullnessLiteral;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -45,6 +56,75 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// HSQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectExpression(Expression expression) {
|
||||
// Null literals have to be casted in the select clause
|
||||
if ( expression instanceof Literal ) {
|
||||
final Literal literal = (Literal) expression;
|
||||
if ( literal.getLiteralValue() == null ) {
|
||||
renderCasted( literal );
|
||||
}
|
||||
else {
|
||||
renderLiteral( literal, true );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof NullnessLiteral || expression instanceof JdbcParameter || expression instanceof SqmParameterInterpretation ) {
|
||||
renderCasted( expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from (values(0))";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 250;
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -89,6 +96,66 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// Informix does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
// We render an empty group instead of literals as some DBs don't support grouping by literals
|
||||
// Note that integer literals, which refer to select item positions, are handled in #visitGroupByClause
|
||||
if ( expression instanceof Literal ) {
|
||||
// todo (6.0): We need to introduce a dummy from clause item
|
||||
// String fromItem = ", (select 1 x " + dialect.getFromDual() + ") dummy";
|
||||
// sqlBuffer.insert( fromEndIndex, fromItem );
|
||||
// appendSql( "dummy.x" );
|
||||
throw new UnsupportedOperationException( "Column reference strategy is not yet implemented!" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from (select 0 from systables where tabid = 1) as dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
private boolean supportsParameterOffsetFetchExpression() {
|
||||
return getDialect().getVersion() >= 11;
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -83,6 +90,65 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// Ingres does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
// todo (6.0): We need to introduce a dummy from clause item
|
||||
// String fromItem = ", (select 1 x " + dialect.getFromDual() + ") dummy";
|
||||
// sqlBuffer.insert( fromEndIndex, fromItem );
|
||||
// appendSql( "dummy.x" );
|
||||
throw new UnsupportedOperationException( "Column reference strategy is not yet implemented!" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
//this is only necessary if the query has a where clause
|
||||
return " from (select 0) as dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return !supportsOffsetFetchClause();
|
||||
|
@ -7,9 +7,13 @@
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -68,6 +72,37 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// MariaDB does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonDistinctOperator( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( " with " );
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRowValueConstructorSyntaxInSet() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean supportsWindowFunctions() {
|
||||
return getDialect().getVersion() >= 1020;
|
||||
}
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -38,4 +46,58 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MaxDB does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFromDual() {
|
||||
return " from dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -39,4 +47,58 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// MimerSQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from (values(0))";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -7,9 +7,13 @@
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -69,6 +73,47 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// MySQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonDistinctOperator( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( " with " );
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRowValueConstructorSyntaxInSet() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return getDialect().getVersion() >= 570;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from dual";
|
||||
}
|
||||
|
||||
private boolean supportsWindowFunctions() {
|
||||
return getDialect().getVersion() >= 802;
|
||||
}
|
||||
|
@ -21,6 +21,6 @@
|
||||
public class Oracle10gDialect extends OracleDialect {
|
||||
|
||||
public Oracle10gDialect() {
|
||||
super(10);
|
||||
super( 1000 );
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,6 @@
|
||||
public class Oracle12cDialect extends OracleDialect {
|
||||
|
||||
public Oracle12cDialect() {
|
||||
super(12);
|
||||
super( 1200 );
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
public class Oracle8iDialect extends OracleDialect {
|
||||
|
||||
public Oracle8iDialect() {
|
||||
super(8);
|
||||
super( 800 );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
public class Oracle9iDialect extends OracleDialect {
|
||||
|
||||
public Oracle9iDialect() {
|
||||
super(9);
|
||||
super( 900 );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public class OracleDialect extends Dialect {
|
||||
private final int version;
|
||||
|
||||
public OracleDialect(DialectResolutionInfo info) {
|
||||
this( info.getDatabaseMajorVersion() );
|
||||
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() );
|
||||
}
|
||||
|
||||
private static final Pattern DISTINCT_KEYWORD_PATTERN = Pattern.compile( "\\bdistinct\\b" );
|
||||
@ -114,7 +114,7 @@ public OracleDialect(DialectResolutionInfo info) {
|
||||
private final LimitHandler limitHandler;
|
||||
|
||||
public OracleDialect() {
|
||||
this(8);
|
||||
this( 800 );
|
||||
}
|
||||
|
||||
public OracleDialect(int version) {
|
||||
@ -128,7 +128,7 @@ public OracleDialect(int version) {
|
||||
registerReverseHibernateTypeMappings();
|
||||
registerDefaultProperties();
|
||||
|
||||
limitHandler = getVersion() < 12
|
||||
limitHandler = getVersion() < 1200
|
||||
? new LegacyOracleLimitHandler( getVersion() )
|
||||
: OffsetFetchLimitHandler.INSTANCE;
|
||||
}
|
||||
@ -182,7 +182,7 @@ public void initializeFunctionRegistry(QueryEngine queryEngine) {
|
||||
CommonFunctionFactory.corr( queryEngine );
|
||||
CommonFunctionFactory.regrLinearRegressionAggregates( queryEngine );
|
||||
|
||||
if ( getVersion() < 9 ) {
|
||||
if ( getVersion() < 900 ) {
|
||||
queryEngine.getSqmFunctionRegistry().register( "coalesce", new NvlCoalesceEmulation() );
|
||||
}
|
||||
else {
|
||||
@ -211,7 +211,7 @@ protected <T extends JdbcOperation> SqlAstTranslator<T> buildTranslator(
|
||||
|
||||
@Override
|
||||
public String currentDate() {
|
||||
return getVersion() < 9 ? currentTimestamp() : "current_date";
|
||||
return getVersion() < 900 ? currentTimestamp() : "current_date";
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -221,7 +221,7 @@ public String currentTime() {
|
||||
|
||||
@Override
|
||||
public String currentTimestamp() {
|
||||
return getVersion() < 9 ? "sysdate" : currentTimestampWithTimeZone();
|
||||
return getVersion() < 900 ? "sysdate" : currentTimestampWithTimeZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -231,12 +231,12 @@ public String currentLocalTime() {
|
||||
|
||||
@Override
|
||||
public String currentLocalTimestamp() {
|
||||
return getVersion() < 9 ? currentTimestamp() : "localtimestamp";
|
||||
return getVersion() < 900 ? currentTimestamp() : "localtimestamp";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String currentTimestampWithTimeZone() {
|
||||
return getVersion() < 9 ? currentTimestamp() : "current_timestamp";
|
||||
return getVersion() < 900 ? currentTimestamp() : "current_timestamp";
|
||||
}
|
||||
|
||||
|
||||
@ -523,7 +523,7 @@ private void extractField(
|
||||
}
|
||||
|
||||
protected void registerCharacterTypeMappings() {
|
||||
if ( getVersion() < 9) {
|
||||
if ( getVersion() < 900) {
|
||||
registerColumnType( Types.VARCHAR, 4000, "varchar2($l)" );
|
||||
registerColumnType( Types.VARCHAR, "clob" );
|
||||
}
|
||||
@ -549,7 +549,7 @@ protected void registerNumericTypeMappings() {
|
||||
}
|
||||
|
||||
protected void registerDateTimeTypeMappings() {
|
||||
if ( getVersion() < 9 ) {
|
||||
if ( getVersion() < 900 ) {
|
||||
registerColumnType( Types.DATE, "date" );
|
||||
registerColumnType( Types.TIME, "date" );
|
||||
registerColumnType( Types.TIMESTAMP, "date" );
|
||||
@ -567,7 +567,7 @@ protected void registerDateTimeTypeMappings() {
|
||||
|
||||
@Override
|
||||
public boolean supportsTimezoneTypes() {
|
||||
return getVersion() >= 9;
|
||||
return getVersion() >= 900;
|
||||
}
|
||||
|
||||
protected void registerBinaryTypeMappings() {
|
||||
@ -585,7 +585,7 @@ protected void registerDefaultProperties() {
|
||||
getDefaultProperties().setProperty( Environment.USE_STREAMS_FOR_BINARY, "true" );
|
||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
|
||||
|
||||
if ( getVersion() < 12 ) {
|
||||
if ( getVersion() < 1200 ) {
|
||||
// Oracle driver reports to support getGeneratedKeys(), but they only
|
||||
// support the version taking an array of the names of the columns to
|
||||
// be returned (via its RETURNING clause). No other driver seems to
|
||||
@ -641,7 +641,7 @@ public boolean supportsBitType() {
|
||||
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
|
||||
super.contributeTypes( typeContributions, serviceRegistry );
|
||||
|
||||
if ( getVersion() >= 12 ) {
|
||||
if ( getVersion() >= 1200 ) {
|
||||
// account for Oracle's deprecated support for LONGVARBINARY
|
||||
// prefer BLOB, unless the user explicitly opts out
|
||||
boolean preferLong = serviceRegistry.getService( ConfigurationService.class ).getSetting(
|
||||
@ -745,7 +745,7 @@ public String getTableAliasSeparator() {
|
||||
|
||||
@Override
|
||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
return getVersion() < 12
|
||||
return getVersion() < 1200
|
||||
? super.getIdentityColumnSupport()
|
||||
: new Oracle12cIdentityColumnSupport();
|
||||
}
|
||||
@ -753,12 +753,12 @@ public IdentityColumnSupport getIdentityColumnSupport() {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public JoinFragment createOuterJoinFragment() {
|
||||
return getVersion() < 10 ? new OracleJoinFragment() : new ANSIJoinFragment();
|
||||
return getVersion() < 1000 ? new OracleJoinFragment() : new ANSIJoinFragment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCrossJoinSeparator() {
|
||||
return getVersion() < 10 ? ", " : " cross join ";
|
||||
return getVersion() < 1000 ? ", " : " cross join ";
|
||||
}
|
||||
|
||||
/**
|
||||
@ -770,7 +770,7 @@ public String getCrossJoinSeparator() {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public CaseFragment createCaseFragment() {
|
||||
return getVersion() < 9
|
||||
return getVersion() < 900
|
||||
? new DecodeCaseFragment()
|
||||
// Oracle did add support for ANSI CASE statements in 9i
|
||||
: new ANSICaseFragment();
|
||||
@ -783,7 +783,7 @@ public LimitHandler getLimitHandler() {
|
||||
|
||||
@Override
|
||||
public String getSelectClauseNullString(int sqlType) {
|
||||
if ( getVersion() >= 9 ) {
|
||||
if ( getVersion() >= 900 ) {
|
||||
return super.getSelectClauseNullString(sqlType);
|
||||
}
|
||||
else {
|
||||
@ -804,7 +804,7 @@ public String getSelectClauseNullString(int sqlType) {
|
||||
|
||||
@Override
|
||||
public String getCurrentTimestampSelectString() {
|
||||
return getVersion() < 9
|
||||
return getVersion() < 900
|
||||
? "select sysdate from dual"
|
||||
: "select systimestamp from dual";
|
||||
}
|
||||
@ -812,7 +812,7 @@ public String getCurrentTimestampSelectString() {
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
public String getCurrentTimestampSQLFunctionName() {
|
||||
return getVersion() < 9
|
||||
return getVersion() < 900
|
||||
? "sysdate"
|
||||
// the standard SQL function name is current_timestamp...
|
||||
: "current_timestamp";
|
||||
@ -1118,7 +1118,7 @@ public boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
|
||||
@Override
|
||||
public boolean supportsRowValueConstructorSyntaxInInSubquery() {
|
||||
return getVersion() >= 9;
|
||||
return getVersion() >= 900;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1128,12 +1128,12 @@ public boolean supportsTupleDistinctCounts() {
|
||||
|
||||
@Override
|
||||
public boolean supportsNoWait() {
|
||||
return getVersion() >= 9;
|
||||
return getVersion() >= 900;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsSkipLocked() {
|
||||
return getVersion() >= 10;
|
||||
return getVersion() >= 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,9 +10,15 @@
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.Stack;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.insert.Values;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
@ -104,8 +110,68 @@ protected void renderRowNumber(SelectClause selectClause, QueryPart queryPart) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateDecode( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return getDialect().getVersion() >= 820;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInSubQuery() {
|
||||
return getDialect().getVersion() >= 900;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from dual";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 12;
|
||||
return getDialect().getVersion() >= 1200;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,6 +11,9 @@
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -85,6 +88,40 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// PostgreSQL does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
// We render an empty group instead of literals as some DBs don't support grouping by literals
|
||||
// Note that integer literals, which refer to select item positions, are handled in #visitGroupByClause
|
||||
if ( expression instanceof Literal ) {
|
||||
if ( getDialect().getVersion() >= 950 ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else {
|
||||
appendSql( "(select 1" );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
appendSql( ')' );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
if ( getDialect().getVersion() >= 950 ) {
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean supportsOffsetFetchClause() {
|
||||
return getDialect().getVersion() >= 840;
|
||||
}
|
||||
|
@ -6,12 +6,20 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.Limit;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -64,4 +72,58 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Unisys 2200 does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from rdms.rdms_dummy where key_col = 1";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,16 @@
|
||||
|
||||
import org.hibernate.query.FetchClauseType;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryGroup;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
@ -203,6 +208,50 @@ protected void renderCycleClause(CteStatement cte) {
|
||||
// SQL Server does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( " with " );
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
enum OffsetFetchClauseMode {
|
||||
STANDARD,
|
||||
TOP_ONLY,
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -38,4 +46,48 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Spanner does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -83,6 +90,39 @@ protected void renderOffsetExpression(Expression offsetExpression) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
// todo (6.0): We need to introduce a dummy from clause item
|
||||
// String fromItem = ", (select 1 x " + dialect.getFromDual() + ") dummy";
|
||||
// sqlBuffer.insert( fromEndIndex, fromItem );
|
||||
// appendSql( "dummy.x" );
|
||||
throw new UnsupportedOperationException( "Column reference strategy is not yet implemented!" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
@ -93,6 +133,21 @@ protected boolean needsMaxRows() {
|
||||
return !supportsTopClause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean supportsTopClause() {
|
||||
return getDialect().getVersion() >= 1250;
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -81,4 +88,58 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Sybase Anywhere does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDual() {
|
||||
return " from sys.dummy";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return getFromDual();
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.exec.spi.JdbcOperation;
|
||||
|
||||
@ -42,6 +50,54 @@ public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
// todo (6.0): We need to introduce a dummy from clause item
|
||||
// String fromItem = ", (select 1 x " + dialect.getFromDual() + ") dummy";
|
||||
// sqlBuffer.insert( fromEndIndex, fromItem );
|
||||
// appendSql( "dummy.x" );
|
||||
throw new UnsupportedOperationException( "Column reference strategy is not yet implemented!" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean needsRowsToSkip() {
|
||||
return true;
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -63,4 +70,48 @@ protected void renderSearchClause(CteStatement cte) {
|
||||
protected void renderCycleClause(CteStatement cte) {
|
||||
// Teradata does not support this, but it can be emulated
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,18 @@
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.cte.CteStatement;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.Literal;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.select.QueryPart;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.sql.ast.tree.select.SelectClause;
|
||||
@ -55,4 +62,48 @@ protected void renderFetchPlusOffsetExpression(
|
||||
public void visitOffsetFetchClause(QueryPart queryPart) {
|
||||
// TimesTen uses ROWS TO clause
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonEmulateIntersect( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderSelectTupleComparison(
|
||||
List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
emulateTupleComparison( lhsExpressions, tuple.getExpressions(), operator, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
if ( expression instanceof Literal ) {
|
||||
appendSql( "'0' || '0'" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
*/
|
||||
public class LegacyOracleLimitHandler extends AbstractLimitHandler {
|
||||
|
||||
private int version;
|
||||
private final int version;
|
||||
|
||||
public LegacyOracleLimitHandler(int version) {
|
||||
this.version = version;
|
||||
@ -39,7 +39,7 @@ public String processSql(String sql, RowSelection selection) {
|
||||
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
|
||||
if ( hasOffset ) {
|
||||
pagingSelect.append( "select * from (select row_.*, rownum rownum_ from (" ).append( sql );
|
||||
if ( version < 9 ) {
|
||||
if ( version < 900 ) {
|
||||
pagingSelect.append( ") row_) where rownum_ <= ? and rownum_ > ?" );
|
||||
}
|
||||
else {
|
||||
@ -74,7 +74,7 @@ public String processSql(String sql, Limit limit) {
|
||||
final StringBuilder pagingSelect = new StringBuilder( sql.length() + 100 );
|
||||
if ( hasOffset ) {
|
||||
pagingSelect.append( "select * from (select row_.*, rownum rownum_ from (" ).append( sql );
|
||||
if ( version < 9 ) {
|
||||
if ( version < 900 ) {
|
||||
pagingSelect.append( ") row_) where rownum_ <= ? and rownum_ > ?" );
|
||||
}
|
||||
else {
|
||||
|
@ -64,6 +64,59 @@ public String sqlText() {
|
||||
return "!=";
|
||||
}
|
||||
},
|
||||
NOT_DISTINCT_FROM {
|
||||
@Override
|
||||
public ComparisonOperator negated() {
|
||||
return DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator invert() {
|
||||
return NOT_DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator broader() {
|
||||
return NOT_DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator sharper() {
|
||||
return NOT_DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sqlText() {
|
||||
return "is not distinct from";
|
||||
}
|
||||
},
|
||||
|
||||
DISTINCT_FROM {
|
||||
@Override
|
||||
public ComparisonOperator negated() {
|
||||
return NOT_DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator invert() {
|
||||
return DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator broader() {
|
||||
return DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonOperator sharper() {
|
||||
return DISTINCT_FROM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sqlText() {
|
||||
return "is distinct from";
|
||||
}
|
||||
},
|
||||
|
||||
LESS_THAN {
|
||||
@Override
|
||||
|
@ -512,6 +512,14 @@ <R> JpaCompoundSelection<R> tuple(
|
||||
@Override
|
||||
JpaPredicate notEqual(Expression<?> x, Object y);
|
||||
|
||||
JpaPredicate distinctFrom(Expression<?> x, Expression<?> y);
|
||||
|
||||
JpaPredicate distinctFrom(Expression<?> x, Object y);
|
||||
|
||||
JpaPredicate notDistinctFrom(Expression<?> x, Expression<?> y);
|
||||
|
||||
JpaPredicate notDistinctFrom(Expression<?> x, Object y);
|
||||
|
||||
@Override
|
||||
<Y extends Comparable<? super Y>> JpaPredicate greaterThan(
|
||||
Expression<? extends Y> x,
|
||||
|
@ -1624,27 +1624,28 @@ public SqmEmptinessPredicate visitIsEmptyPredicate(HqlParser.IsEmptyPredicateCon
|
||||
|
||||
@Override
|
||||
public Object visitComparisonOperator(HqlParser.ComparisonOperatorContext ctx) {
|
||||
if ( ctx.EQUAL()!=null ) {
|
||||
return ComparisonOperator.EQUAL;
|
||||
}
|
||||
else if ( ctx.NOT_EQUAL()!=null ) {
|
||||
return ComparisonOperator.NOT_EQUAL;
|
||||
}
|
||||
else if ( ctx.LESS()!=null ) {
|
||||
return ComparisonOperator.LESS_THAN;
|
||||
}
|
||||
else if ( ctx.LESS_EQUAL()!=null ) {
|
||||
return ComparisonOperator.LESS_THAN_OR_EQUAL;
|
||||
}
|
||||
else if ( ctx.GREATER()!=null ) {
|
||||
return ComparisonOperator.GREATER_THAN;
|
||||
}
|
||||
else if ( ctx.GREATER_EQUAL()!=null ) {
|
||||
return ComparisonOperator.GREATER_THAN_OR_EQUAL;
|
||||
}
|
||||
else {
|
||||
throw new QueryException("missing operator");
|
||||
final TerminalNode firstToken = (TerminalNode) ctx.getChild( 0 );
|
||||
switch ( firstToken.getSymbol().getType() ) {
|
||||
case HqlLexer.EQUAL:
|
||||
return ComparisonOperator.EQUAL;
|
||||
case HqlLexer.NOT_EQUAL:
|
||||
return ComparisonOperator.NOT_EQUAL;
|
||||
case HqlLexer.LESS:
|
||||
return ComparisonOperator.LESS_THAN;
|
||||
case HqlLexer.LESS_EQUAL:
|
||||
return ComparisonOperator.LESS_THAN_OR_EQUAL;
|
||||
case HqlLexer.GREATER:
|
||||
return ComparisonOperator.GREATER_THAN;
|
||||
case HqlLexer.GREATER_EQUAL:
|
||||
return ComparisonOperator.GREATER_THAN_OR_EQUAL;
|
||||
case HqlLexer.IS: {
|
||||
final TerminalNode secondToken = (TerminalNode) ctx.getChild( 1 );
|
||||
return secondToken.getSymbol().getType() == HqlLexer.NOT
|
||||
? ComparisonOperator.NOT_DISTINCT_FROM
|
||||
: ComparisonOperator.DISTINCT_FROM;
|
||||
}
|
||||
}
|
||||
throw new QueryException("missing operator");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1657,7 +1658,9 @@ public SqmPredicate visitComparisonPredicate(HqlParser.ComparisonPredicateContex
|
||||
final HqlParser.ExpressionContext rightExpressionContext = expressionContexts.get( 1 );
|
||||
switch (comparisonOperator) {
|
||||
case EQUAL:
|
||||
case NOT_EQUAL: {
|
||||
case NOT_EQUAL:
|
||||
case DISTINCT_FROM:
|
||||
case NOT_DISTINCT_FROM: {
|
||||
Map<Class<?>, Enum<?>> possibleEnumValues;
|
||||
if ( ( possibleEnumValues = getPossibleEnumValues( leftExpressionContext ) ) != null ) {
|
||||
right = (SqmExpression) rightExpressionContext.accept( this );
|
||||
@ -1683,14 +1686,16 @@ else if ( ( possibleEnumValues = getPossibleEnumValues( rightExpressionContext )
|
||||
if ( left instanceof SqmLiteralNull<?> ) {
|
||||
return new SqmNullnessPredicate(
|
||||
right,
|
||||
comparisonOperator == ComparisonOperator.NOT_EQUAL,
|
||||
comparisonOperator == ComparisonOperator.NOT_EQUAL
|
||||
|| comparisonOperator == ComparisonOperator.DISTINCT_FROM,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
else if ( right instanceof SqmLiteralNull<?> ) {
|
||||
return new SqmNullnessPredicate(
|
||||
left,
|
||||
comparisonOperator == ComparisonOperator.NOT_EQUAL,
|
||||
comparisonOperator == ComparisonOperator.NOT_EQUAL
|
||||
|| comparisonOperator == ComparisonOperator.DISTINCT_FROM,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -466,6 +466,18 @@ <R> SqmTuple<R> tuple(
|
||||
@Override
|
||||
SqmPredicate notEqual(Expression<?> x, Object y);
|
||||
|
||||
@Override
|
||||
SqmPredicate distinctFrom(Expression<?> x, Expression<?> y);
|
||||
|
||||
@Override
|
||||
SqmPredicate distinctFrom(Expression<?> x, Object y);
|
||||
|
||||
@Override
|
||||
SqmPredicate notDistinctFrom(Expression<?> x, Expression<?> y);
|
||||
|
||||
@Override
|
||||
SqmPredicate notDistinctFrom(Expression<?> x, Object y);
|
||||
|
||||
@Override
|
||||
<Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y);
|
||||
|
||||
|
@ -1710,6 +1710,46 @@ public SqmPredicate notEqual(Expression<?> x, Object y) {
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Expression<?> y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
(SqmExpression<?>) y,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate distinctFrom(Expression<?> x, Object y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.DISTINCT_FROM,
|
||||
value( y ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Expression<?> y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
(SqmExpression<?>) y,
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate notDistinctFrom(Expression<?> x, Object y) {
|
||||
return new SqmComparisonPredicate(
|
||||
(SqmExpression<?>) x,
|
||||
ComparisonOperator.NOT_DISTINCT_FROM,
|
||||
value( y ),
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <Y extends Comparable<? super Y>> SqmPredicate greaterThan(Expression<? extends Y> x, Expression<? extends Y> y) {
|
||||
return new SqmComparisonPredicate(
|
||||
|
@ -411,6 +411,12 @@ else if ( expression instanceof JdbcParameter ) {
|
||||
}
|
||||
return (R) getParameterBindValue( (JdbcParameter) expression );
|
||||
}
|
||||
else if ( expression instanceof SqmParameterInterpretation ) {
|
||||
if ( jdbcParameterBindings == null ) {
|
||||
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available!" );
|
||||
}
|
||||
return (R) getParameterBindValue( (JdbcParameter) ( (SqmParameterInterpretation) expression).getResolvedExpression() );
|
||||
}
|
||||
throw new UnsupportedOperationException( "Can't interpret expression: " + expression );
|
||||
}
|
||||
|
||||
@ -427,6 +433,14 @@ else if ( expression instanceof JdbcParameter ) {
|
||||
renderAsLiteral( parameter, getParameterBindValue( parameter ) );
|
||||
return;
|
||||
}
|
||||
else if ( expression instanceof SqmParameterInterpretation ) {
|
||||
if ( jdbcParameterBindings == null ) {
|
||||
throw new IllegalArgumentException( "Can't interpret expression because no parameter bindings are available!" );
|
||||
}
|
||||
final JdbcParameter parameter = (JdbcParameter) ( (SqmParameterInterpretation) expression).getResolvedExpression();
|
||||
renderAsLiteral( parameter, getParameterBindValue( parameter ) );
|
||||
return;
|
||||
}
|
||||
throw new UnsupportedOperationException( "Can't render expression as literal: " + expression );
|
||||
}
|
||||
|
||||
@ -1219,56 +1233,15 @@ protected final void visitPartitionExpressions(List<Expression> partitionExpress
|
||||
}
|
||||
|
||||
protected void renderPartitionItem(Expression expression) {
|
||||
// We render an empty group instead of literals as some DBs don't support grouping by literals
|
||||
// Note that integer literals, which refer to select item positions, are handled in #visitGroupByClause
|
||||
if ( expression instanceof Literal ) {
|
||||
switch ( dialect.getGroupByConstantRenderingStrategy() ) {
|
||||
case CONSTANT:
|
||||
appendSql( "'0'" );
|
||||
break;
|
||||
case CONSTANT_EXPRESSION:
|
||||
appendSql( "'0' || '0'" );
|
||||
break;
|
||||
case EMPTY_GROUPING:
|
||||
appendSql( "()" );
|
||||
break;
|
||||
case SUBQUERY:
|
||||
appendSql( "(select 1" );
|
||||
final String fromDual = dialect.getFromDual();
|
||||
if ( !fromDual.isEmpty() ) {
|
||||
appendSql( " " );
|
||||
appendSql( fromDual );
|
||||
}
|
||||
appendSql( ')' );
|
||||
break;
|
||||
case COLUMN_REFERENCE:
|
||||
// todo (6.0): We need to introduce a dummy from clause item
|
||||
// String fromItem = ", (select 1 x " + dialect.getFromDual() + ") dummy";
|
||||
// sqlBuffer.insert( fromEndIndex, fromItem );
|
||||
// appendSql( "dummy.x" );
|
||||
throw new UnsupportedOperationException( "Column reference strategy is not yet implemented!" );
|
||||
}
|
||||
appendSql( "()" );
|
||||
}
|
||||
else if ( expression instanceof Summarization ) {
|
||||
Summarization summarization = (Summarization) expression;
|
||||
switch ( dialect.getGroupBySummarizationRenderingStrategy() ) {
|
||||
case FUNCTION:
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
break;
|
||||
case CLAUSE:
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( " with " );
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
break;
|
||||
default:
|
||||
// This could theoretically be emulated by rendering all grouping variations of the query and
|
||||
// connect them via union all but that's probably pretty inefficient and would have to happen
|
||||
// on the query spec level
|
||||
throw new UnsupportedOperationException( "Summarization is not supported by DBMS!" );
|
||||
}
|
||||
appendSql( summarization.getKind().name().toLowerCase() );
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
renderCommaSeparated( summarization.getGroupings() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
@ -1331,8 +1304,8 @@ protected void renderOrderBy(boolean addWhitespace, List<SortSpecification> sort
|
||||
* For <code>(a, b, c) > (1, 2, 3)</code> we use the broad predicate <code>a >= 1</code> and then want to remove rows where <code>a = 1 and (b, c) <= (2, 3)</code>
|
||||
*/
|
||||
protected void emulateTupleComparison(
|
||||
final List<? extends Expression> lhsExpressions,
|
||||
final List<? extends Expression> rhsExpressions,
|
||||
final List<? extends SqlAstNode> lhsExpressions,
|
||||
final List<? extends SqlAstNode> rhsExpressions,
|
||||
ComparisonOperator operator,
|
||||
boolean indexOptimized) {
|
||||
final boolean isCurrentWhereClause = clauseStack.getCurrent() == Clause.WHERE;
|
||||
@ -1343,6 +1316,18 @@ protected void emulateTupleComparison(
|
||||
final int size = lhsExpressions.size();
|
||||
assert size == rhsExpressions.size();
|
||||
switch ( operator ) {
|
||||
case DISTINCT_FROM:
|
||||
appendSql( "not " );
|
||||
case NOT_DISTINCT_FROM: {
|
||||
appendSql( "exists (select " );
|
||||
renderCommaSeparatedSelectExpression( lhsExpressions );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
appendSql( " intersect select " );
|
||||
renderCommaSeparatedSelectExpression( rhsExpressions );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
appendSql( ")" );
|
||||
break;
|
||||
}
|
||||
case EQUAL:
|
||||
case NOT_EQUAL: {
|
||||
final String operatorText = operator.sqlText();
|
||||
@ -1406,12 +1391,8 @@ protected void renderExpressionsAsSubquery(final List<? extends Expression> expr
|
||||
try {
|
||||
appendSql( "select " );
|
||||
|
||||
renderCommaSeparated( expressions );
|
||||
final String fromDual = dialect.getFromDual();
|
||||
if ( !fromDual.isEmpty() ) {
|
||||
appendSql( " " );
|
||||
appendSql( fromDual );
|
||||
}
|
||||
renderCommaSeparatedSelectExpression( expressions );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
}
|
||||
finally {
|
||||
clauseStack.pop();
|
||||
@ -1419,8 +1400,8 @@ protected void renderExpressionsAsSubquery(final List<? extends Expression> expr
|
||||
}
|
||||
|
||||
private void emulateTupleComparisonSimple(
|
||||
final List<? extends Expression> lhsExpressions,
|
||||
final List<? extends Expression> rhsExpressions,
|
||||
final List<? extends SqlAstNode> lhsExpressions,
|
||||
final List<? extends SqlAstNode> rhsExpressions,
|
||||
final String operatorText,
|
||||
final String finalOperatorText,
|
||||
final boolean optimized) {
|
||||
@ -1478,30 +1459,118 @@ private void emulateTupleComparisonSimple(
|
||||
}
|
||||
|
||||
protected void renderSelectTupleComparison(final List<SqlSelection> lhsExpressions, SqlTuple tuple, ComparisonOperator operator) {
|
||||
if ( dialect.supportsRowValueConstructorSyntax() ) {
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( SqlSelection lhsExpression : lhsExpressions ) {
|
||||
appendSql( separator );
|
||||
lhsExpression.getExpression().accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
tuple.accept( this );
|
||||
}
|
||||
else {
|
||||
final List<Expression> lhs = new ArrayList<>( lhsExpressions.size() );
|
||||
for ( SqlSelection lhsExpression : lhsExpressions ) {
|
||||
lhs.add( lhsExpression.getExpression() );
|
||||
}
|
||||
renderTupleComparisonStandard( lhsExpressions, tuple, operator );
|
||||
}
|
||||
|
||||
emulateTupleComparison( lhs, tuple.getExpressions(), operator, true );
|
||||
protected void renderTupleComparisonStandard(
|
||||
final List<SqlSelection> lhsExpressions,
|
||||
SqlTuple tuple,
|
||||
ComparisonOperator operator) {
|
||||
appendSql( OPEN_PARENTHESIS );
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( SqlSelection lhsExpression : lhsExpressions ) {
|
||||
appendSql( separator );
|
||||
lhsExpression.getExpression().accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
tuple.accept( this );
|
||||
}
|
||||
|
||||
protected void renderComparison(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
renderComparisonStandard( lhs, operator, rhs );
|
||||
}
|
||||
|
||||
protected void renderComparisonStandard(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
lhs.accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
rhs.accept( this );
|
||||
}
|
||||
|
||||
protected void renderComparisonDistinctOperator(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
final boolean notWrapper;
|
||||
final String operatorText;
|
||||
switch ( operator ) {
|
||||
case DISTINCT_FROM:
|
||||
notWrapper = true;
|
||||
operatorText = "<=>";
|
||||
break;
|
||||
case NOT_DISTINCT_FROM:
|
||||
notWrapper = false;
|
||||
operatorText = "<=>";
|
||||
break;
|
||||
default:
|
||||
notWrapper = false;
|
||||
operatorText = operator.sqlText();
|
||||
break;
|
||||
}
|
||||
if ( notWrapper ) {
|
||||
appendSql( "not(" );
|
||||
}
|
||||
lhs.accept( this );
|
||||
appendSql( ' ' );
|
||||
appendSql( operatorText );
|
||||
appendSql( ' ' );
|
||||
rhs.accept( this );
|
||||
if ( notWrapper ) {
|
||||
appendSql( ')' );
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderComparisonEmulateDecode(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
switch ( operator ) {
|
||||
case DISTINCT_FROM:
|
||||
appendSql( "decode(" );
|
||||
lhs.accept( this );
|
||||
appendSql( ',' );
|
||||
rhs.accept( this );
|
||||
appendSql( ",0,1)=1" );
|
||||
break;
|
||||
case NOT_DISTINCT_FROM:
|
||||
appendSql( "decode(" );
|
||||
lhs.accept( this );
|
||||
appendSql( ',' );
|
||||
rhs.accept( this );
|
||||
appendSql( ",0,1)=0" );
|
||||
break;
|
||||
default:
|
||||
lhs.accept( this );
|
||||
appendSql( ' ' );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( ' ' );
|
||||
rhs.accept( this );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void renderComparisonEmulateIntersect(Expression lhs, ComparisonOperator operator, Expression rhs) {
|
||||
switch ( operator ) {
|
||||
case DISTINCT_FROM:
|
||||
appendSql( "not " );
|
||||
case NOT_DISTINCT_FROM: {
|
||||
appendSql( "exists (select " );
|
||||
clauseStack.push( Clause.SELECT );
|
||||
renderSelectExpression( lhs );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
appendSql( " intersect select " );
|
||||
renderSelectExpression( rhs );
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
clauseStack.pop();
|
||||
appendSql( ")" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
lhs.accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
rhs.accept( this );
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// ORDER BY clause
|
||||
@ -2414,26 +2483,14 @@ protected List<SortSpecification> getSortSpecificationsRowNumbering(
|
||||
|
||||
@Override
|
||||
public void visitSqlSelection(SqlSelection sqlSelection) {
|
||||
final Expression expression = sqlSelection.getExpression();
|
||||
// Null literals have to be casted in the select clause
|
||||
if ( expression instanceof Literal ) {
|
||||
final Literal literal = (Literal) expression;
|
||||
if ( literal.getLiteralValue() == null ) {
|
||||
renderNullCast( literal );
|
||||
}
|
||||
else {
|
||||
renderLiteral( literal, dialect.requiresCastingOfParametersInSelectClause() );
|
||||
}
|
||||
}
|
||||
else if ( expression instanceof NullnessLiteral ) {
|
||||
renderNullCast( expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
renderSelectExpression( sqlSelection.getExpression() );
|
||||
}
|
||||
|
||||
protected void renderNullCast(Expression expression) {
|
||||
protected void renderSelectExpression(Expression expression) {
|
||||
expression.accept( this );
|
||||
}
|
||||
|
||||
protected void renderCasted(Expression expression) {
|
||||
final List<SqlAstNode> arguments = new ArrayList<>( 2 );
|
||||
arguments.add( expression );
|
||||
arguments.add( new CastTarget( (BasicValuedMapping) expression.getExpressionType() ) );
|
||||
@ -2482,10 +2539,7 @@ protected void renderLiteral(Literal literal, boolean castParameter) {
|
||||
@Override
|
||||
public void visitFromClause(FromClause fromClause) {
|
||||
if ( fromClause == null || fromClause.getRoots().isEmpty() ) {
|
||||
if ( !getDialect().supportsSelectQueryWithoutFromClause() ) {
|
||||
appendSql( " " );
|
||||
appendSql( getDialect().getFromDual() );
|
||||
}
|
||||
appendSql( getFromDualForSelectOnly() );
|
||||
}
|
||||
else {
|
||||
appendSql( " from " );
|
||||
@ -2857,15 +2911,29 @@ public void visitTuple(SqlTuple tuple) {
|
||||
}
|
||||
}
|
||||
|
||||
private void renderCommaSeparated(Iterable<? extends Expression> expressions) {
|
||||
protected final void renderCommaSeparated(Iterable<? extends SqlAstNode> expressions) {
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : expressions ) {
|
||||
for ( SqlAstNode expression : expressions ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
protected final void renderCommaSeparatedSelectExpression(Iterable<? extends SqlAstNode> expressions) {
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( SqlAstNode expression : expressions ) {
|
||||
appendSql( separator );
|
||||
if ( expression instanceof Expression ) {
|
||||
renderSelectExpression( (Expression) expression );
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
}
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCollate(Collate collate) {
|
||||
collate.getExpression().accept( this );
|
||||
@ -3381,12 +3449,12 @@ public void visitInListPredicate(InListPredicate inListPredicate) {
|
||||
}
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
else if ( !dialect.supportsRowValueConstructorSyntaxInInList() ) {
|
||||
else if ( !supportsRowValueConstructorSyntaxInInList() ) {
|
||||
final ComparisonOperator comparisonOperator = inListPredicate.isNegated() ?
|
||||
ComparisonOperator.NOT_EQUAL :
|
||||
ComparisonOperator.EQUAL;
|
||||
// Some DBs like Oracle support tuples only for the IN subquery predicate
|
||||
if ( dialect.supportsRowValueConstructorSyntaxInInSubquery() && dialect.supportsUnionAll() ) {
|
||||
if ( supportsRowValueConstructorSyntaxInInSubQuery() && dialect.supportsUnionAll() ) {
|
||||
inListPredicate.getTestExpression().accept( this );
|
||||
if ( inListPredicate.isNegated() ) {
|
||||
appendSql( " not" );
|
||||
@ -3469,7 +3537,7 @@ public void visitInSubQueryPredicate(InSubQueryPredicate inSubQueryPredicate) {
|
||||
appendSql( " in " );
|
||||
inSubQueryPredicate.getSubQuery().accept( this );
|
||||
}
|
||||
else if ( !dialect.supportsRowValueConstructorSyntaxInInSubquery() ) {
|
||||
else if ( !supportsRowValueConstructorSyntaxInInSubQuery() ) {
|
||||
emulateTupleSubQueryPredicate(
|
||||
inSubQueryPredicate,
|
||||
inSubQueryPredicate.isNegated(),
|
||||
@ -3582,7 +3650,7 @@ protected void emulateTupleSubQueryPredicate(
|
||||
}
|
||||
|
||||
/**
|
||||
* An optimized emulation for relational tuple subquery comparisons.
|
||||
* An optimized emulation for relational tuple sub-query comparisons.
|
||||
* The idea of this method is to use limit 1 to select the max or min tuple and only compare against that.
|
||||
*/
|
||||
protected void emulateQuantifiedTupleSubQueryPredicate(
|
||||
@ -3593,7 +3661,7 @@ protected void emulateQuantifiedTupleSubQueryPredicate(
|
||||
final QuerySpec subQuery;
|
||||
if ( queryPart instanceof QuerySpec && queryPart.getFetchClauseExpression() == null && queryPart.getOffsetClauseExpression() == null ) {
|
||||
subQuery = (QuerySpec) queryPart;
|
||||
// We can only emulate the tuple sub query predicate as exists predicate when there are no limit/offsets
|
||||
// We can only emulate the tuple sub query predicate comparing against the top element when there are no limit/offsets
|
||||
lhsTuple.accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( tupleComparisonOperator.sqlText() );
|
||||
@ -3656,15 +3724,14 @@ public void visitJunction(Junction junction) {
|
||||
return;
|
||||
}
|
||||
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Predicate predicate : junction.getPredicates() ) {
|
||||
appendSql( separator );
|
||||
predicate.accept( this );
|
||||
if ( separator == NO_SEPARATOR ) {
|
||||
separator = junction.getNature() == Junction.Nature.CONJUNCTION
|
||||
final String separator = junction.getNature() == Junction.Nature.CONJUNCTION
|
||||
? " and "
|
||||
: " or ";
|
||||
}
|
||||
final List<Predicate> predicates = junction.getPredicates();
|
||||
predicates.get( 0 ).accept( this );
|
||||
for ( int i = 1; i < predicates.size(); i++ ) {
|
||||
appendSql( separator );
|
||||
predicates.get( i ).accept( this );
|
||||
}
|
||||
}
|
||||
|
||||
@ -3763,42 +3830,48 @@ else if ( rhsExpression instanceof Any ) {
|
||||
final ComparisonOperator operator = comparisonPredicate.getOperator();
|
||||
if ( lhsTuple.getExpressions().size() == 1 ) {
|
||||
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
|
||||
lhsTuple.getExpressions().get( 0 ).accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
if ( subquery == null ) {
|
||||
getTuple( comparisonPredicate.getRightHandExpression() ).getExpressions().get( 0 ).accept( this );
|
||||
renderComparison(
|
||||
lhsTuple.getExpressions().get( 0 ),
|
||||
operator,
|
||||
getTuple( comparisonPredicate.getRightHandExpression() ).getExpressions().get( 0 )
|
||||
);
|
||||
}
|
||||
else {
|
||||
rhsExpression.accept( this );
|
||||
renderComparison( lhsTuple.getExpressions().get( 0 ), operator, rhsExpression );
|
||||
}
|
||||
}
|
||||
else if ( subquery != null && !dialect.supportsRowValueConstructorSyntaxInQuantifiedPredicates() ) {
|
||||
else if ( subquery != null && !supportsRowValueConstructorSyntaxInQuantifiedPredicates() ) {
|
||||
// For quantified relational comparisons, we can do an optimized emulation
|
||||
if ( all && operator != ComparisonOperator.EQUAL && operator != ComparisonOperator.NOT_EQUAL && dialect.supportsRowValueConstructorSyntax() ) {
|
||||
emulateQuantifiedTupleSubQueryPredicate(
|
||||
comparisonPredicate,
|
||||
subquery,
|
||||
lhsTuple,
|
||||
operator
|
||||
);
|
||||
}
|
||||
else {
|
||||
emulateTupleSubQueryPredicate(
|
||||
comparisonPredicate,
|
||||
all,
|
||||
subquery,
|
||||
lhsTuple,
|
||||
all ? operator.negated() : operator
|
||||
);
|
||||
if ( supportsRowValueConstructorSyntax() && all ) {
|
||||
switch ( operator ) {
|
||||
case LESS_THAN:
|
||||
case LESS_THAN_OR_EQUAL:
|
||||
case GREATER_THAN:
|
||||
case GREATER_THAN_OR_EQUAL: {
|
||||
emulateQuantifiedTupleSubQueryPredicate(
|
||||
comparisonPredicate,
|
||||
subquery,
|
||||
lhsTuple,
|
||||
operator
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
emulateTupleSubQueryPredicate(
|
||||
comparisonPredicate,
|
||||
all,
|
||||
subquery,
|
||||
lhsTuple,
|
||||
all ? operator.negated() : operator
|
||||
);
|
||||
}
|
||||
else if ( !dialect.supportsRowValueConstructorSyntax() ) {
|
||||
else if ( !supportsRowValueConstructorSyntax() ) {
|
||||
rhsTuple = getTuple( rhsExpression );
|
||||
assert rhsTuple != null;
|
||||
// Some DBs like Oracle support tuples only for the IN subquery predicate
|
||||
if ( ( operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL ) && dialect.supportsRowValueConstructorSyntaxInInSubquery() ) {
|
||||
if ( ( operator == ComparisonOperator.EQUAL || operator == ComparisonOperator.NOT_EQUAL ) && supportsRowValueConstructorSyntaxInInSubQuery() ) {
|
||||
comparisonPredicate.getLeftHandExpression().accept( this );
|
||||
if ( operator == ComparisonOperator.NOT_EQUAL ) {
|
||||
appendSql( " not" );
|
||||
@ -3817,11 +3890,7 @@ else if ( !dialect.supportsRowValueConstructorSyntax() ) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
comparisonPredicate.getLeftHandExpression().accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( operator.sqlText() );
|
||||
appendSql( " " );
|
||||
rhsExpression.accept( this );
|
||||
renderComparison( comparisonPredicate.getLeftHandExpression(), operator, rhsExpression );
|
||||
}
|
||||
}
|
||||
else if ( ( rhsTuple = getTuple( comparisonPredicate.getRightHandExpression() ) ) != null ) {
|
||||
@ -3832,18 +3901,18 @@ else if ( ( rhsTuple = getTuple( comparisonPredicate.getRightHandExpression() )
|
||||
|
||||
if ( rhsTuple.getExpressions().size() == 1 ) {
|
||||
// Special case for tuples with arity 1 as any DBMS supports scalar IN predicates
|
||||
lhsExpression.accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( comparisonPredicate.getOperator().sqlText() );
|
||||
appendSql( " " );
|
||||
rhsTuple.getExpressions().get( 0 ).accept( this );
|
||||
renderComparison(
|
||||
lhsExpression,
|
||||
comparisonPredicate.getOperator(),
|
||||
rhsTuple.getExpressions().get( 0 )
|
||||
);
|
||||
}
|
||||
else if ( dialect.supportsRowValueConstructorSyntax() ) {
|
||||
lhsExpression.accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( comparisonPredicate.getOperator().sqlText() );
|
||||
appendSql( " " );
|
||||
comparisonPredicate.getRightHandExpression().accept( this );
|
||||
else if ( supportsRowValueConstructorSyntax() ) {
|
||||
renderComparison(
|
||||
lhsExpression,
|
||||
comparisonPredicate.getOperator(),
|
||||
comparisonPredicate.getRightHandExpression()
|
||||
);
|
||||
}
|
||||
else {
|
||||
emulateTupleSubQueryPredicate(
|
||||
@ -3862,12 +3931,93 @@ else if ( dialect.supportsRowValueConstructorSyntax() ) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
comparisonPredicate.getLeftHandExpression().accept( this );
|
||||
appendSql( " " );
|
||||
appendSql( comparisonPredicate.getOperator().sqlText() );
|
||||
appendSql( " " );
|
||||
comparisonPredicate.getRightHandExpression().accept( this );
|
||||
renderComparison(
|
||||
comparisonPredicate.getLeftHandExpression(),
|
||||
comparisonPredicate.getOperator(),
|
||||
comparisonPredicate.getRightHandExpression()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected boolean supportsRowValueConstructorSyntax() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected 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.
|
||||
*/
|
||||
protected boolean supportsRowValueConstructorSyntaxInQuantifiedPredicates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected boolean supportsRowValueConstructorSyntaxInInList() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the dialect supports {@link #supportsRowValueConstructorSyntax() row values},
|
||||
* does it offer such support in IN subqueries as well?
|
||||
* <p/>
|
||||
* For example, "... where (FIRST_NAME, LAST_NAME) IN ( select ... ) ..."
|
||||
*
|
||||
* @return True if this SQL dialect is known to support "row value
|
||||
* constructor" syntax in the IN subqueries; false otherwise.
|
||||
*/
|
||||
protected boolean supportsRowValueConstructorSyntaxInInSubQuery() {
|
||||
return supportsRowValueConstructorSyntaxInInList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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}.
|
||||
*/
|
||||
protected String getFromDual() {
|
||||
return " from (values (0)) as dual";
|
||||
}
|
||||
|
||||
protected String getFromDualForSelectOnly() {
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
|
||||
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
|
||||
@ -28,7 +29,7 @@
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqlSelection {
|
||||
public interface SqlSelection extends SqlAstNode {
|
||||
/**
|
||||
* Get the extractor that can be used to extract JDBC values for this selection
|
||||
*/
|
||||
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
public class ComparisonPredicate implements Predicate {
|
||||
private final Expression leftHandExpression;
|
||||
private ComparisonOperator operator;
|
||||
private final ComparisonOperator operator;
|
||||
private final Expression rightHandExpression;
|
||||
|
||||
public ComparisonPredicate(
|
||||
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.orm.test.query.hql;
|
||||
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.ServiceRegistry;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
@ServiceRegistry
|
||||
@DomainModel(standardModels = StandardDomainModel.GAMBIT)
|
||||
@SessionFactory
|
||||
public class DistinctFromTest {
|
||||
|
||||
@BeforeAll
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
em -> {
|
||||
EntityOfBasics entity1 = new EntityOfBasics();
|
||||
entity1.setId( 123 );
|
||||
em.persist( entity1 );
|
||||
EntityOfBasics entity = new EntityOfBasics();
|
||||
entity.setId( 456 );
|
||||
entity.setTheString( "abc" );
|
||||
em.persist( entity );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDistinctFrom(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
Assertions.assertEquals(
|
||||
456,
|
||||
session.createQuery(
|
||||
"select e.id from EntityOfBasics e where e.theString is distinct from :param",
|
||||
Integer.class
|
||||
)
|
||||
.setParameter( "param", null )
|
||||
.list()
|
||||
.get( 0 )
|
||||
);
|
||||
Assertions.assertEquals(
|
||||
123,
|
||||
session.createQuery(
|
||||
"select e.id from EntityOfBasics e where e.theString is distinct from :param",
|
||||
Integer.class
|
||||
)
|
||||
.setParameter( "param", "abc" )
|
||||
.list()
|
||||
.get( 0 )
|
||||
);
|
||||
Assertions.assertEquals(
|
||||
123,
|
||||
session.createQuery(
|
||||
"select e.id from EntityOfBasics e where e.theString is not distinct from :param",
|
||||
Integer.class
|
||||
)
|
||||
.setParameter( "param", null )
|
||||
.list()
|
||||
.get( 0 )
|
||||
);
|
||||
Assertions.assertEquals(
|
||||
456,
|
||||
session.createQuery(
|
||||
"select e.id from EntityOfBasics e where e.theString is not distinct from :param",
|
||||
Integer.class
|
||||
)
|
||||
.setParameter( "param", "abc" )
|
||||
.list()
|
||||
.get( 0 )
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -53,8 +53,8 @@ public void setUp(SessionFactoryScope scope) {
|
||||
@AfterEach
|
||||
public void tearDown(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
sesison ->
|
||||
sesison.createQuery( "delete from EmbeddedIdEntity" ).executeUpdate()
|
||||
session ->
|
||||
session.createQuery( "delete from EmbeddedIdEntity" ).executeUpdate()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.RequiresDialect;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
@ -214,7 +215,7 @@ public void testComponentFormulaQuery() {
|
||||
// .add( Property.forName("person.yob").between( new Integer(1999), new Integer(2002) ) )
|
||||
// .list();
|
||||
|
||||
if ( getDialect().supportsRowValueConstructorSyntax() ) {
|
||||
if ( new DialectChecks.SupportsRowValueConstructorSyntaxCheck().isMatch( getDialect() ) ) {
|
||||
s.createQuery("from User u where u.person = ('gavin', :dob, 'Peachtree Rd', 'Karbarook Ave', 1974, 34, 'Peachtree Rd')")
|
||||
.setParameter("dob", new Date("March 25, 1974")).list();
|
||||
s.createQuery("from User where person = ('gavin', :dob, 'Peachtree Rd', 'Karbarook Ave', 1974, 34, 'Peachtree Rd')")
|
||||
|
@ -13,6 +13,7 @@
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import org.hibernate.testing.DialectChecks;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@ -54,7 +55,7 @@ public void testHqlIdPropertyReferences() {
|
||||
count = extractCount( s, "select count(*) from LineItem l where l.id = '456'" );
|
||||
assertEquals( "LineItem by id prop (non-identifier", 1, count );
|
||||
|
||||
if ( getDialect().supportsRowValueConstructorSyntax() ) {
|
||||
if ( new DialectChecks.SupportsRowValueConstructorSyntaxCheck().isMatch( getDialect() ) ) {
|
||||
Query q = s.createQuery( "select count(*) from LineItem l where l.pk = (:order, :product)" )
|
||||
.setParameter( "order", o )
|
||||
.setParameter( "product", "my-product" );
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
package org.hibernate.testing;
|
||||
|
||||
import org.hibernate.dialect.AbstractHANADialect;
|
||||
import org.hibernate.dialect.CockroachDialect;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
@ -17,6 +18,7 @@
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||
import org.hibernate.dialect.PostgreSQLDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.dialect.TeradataDialect;
|
||||
import org.hibernate.dialect.TimesTenDialect;
|
||||
@ -132,7 +134,10 @@ public boolean isMatch(Dialect dialect) {
|
||||
|
||||
public static class SupportsRowValueConstructorSyntaxCheck implements DialectCheck {
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
return dialect.supportsRowValueConstructorSyntax();
|
||||
return dialect instanceof AbstractHANADialect
|
||||
|| dialect instanceof CockroachDialect
|
||||
|| dialect instanceof MySQLDialect
|
||||
|| dialect instanceof PostgreSQLDialect;
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,12 +208,6 @@ public boolean isMatch(Dialect dialect) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class DoesNotSupportRowValueConstructorSyntax implements DialectCheck {
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
return dialect.supportsRowValueConstructorSyntax() == false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DoesNotSupportFollowOnLocking implements DialectCheck {
|
||||
public boolean isMatch(Dialect dialect) {
|
||||
return !dialect.useFollowOnLocking( null, null );
|
||||
|
@ -137,7 +137,10 @@ public boolean apply(Dialect dialect) {
|
||||
|
||||
public static class SupportsRowValueConstructorSyntaxCheck implements DialectFeatureCheck {
|
||||
public boolean apply(Dialect dialect) {
|
||||
return dialect.supportsRowValueConstructorSyntax();
|
||||
return dialect instanceof AbstractHANADialect
|
||||
|| dialect instanceof CockroachDialect
|
||||
|| dialect instanceof MySQLDialect
|
||||
|| dialect instanceof PostgreSQLDialect;
|
||||
}
|
||||
}
|
||||
|
||||
@ -240,18 +243,22 @@ public boolean apply(Dialect dialect) {
|
||||
|
||||
public static class SupportsGroupByRollup implements DialectFeatureCheck {
|
||||
public boolean apply(Dialect dialect) {
|
||||
return dialect.getGroupBySummarizationRenderingStrategy() != GroupBySummarizationRenderingStrategy.NONE;
|
||||
return dialect instanceof DB2Dialect
|
||||
|| dialect instanceof OracleDialect
|
||||
|| dialect instanceof PostgreSQLDialect && dialect.getVersion() >= 950
|
||||
|| dialect instanceof SQLServerDialect
|
||||
|| dialect instanceof DerbyDialect
|
||||
|| dialect instanceof MySQLDialect
|
||||
|| dialect instanceof MariaDBDialect;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SupportsGroupByGroupingSets implements DialectFeatureCheck {
|
||||
public boolean apply(Dialect dialect) {
|
||||
return dialect.getGroupBySummarizationRenderingStrategy() != GroupBySummarizationRenderingStrategy.NONE
|
||||
&& !( dialect instanceof DerbyDialect )
|
||||
// MariaDB only supports ROLLUP
|
||||
&& !( dialect instanceof MariaDBDialect )
|
||||
// MySQL only supports ROLLUP
|
||||
&& !( dialect instanceof MySQLDialect );
|
||||
return dialect instanceof DB2Dialect
|
||||
|| dialect instanceof OracleDialect
|
||||
|| dialect instanceof PostgreSQLDialect && dialect.getVersion() >= 950
|
||||
|| dialect instanceof SQLServerDialect;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user