Fix a few more test issues and handle group by summarization rendering strategies as well as group by literal rendering strategies
This commit is contained in:
parent
a57f93b14a
commit
c4673e5a5c
|
@ -1538,4 +1538,9 @@ public abstract class AbstractHANADialect extends Dialect {
|
|||
protected abstract boolean supportsAsciiStringTypes();
|
||||
|
||||
protected abstract Boolean useUnicodeStringTypesDefault();
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import org.hibernate.query.spi.QueryEngine;
|
|||
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
|
@ -217,14 +218,24 @@ abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
return "select getdate()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType entityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( entityDescriptor, basename -> "#" + basename, this ),
|
||||
() -> new TempIdTableExporter( true, this::getTypeName ) {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
return "create table";
|
||||
}
|
||||
},
|
||||
// // sql-server, at least needed this dropped after use; strange!
|
||||
this::getTypeName,
|
||||
AfterUseAction.DROP,
|
||||
TempTableDdlTransactionHandling.NONE,
|
||||
runtimeModelCreationContext.getSessionFactory()
|
||||
|
|
|
@ -698,8 +698,13 @@ public class DB2Dialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return true;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.FUNCTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -766,7 +766,7 @@ public class DerbyDialect extends Dialect {
|
|||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new LocalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, basename -> "HT_" + basename, this ),
|
||||
new IdTable( rootEntityDescriptor, basename -> "session.HT_" + basename, this ),
|
||||
() -> new TempIdTableExporter( true, this::getTypeName ) {
|
||||
@Override
|
||||
protected String getCreateCommand() {
|
||||
|
@ -785,7 +785,7 @@ public class DerbyDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return true;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.FUNCTION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -360,10 +360,6 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
CommonFunctionFactory.aggregates(queryEngine);
|
||||
|
||||
//grouping functions cube() and rollup() supported on some databases
|
||||
|
||||
CommonFunctionFactory.groupings(queryEngine);
|
||||
|
||||
//the ANSI SQL-defined aggregate functions any() and every() are only
|
||||
//supported on one database, but can be emulated using sum() and case,
|
||||
//though there is a more natural mapping on some databases
|
||||
|
@ -2625,14 +2621,21 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Is this dialect known to support ROLLUP functions in the GROUP BY clause.
|
||||
* The strategy to use for rendering summarizations in the GROUP BY clause.
|
||||
*
|
||||
* @return True if this SQL dialect supports ROLLUP functions; false otherwise.
|
||||
* @since 6.0
|
||||
*/
|
||||
public boolean supportsGroupByRollup() {
|
||||
// return false here, as most databases do not properly support this construct...
|
||||
return false;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The strategy to use for rendering constants in the GROUP BY clause.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.CONSTANT_EXPRESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
/**
|
||||
* Strategies for rendering a constant in a group by.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum GroupByConstantRenderingStrategy {
|
||||
/**
|
||||
* The strategy for ANSI SQL compliant DBs like e.g. PostgreSQL that renders `()` i.e. the empty grouping.
|
||||
*/
|
||||
EMPTY_GROUPING,
|
||||
/**
|
||||
* Renders a constant e.g. `'0'`
|
||||
*/
|
||||
CONSTANT,
|
||||
/**
|
||||
* Renders a constant expression e.g. `'0' || '0'`
|
||||
*/
|
||||
CONSTANT_EXPRESSION,
|
||||
/**
|
||||
* Renders a subquery e.g. `(select 1)`
|
||||
*/
|
||||
SUBQUERY,
|
||||
/**
|
||||
* Renders a column reference to a dummy table e.g. `, (select 1 x) dummy` and `dummy.x`
|
||||
*/
|
||||
COLUMN_REFERENCE;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
/**
|
||||
* Strategies for rendering summarization function like rollup and cube in a group by.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public enum GroupBySummarizationRenderingStrategy {
|
||||
/**
|
||||
* No support for summarization.
|
||||
*/
|
||||
NONE,
|
||||
/**
|
||||
* Use the proprietary WITH ROLLUP or WITH CUBE clause.
|
||||
*/
|
||||
CLAUSE,
|
||||
/**
|
||||
* Use the rollup or cube functions like specified in the SQL standard.
|
||||
*/
|
||||
FUNCTION;
|
||||
}
|
|
@ -334,6 +334,11 @@ public class InformixDialect extends Dialect {
|
|||
return "select distinct current timestamp from informix.systables";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
|
|
|
@ -420,4 +420,9 @@ public class IngresDialect extends Dialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.COLUMN_REFERENCE;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -107,6 +107,11 @@ public class MariaDBDialect extends MySQLDialect {
|
|||
return getVersion() >= 1030;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.CLAUSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean supportsForShare() {
|
||||
//only supported on MySQL
|
||||
|
|
|
@ -922,7 +922,7 @@ public class MySQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return true;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.CLAUSE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
|
|||
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
|
||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
|
||||
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
|
||||
import org.hibernate.procedure.spi.CallableStatementSupport;
|
||||
import org.hibernate.query.CastType;
|
||||
|
@ -37,6 +39,11 @@ import org.hibernate.query.SemanticException;
|
|||
import org.hibernate.query.TemporalUnit;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.GlobalTemporaryTableStrategy;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
|
||||
import org.hibernate.query.sqm.mutation.internal.idtable.TempIdTableExporter;
|
||||
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
import org.hibernate.sql.*;
|
||||
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOracleDatabaseImpl;
|
||||
|
@ -807,8 +814,13 @@ public class OracleDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return true;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.FUNCTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -826,6 +838,23 @@ public class OracleDialect extends Dialect {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy(
|
||||
EntityMappingType rootEntityDescriptor,
|
||||
RuntimeModelCreationContext runtimeModelCreationContext) {
|
||||
return new GlobalTemporaryTableStrategy(
|
||||
new IdTable( rootEntityDescriptor, name -> name.length() > 30 ? name.substring( 0, 30 ) : name, this ),
|
||||
() -> new TempIdTableExporter( false, this::getTypeName ) {
|
||||
@Override
|
||||
protected String getCreateOptions() {
|
||||
return "on commit delete rows";
|
||||
}
|
||||
},
|
||||
AfterUseAction.CLEAN,
|
||||
runtimeModelCreationContext.getSessionFactory()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* For Oracle, the FOR UPDATE clause cannot be applied when using ORDER BY, DISTINCT or views.
|
||||
*
|
||||
|
|
|
@ -781,8 +781,13 @@ public class PostgreSQLDialect extends Dialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return getVersion() >= 950;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return getVersion() >= 950 ? GroupBySummarizationRenderingStrategy.FUNCTION : GroupBySummarizationRenderingStrategy.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return getVersion() >= 950 ? GroupByConstantRenderingStrategy.EMPTY_GROUPING : GroupByConstantRenderingStrategy.SUBQUERY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -359,8 +359,8 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGroupByRollup() {
|
||||
return true;
|
||||
public GroupBySummarizationRenderingStrategy getGroupBySummarizationRenderingStrategy() {
|
||||
return GroupBySummarizationRenderingStrategy.CLAUSE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -638,4 +638,9 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -130,4 +130,9 @@ public class SybaseAnywhereDialect extends SybaseDialect {
|
|||
// by default
|
||||
return TopLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,4 +549,9 @@ public class TeradataDialect extends Dialect {
|
|||
//TODO: is this right?!
|
||||
return TopLimitHandler.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupByConstantRenderingStrategy getGroupByConstantRenderingStrategy() {
|
||||
return GroupByConstantRenderingStrategy.EMPTY_GROUPING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1431,15 +1431,6 @@ public class CommonFunctionFactory {
|
|||
.register();
|
||||
}
|
||||
|
||||
public static void groupings(QueryEngine queryEngine) {
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("cube")
|
||||
.setMinArgumentCount(1)
|
||||
.register();
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("rollup")
|
||||
.setMinArgumentCount(1)
|
||||
.register();
|
||||
}
|
||||
|
||||
public static void aggregates(QueryEngine queryEngine) {
|
||||
queryEngine.getSqmFunctionRegistry().namedDescriptorBuilder("max")
|
||||
.setExactArgumentCount(1)
|
||||
|
|
|
@ -119,6 +119,7 @@ import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
|
@ -3307,31 +3308,19 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implements SqmCre
|
|||
|
||||
@Override
|
||||
public SqmExpression<?> visitCube(HqlParser.CubeContext ctx) {
|
||||
List<SqmTypedNode<?>> args = new ArrayList<>();
|
||||
for ( HqlParser.ExpressionContext arg: ctx.expression() ) {
|
||||
args.add( (SqmExpression<?>) arg.accept( this ) );
|
||||
}
|
||||
//ignore DISTINCT
|
||||
return getFunctionDescriptor("cube").generateSqmExpression(
|
||||
args,
|
||||
resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine(),
|
||||
creationContext.getJpaMetamodel().getTypeConfiguration()
|
||||
return new SqmSummarization<>(
|
||||
SqmSummarization.Kind.CUBE,
|
||||
visitExpressions( ctx.expression() ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmExpression<?> visitRollup(HqlParser.RollupContext ctx) {
|
||||
List<SqmTypedNode<?>> args = new ArrayList<>();
|
||||
for ( HqlParser.ExpressionContext arg: ctx.expression() ) {
|
||||
args.add( (SqmExpression<?>) arg.accept( this ) );
|
||||
}
|
||||
//ignore DISTINCT
|
||||
return getFunctionDescriptor("rollup").generateSqmExpression(
|
||||
args,
|
||||
resolveExpressableTypeBasic( Integer.class ),
|
||||
creationContext.getQueryEngine(),
|
||||
creationContext.getJpaMetamodel().getTypeConfiguration()
|
||||
return new SqmSummarization<>(
|
||||
SqmSummarization.Kind.ROLLUP,
|
||||
visitExpressions( ctx.expression() ),
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||
|
@ -205,6 +206,8 @@ public interface SemanticQueryWalker<T> {
|
|||
|
||||
T visitEvery(SqmEvery<?> sqmEvery);
|
||||
|
||||
T visitSummarization(SqmSummarization<?> sqmSummarization);
|
||||
|
||||
T visitPositionalParameterExpression(SqmPositionalParameter<?> expression);
|
||||
|
||||
T visitNamedParameterExpression(SqmNamedParameter<?> expression);
|
||||
|
|
|
@ -56,6 +56,7 @@ import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
|
@ -935,6 +936,11 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitSummarization(SqmSummarization<?> sqmSummarization) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitDynamicInstantiation(SqmDynamicInstantiation sqmDynamicInstantiation) {
|
||||
processStanza(
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.hibernate.query.sqm.tree.expression.SqmParameterizedEntityType;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmPathEntityType;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmRestrictedSubQueryExpression;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||
|
@ -633,6 +634,11 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
|
|||
return sqmEvery;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitSummarization(SqmSummarization<?> sqmSummarization) {
|
||||
return sqmSummarization;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitSearchedCaseExpression(SqmCaseSearched<?> expression) {
|
||||
return expression;
|
||||
|
|
|
@ -108,6 +108,7 @@ import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
|||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmStar;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmSummarization;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmToDuration;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTrimSpecification;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmTuple;
|
||||
|
@ -179,6 +180,7 @@ import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
|||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Star;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
|
@ -2235,6 +2237,30 @@ public abstract class BaseSqmToSqlAstConverter
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitSummarization(SqmSummarization<?> sqmSummarization) {
|
||||
final List<SqmExpression<?>> groupingExpressions = sqmSummarization.getGroupings();
|
||||
final int size = groupingExpressions.size();
|
||||
final List<Expression> expressions = new ArrayList<>( size );
|
||||
for ( int i = 0; i < size; i++ ) {
|
||||
expressions.add( (Expression) groupingExpressions.get( i ).accept( this ) );
|
||||
}
|
||||
return new Summarization(
|
||||
getSummarizationKind(sqmSummarization.getKind()),
|
||||
expressions
|
||||
);
|
||||
}
|
||||
|
||||
private Summarization.Kind getSummarizationKind(SqmSummarization.Kind kind) {
|
||||
switch ( kind ) {
|
||||
case CUBE:
|
||||
return Summarization.Kind.CUBE;
|
||||
case ROLLUP:
|
||||
return Summarization.Kind.ROLLUP;
|
||||
}
|
||||
throw new UnsupportedOperationException( "Unsupported summarization: " + kind );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitEnumLiteral(SqmEnumLiteral sqmEnumLiteral) {
|
||||
return new QueryLiteral<>(
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.query.sqm.tree.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.select.SqmSubQuery;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class SqmSummarization<T> extends AbstractSqmExpression<T> {
|
||||
|
||||
private final Kind kind;
|
||||
private final List<SqmExpression<?>> groupings;
|
||||
|
||||
public SqmSummarization(Kind kind, List<SqmExpression<?>> groupings, NodeBuilder criteriaBuilder) {
|
||||
super( null, criteriaBuilder );
|
||||
this.kind = kind;
|
||||
this.groupings = groupings;
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public List<SqmExpression<?>> getGroupings() {
|
||||
return groupings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> X accept(SemanticQueryWalker<X> walker) {
|
||||
return walker.visitSummarization( this );
|
||||
}
|
||||
|
||||
public enum Kind {
|
||||
ROLLUP,
|
||||
CUBE
|
||||
}
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@ import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
|||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Star;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||
|
@ -106,6 +107,8 @@ public interface SqlAstWalker {
|
|||
|
||||
void visitEvery(Every every);
|
||||
|
||||
void visitSummarization(Summarization every);
|
||||
|
||||
void visitSelfRenderingExpression(SelfRenderingExpression expression);
|
||||
|
||||
void visitSqlSelectionExpression(SqlSelectionExpression expression);
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
|
|||
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
|
||||
import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
||||
import org.hibernate.sql.ast.tree.expression.Star;
|
||||
import org.hibernate.sql.ast.tree.expression.Summarization;
|
||||
import org.hibernate.sql.ast.tree.expression.TrimSpecification;
|
||||
import org.hibernate.sql.ast.tree.expression.UnaryOperation;
|
||||
import org.hibernate.sql.ast.tree.from.FromClause;
|
||||
|
@ -369,7 +370,49 @@ public abstract class AbstractSqlAstWalker
|
|||
// 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 ) {
|
||||
appendSql( "()" );
|
||||
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 " );
|
||||
appendSql( dialect.getFromDual() );
|
||||
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!" );
|
||||
}
|
||||
}
|
||||
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!" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
expression.accept( this );
|
||||
|
@ -497,12 +540,7 @@ public abstract class AbstractSqlAstWalker
|
|||
try {
|
||||
appendSql( "select " );
|
||||
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : expressions ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
renderCommaSeparated( expressions );
|
||||
String fromDual = dialect.getFromDual();
|
||||
if ( !fromDual.isEmpty() ) {
|
||||
appendSql( " " );
|
||||
|
@ -985,17 +1023,22 @@ public abstract class AbstractSqlAstWalker
|
|||
appendSql( OPEN_PARENTHESIS );
|
||||
}
|
||||
|
||||
for ( Expression expression : tuple.getExpressions() ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
renderCommaSeparated( tuple.getExpressions() );
|
||||
|
||||
if ( isCurrentWhereClause ) {
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
||||
private void renderCommaSeparated(Iterable<? extends Expression> expressions) {
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : expressions ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCollate(Collate collate) {
|
||||
collate.getExpression().accept( this );
|
||||
|
@ -1366,6 +1409,11 @@ public abstract class AbstractSqlAstWalker
|
|||
every.getSubquery().accept( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSummarization(Summarization every) {
|
||||
// nothing to do... handled within #renderGroupByItem
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJdbcLiteral(JdbcLiteral jdbcLiteral) {
|
||||
visitLiteral( jdbcLiteral );
|
||||
|
@ -1538,12 +1586,7 @@ public abstract class AbstractSqlAstWalker
|
|||
appendSql( " not" );
|
||||
}
|
||||
appendSql( " in (" );
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : inListPredicate.getListExpressions() ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
renderCommaSeparated( inListPredicate.getListExpressions() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
@ -1553,12 +1596,7 @@ public abstract class AbstractSqlAstWalker
|
|||
appendSql( " not" );
|
||||
}
|
||||
appendSql( " in (" );
|
||||
String separator = NO_SEPARATOR;
|
||||
for ( Expression expression : inListPredicate.getListExpressions() ) {
|
||||
appendSql( separator );
|
||||
expression.accept( this );
|
||||
separator = COMA_SEPARATOR;
|
||||
}
|
||||
renderCommaSeparated( inListPredicate.getListExpressions() );
|
||||
appendSql( CLOSE_PARENTHESIS );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.sql.ast.tree.expression;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
|
||||
/**
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class Summarization implements Expression {
|
||||
|
||||
private final Kind kind;
|
||||
private final List<Expression> groupings;
|
||||
|
||||
public Summarization(Kind kind, List<Expression> groupings) {
|
||||
this.kind = kind;
|
||||
this.groupings = groupings;
|
||||
}
|
||||
|
||||
public Kind getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public List<Expression> getGroupings() {
|
||||
return groupings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingModelExpressable getExpressionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker walker) {
|
||||
walker.visitSummarization( this );
|
||||
}
|
||||
|
||||
public enum Kind {
|
||||
ROLLUP,
|
||||
CUBE
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ package org.hibernate.testing.orm.junit;
|
|||
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.GroupBySummarizationRenderingStrategy;
|
||||
|
||||
/**
|
||||
* Container class for different implementation of the {@link DialectFeatureCheck} interface.
|
||||
|
@ -223,7 +224,7 @@ abstract public class DialectFeatureChecks {
|
|||
|
||||
public static class SupportsGroupByRollup implements DialectFeatureCheck {
|
||||
public boolean apply(Dialect dialect) {
|
||||
return dialect.supportsGroupByRollup();
|
||||
return dialect.getGroupBySummarizationRenderingStrategy() != GroupBySummarizationRenderingStrategy.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue