re-enable tests
re-organize some tests continuing with o.h.test.hql - order-by add Expression#unwrap to help account for SqlSelectionExpression
This commit is contained in:
parent
51074eb9a0
commit
159135ea89
|
@ -219,7 +219,7 @@ public class EmbeddedAttributeMapping
|
|||
)
|
||||
);
|
||||
|
||||
columnReferences.add( (ColumnReference) columnReference );
|
||||
columnReferences.add( columnReference.unwrap( ColumnReference.class ) );
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.query.results;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.hibernate.Internal;
|
||||
import org.hibernate.sql.ast.spi.FromClauseAccess;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@Internal
|
||||
public class SqlAstProcessingStateImpl implements SqlAstProcessingState, SqlExpressionResolver {
|
||||
private final FromClauseAccessImpl fromClauseAccess;
|
||||
|
||||
private final Map<String, SqlSelectionImpl> sqlSelectionMap = new HashMap<>();
|
||||
private final Consumer<SqlSelection> sqlSelectionConsumer;
|
||||
|
||||
private final SqlAstCreationState sqlAstCreationState;
|
||||
|
||||
public SqlAstProcessingStateImpl(
|
||||
FromClauseAccessImpl fromClauseAccess,
|
||||
Consumer<SqlSelection> sqlSelectionConsumer,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
this.fromClauseAccess = fromClauseAccess;
|
||||
this.sqlSelectionConsumer = sqlSelectionConsumer;
|
||||
this.sqlAstCreationState = sqlAstCreationState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstProcessingState getParentState() {
|
||||
// none
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlExpressionResolver getSqlExpressionResolver() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlAstCreationState getSqlAstCreationState() {
|
||||
return sqlAstCreationState;
|
||||
}
|
||||
|
||||
public int getNumberOfProcessedSelections() {
|
||||
return sqlSelectionMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression resolveSqlExpression(
|
||||
String key,
|
||||
Function<SqlAstProcessingState, Expression> creator) {
|
||||
final SqlSelectionImpl existing = sqlSelectionMap.get( key );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
final Expression created = creator.apply( this );
|
||||
|
||||
if ( created instanceof SqlSelectionImpl ) {
|
||||
sqlSelectionMap.put( key, (SqlSelectionImpl) created );
|
||||
sqlSelectionConsumer.accept( (SqlSelectionImpl) created );
|
||||
}
|
||||
else if ( created instanceof ColumnReference ) {
|
||||
final ColumnReference columnReference = (ColumnReference) created;
|
||||
|
||||
final SqlSelectionImpl sqlSelection = new SqlSelectionImpl(
|
||||
sqlSelectionMap.size() + 1,
|
||||
columnReference.getJdbcMapping()
|
||||
);
|
||||
|
||||
sqlSelectionMap.put( key, sqlSelection );
|
||||
sqlSelectionConsumer.accept( sqlSelection );
|
||||
}
|
||||
|
||||
return created;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlSelection resolveSqlSelection(
|
||||
Expression expression,
|
||||
JavaTypeDescriptor javaTypeDescriptor,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
assert expression instanceof SqlSelectionImpl;
|
||||
return (SqlSelection) expression;
|
||||
}
|
||||
|
||||
public FromClauseAccess getFromClauseAccess() {
|
||||
return fromClauseAccess;
|
||||
}
|
||||
}
|
|
@ -86,6 +86,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
final List<ColumnReference> columnReferences = new ArrayList<>();
|
||||
|
||||
// todo (6.0) : "polymorphize" this
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
if ( mapping instanceof ToOneAttributeMapping ) {
|
||||
final ToOneAttributeMapping toOne = (ToOneAttributeMapping) mapping;
|
||||
final ModelPart modelPart = getModelPart( sqlAstCreationState, toOne );
|
||||
|
@ -99,21 +100,19 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
toOne,
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
final Expression columnReference = sqlExpressionResolver.resolveSqlExpression(
|
||||
createColumnReferenceKey(
|
||||
tableReference,
|
||||
selection.getSelectionExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableReference.getIdentificationVariable(),
|
||||
selection,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
);
|
||||
|
||||
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
|
||||
.resolveSqlExpression(
|
||||
createColumnReferenceKey(
|
||||
tableReference,
|
||||
selection.getSelectionExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableReference.getIdentificationVariable(),
|
||||
selection,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
);
|
||||
|
||||
columnReferences.add( (ColumnReference) columnReference );
|
||||
columnReferences.add( columnReference.unwrap( ColumnReference.class ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -151,7 +150,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
(index, selectable) -> {
|
||||
final TableReference tableReference = mapTableGroup.resolveTableReference( selectable.getContainingTableExpression() );
|
||||
|
||||
final SqlExpressionResolver expressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final SqlExpressionResolver expressionResolver = sqlExpressionResolver;
|
||||
|
||||
columnReferences.add(
|
||||
(ColumnReference) expressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -25,6 +25,10 @@ public interface Expression extends SqlAstNode, SqlSelectionProducer {
|
|||
*/
|
||||
MappingModelExpressable getExpressionType();
|
||||
|
||||
default <T> T unwrap(Class<T> target) {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
default SqlSelection createSqlSelection(
|
||||
int jdbcPosition,
|
||||
|
|
|
@ -29,6 +29,28 @@ public class SqlSelectionExpression implements Expression {
|
|||
return theSelection;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> target) {
|
||||
if ( target.isInstance( this ) ) {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
if ( target.isInstance( theSelection ) ) {
|
||||
return (T) theSelection;
|
||||
}
|
||||
|
||||
if ( target.isInstance( theSelection.getExpression() ) ) {
|
||||
return (T) theSelection.getExpression();
|
||||
}
|
||||
|
||||
if ( target.isInstance( theSelection.getExpressionType() ) ) {
|
||||
return (T) theSelection.getExpressionType();
|
||||
}
|
||||
|
||||
return theSelection.getExpression().unwrap( target );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SqlAstWalker sqlTreeWalker) {
|
||||
sqlTreeWalker.visitSqlSelectionExpression( this );
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.sql.results.jdbc.internal;
|
|||
import java.sql.SQLException;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.cache.spi.QueryKey;
|
||||
import org.hibernate.cache.spi.QueryResultsCache;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
|
@ -248,11 +249,19 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
|
|||
|
||||
private void readCurrentRowValues() throws SQLException {
|
||||
for ( final SqlSelection sqlSelection : sqlSelections ) {
|
||||
currentRowJdbcValues[ sqlSelection.getValuesArrayPosition() ] = sqlSelection.getJdbcValueExtractor().extract(
|
||||
resultSetAccess.getResultSet(),
|
||||
sqlSelection.getJdbcResultSetIndex(),
|
||||
executionContext.getSession()
|
||||
);
|
||||
try {
|
||||
currentRowJdbcValues[ sqlSelection.getValuesArrayPosition() ] = sqlSelection.getJdbcValueExtractor().extract(
|
||||
resultSetAccess.getResultSet(),
|
||||
sqlSelection.getJdbcResultSetIndex(),
|
||||
executionContext.getSession()
|
||||
);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException(
|
||||
"Unable to extract JDBC value for position `" + sqlSelection.getJdbcResultSetIndex() + "`",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
super.configure( cfg );
|
||||
cfg.setProperty( Environment.USE_QUERY_CACHE, "false" );
|
||||
cfg.setProperty( Environment.GENERATE_STATISTICS, "true" );
|
||||
cfg.setProperty( Environment.SEMANTIC_QUERY_PRODUCER, HqlTranslator.class.getName() );
|
||||
}
|
||||
|
||||
private void createData() {
|
||||
|
@ -68,6 +67,7 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
address1.setStreet( "1313 Mockingbird Lane" );
|
||||
address1.setCity( "Anywhere" );
|
||||
address1.setStateProvince( stateProvince );
|
||||
address1.setPostalCode( "12345" );
|
||||
address1.setCountry( "USA" );
|
||||
zoo1.setAddress( address1 );
|
||||
zoo1Mammal1 = new Mammal();
|
||||
|
@ -84,6 +84,7 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
Address address2 = new Address();
|
||||
address2.setStreet( "1313 Mockingbird Lane" );
|
||||
address2.setCity( "Anywhere" );
|
||||
address2.setPostalCode( "12345" );
|
||||
address2.setStateProvince( stateProvince );
|
||||
address2.setCountry( "USA" );
|
||||
zoo2.setAddress( address2 );
|
||||
|
@ -100,6 +101,7 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
address3.setStreet( "1312 Mockingbird Lane" );
|
||||
address3.setCity( "Anywhere" );
|
||||
address3.setStateProvince( stateProvince );
|
||||
address3.setPostalCode( "12345" );
|
||||
address3.setCountry( "USA" );
|
||||
zoo3.setAddress( address3 );
|
||||
|
||||
|
@ -109,6 +111,7 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
address4.setStreet( "1312 Mockingbird Lane" );
|
||||
address4.setCity( "Nowhere" );
|
||||
address4.setStateProvince( stateProvince );
|
||||
address4.setPostalCode( "12345" );
|
||||
address4.setCountry( "USA" );
|
||||
zoo4.setAddress( address4 );
|
||||
|
||||
|
@ -241,17 +244,58 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
// zoo4 Duh Zoo 1312 Mockingbird Lane, Nowhere, IL USA
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
|
||||
// NOTE (6.0) : the above illustration is based on 5.x code. but the outcome
|
||||
// is ultimately based on the order in which we render the attributes of
|
||||
// the Address component. In 6.0 this has been made consistent and easily
|
||||
// explainable, whereas that was not previously the case.
|
||||
// checkTestOrderByResults(
|
||||
// s.createQuery(
|
||||
// "select z.name, z.address from Zoo z order by z.address, z.name"
|
||||
// ).list(),
|
||||
// zoo3, zoo4, zoo2, zoo1, null
|
||||
// );
|
||||
|
||||
// NOTE (6.0) - continued : this is functionally equivalent to the 5.x case
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address " +
|
||||
"from Zoo z " +
|
||||
"order by z.address.street," +
|
||||
" z.address.city," +
|
||||
" z.address.postalCode, " +
|
||||
" z.address.country," +
|
||||
" z.name"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
);
|
||||
|
||||
// NOTE (6.0) - continued 2 : this is the 6.x functionally
|
||||
// ordered by address, name:
|
||||
// zoo3 Zoo 1312 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo4 Duh Zoo 1312 Mockingbird Lane, Nowhere, IL USA
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address from Zoo z order by z.address, z.name"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
|
||||
// NOTE (6.0) - continued 3 : and the functionally equiv "full ordering"
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address from Zoo z order by z.address.city, z.address.country, z.address.stateProvince, z.address.street, z.name"
|
||||
).list(),
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select name, address from Zoo order by address, name"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
|
||||
// ordered by address:
|
||||
|
@ -260,15 +304,24 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
// unordered:
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
//
|
||||
// NOTE 6.0 : these results are not well defined. Because we primarily order
|
||||
// based on city zoo1, zoo2 and zoo3 are all sorted "above" zoo4. however
|
||||
// the order between zoo1 and zoo2 is completely undefined because they
|
||||
// have the same address
|
||||
//
|
||||
// and honestly, not even sure what this assertion is even trying to test.
|
||||
// but changed the query to what you'd need to get those results - which I guess
|
||||
// is the order used by 5.x
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address from Zoo z order by z.address"
|
||||
"select z.name, z.address from Zoo z order by z.address.street, z.address.city"
|
||||
).list(),
|
||||
zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
);
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select name, address from Zoo order by address"
|
||||
"select name, address from Zoo order by address.street, address.city"
|
||||
).list(),
|
||||
zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
);
|
||||
|
@ -406,30 +459,37 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
// zoo4 Duh Zoo 1312 Mockingbird Lane, Nowhere, IL USA
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
//
|
||||
// NOTE (6.0) : another case of different handling for the component attributes
|
||||
// causing a "failure"
|
||||
// zoo3 Zoo 1312 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo4 Duh Zoo 1312 Mockingbird Lane, Nowhere, IL USA
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name as address, z.address as name from Zoo z order by name, address"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address as name from Zoo z order by name, z.name"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
// using ASC
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name as address, z.address as name from Zoo z order by name ASC, address ASC"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name, z.address as name from Zoo z order by name ASC, z.name ASC"
|
||||
).list(),
|
||||
zoo3, zoo4, zoo2, zoo1, null
|
||||
zoo3, zoo2, zoo1, zoo4, null
|
||||
);
|
||||
|
||||
// ordered by address:
|
||||
|
@ -438,19 +498,22 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
// unordered:
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
// zoo1 Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name as zooName, z.address as zooAddress from Zoo z order by zooAddress"
|
||||
).list(),
|
||||
zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
);
|
||||
//
|
||||
// NOTE (6.0) : another one where the result order would be undefined
|
||||
// checkTestOrderByResults(
|
||||
// s.createQuery(
|
||||
// "select z.name as zooName, z.address as zooAddress from Zoo z order by zooAddress"
|
||||
// ).list(),
|
||||
// zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
// );
|
||||
|
||||
checkTestOrderByResults(
|
||||
s.createQuery(
|
||||
"select z.name as zooName, z.address as name from Zoo z order by name"
|
||||
).list(),
|
||||
zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
);
|
||||
// NOTE (6.0) : another undefined case
|
||||
// checkTestOrderByResults(
|
||||
// s.createQuery(
|
||||
// "select z.name as zooName, z.address as name from Zoo z order by name"
|
||||
// ).list(),
|
||||
// zoo3, zoo4, null, null, zoosWithSameAddress
|
||||
// );
|
||||
|
||||
// ordered by name:
|
||||
// zoo2 A Zoo 1313 Mockingbird Lane, Anywhere, IL USA
|
||||
|
@ -679,8 +742,8 @@ public class ASTParserLoadingOrderByTest extends BaseCoreFunctionalTestCase {
|
|||
assertTrue( zoosUnordered.remove( zooResult ) );
|
||||
}
|
||||
else {
|
||||
assertEquals( zooExpected.getName(), ( ( Object[] ) result )[ 0 ] );
|
||||
assertEquals( zooExpected.getAddress(), ( ( Object[] ) result )[ 1 ] );
|
||||
assertEquals( zooExpected.getName(), ( ( Object[] ) result )[ 0 ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -100,4 +100,15 @@ public class Address {
|
|||
result = 31 * result + ( stateProvince != null ? stateProvince.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Address{" +
|
||||
"street='" + street + '\'' +
|
||||
", city='" + city + '\'' +
|
||||
", postalCode='" + postalCode + '\'' +
|
||||
", country='" + country + '\'' +
|
||||
", stateProvince=" + stateProvince +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,4 +70,13 @@ public class StateProvince {
|
|||
result = 31 * result + ( isoCode != null ? isoCode.hashCode() : 0 );
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "StateProvince{" +
|
||||
"id=" + id +
|
||||
", name='" + name + '\'' +
|
||||
", isoCode='" + isoCode + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue