Fix compilation errors after merge
This commit is contained in:
parent
3476e82122
commit
ade760d71a
|
@ -345,28 +345,6 @@ public class H2Dialect extends Dialect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not drop constraints explicitly, just do this by cascading instead.
|
|
||||||
@Override
|
|
||||||
public boolean dropConstraints() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getCascadeConstraintsString() {
|
|
||||||
return " CASCADE ";
|
|
||||||
}
|
|
||||||
|
|
||||||
// CASCADE has to be AFTER IF EXISTS in case it's after the tablename
|
|
||||||
@Override
|
|
||||||
public boolean supportsIfExistsAfterTableName() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supportsIfExistsBeforeTableName() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IdentityColumnSupport getIdentityColumnSupport() {
|
public IdentityColumnSupport getIdentityColumnSupport() {
|
||||||
return new H2IdentityColumnSupport();
|
return new H2IdentityColumnSupport();
|
||||||
|
|
|
@ -1,296 +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.hql.internal.ast.tree;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.hibernate.QueryException;
|
|
||||||
import org.hibernate.hql.internal.ast.HqlSqlWalker;
|
|
||||||
import org.hibernate.hql.internal.ast.SqlASTFactory;
|
|
||||||
import org.hibernate.internal.util.StringHelper;
|
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.persister.entity.Joinable;
|
|
||||||
import org.hibernate.persister.entity.PropertyMapping;
|
|
||||||
import org.hibernate.type.CollectionType;
|
|
||||||
import org.hibernate.type.CompositeType;
|
|
||||||
import org.hibernate.type.EntityType;
|
|
||||||
import org.hibernate.type.Type;
|
|
||||||
|
|
||||||
import antlr.SemanticException;
|
|
||||||
import antlr.collections.AST;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class CollectionPathNode extends SqlNode {
|
|
||||||
/**
|
|
||||||
* Used to resolve the collection "owner key" columns
|
|
||||||
*/
|
|
||||||
private final FromElement ownerFromElement;
|
|
||||||
|
|
||||||
private final CollectionPersister collectionDescriptor;
|
|
||||||
|
|
||||||
private final String collectionPropertyName;
|
|
||||||
private final String collectionPropertyPath;
|
|
||||||
private final String collectionQueryPath;
|
|
||||||
|
|
||||||
private final HqlSqlWalker walker;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instantiate a `CollectionPathNode`
|
|
||||||
*
|
|
||||||
* @see #from(AST, AST, HqlSqlWalker)
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public CollectionPathNode(
|
|
||||||
FromElement ownerFromElement,
|
|
||||||
CollectionPersister collectionDescriptor,
|
|
||||||
String collectionPropertyName,
|
|
||||||
String collectionQueryPath,
|
|
||||||
String collectionPropertyPath,
|
|
||||||
HqlSqlWalker walker) {
|
|
||||||
this.ownerFromElement = ownerFromElement;
|
|
||||||
this.collectionDescriptor = collectionDescriptor;
|
|
||||||
this.collectionPropertyName = collectionPropertyName;
|
|
||||||
this.collectionQueryPath = collectionQueryPath;
|
|
||||||
this.collectionPropertyPath = collectionPropertyPath;
|
|
||||||
this.walker = walker;
|
|
||||||
|
|
||||||
walker.addQuerySpaces( collectionDescriptor.getCollectionSpaces() );
|
|
||||||
|
|
||||||
super.setType( SqlASTFactory.COLL_PATH );
|
|
||||||
super.setDataType( collectionDescriptor.getCollectionType() );
|
|
||||||
super.setText( collectionDescriptor.getRole() );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Factory for `CollectionPathNode` instances
|
|
||||||
*
|
|
||||||
* @param qualifier The left-hand-side of a dot-ident node - may be null to indicate an ident arg
|
|
||||||
* @param reference The right-hand-side of the dot-ident or the ident that is an unqualified reference
|
|
||||||
*/
|
|
||||||
public static CollectionPathNode from(
|
|
||||||
AST qualifier,
|
|
||||||
AST reference,
|
|
||||||
HqlSqlWalker walker) {
|
|
||||||
|
|
||||||
final String referenceName = reference.getText();
|
|
||||||
final String referenceQueryPath;
|
|
||||||
|
|
||||||
if ( qualifier == null ) {
|
|
||||||
// If there is no qualifier it means the argument to `size()` was a simple IDENT node as opposed to a DOT-IDENT
|
|
||||||
// node. In this case, `reference` could technically be a join alias. This is not JPA
|
|
||||||
// compliant, but is a Hibernate-specific extension
|
|
||||||
|
|
||||||
referenceQueryPath = referenceName;
|
|
||||||
|
|
||||||
final FromElement byAlias = walker.getCurrentFromClause().getFromElement( referenceName );
|
|
||||||
|
|
||||||
if ( byAlias != null ) {
|
|
||||||
final FromElement ownerRef = byAlias.getOrigin();
|
|
||||||
final QueryableCollection collectionDescriptor = byAlias.getQueryableCollection();
|
|
||||||
|
|
||||||
return new CollectionPathNode(
|
|
||||||
ownerRef,
|
|
||||||
collectionDescriptor,
|
|
||||||
referenceName,
|
|
||||||
referenceQueryPath,
|
|
||||||
referenceName,
|
|
||||||
walker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we (should) have an unqualified plural-attribute name - look through all of the defined from-elements
|
|
||||||
// and look for one that exposes that property
|
|
||||||
|
|
||||||
//noinspection unchecked
|
|
||||||
final List<FromElement> fromElements = walker.getCurrentFromClause().getExplicitFromElements();
|
|
||||||
|
|
||||||
if ( fromElements.size() == 1 ) {
|
|
||||||
final FromElement ownerRef = fromElements.get( 0 );
|
|
||||||
|
|
||||||
final PropertyMapping collectionPropertyMapping = ownerRef.getPropertyMapping( referenceName );
|
|
||||||
|
|
||||||
//noinspection RedundantClassCall
|
|
||||||
if ( ! CollectionType.class.isInstance( collectionPropertyMapping.getType() ) ) {
|
|
||||||
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
|
||||||
}
|
|
||||||
|
|
||||||
final CollectionType collectionType = (CollectionType) collectionPropertyMapping.getType();
|
|
||||||
|
|
||||||
return new CollectionPathNode(
|
|
||||||
ownerRef,
|
|
||||||
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
|
||||||
referenceName,
|
|
||||||
referenceQueryPath,
|
|
||||||
referenceName,
|
|
||||||
walker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FromElement discoveredQualifier = null;
|
|
||||||
|
|
||||||
//noinspection ForLoopReplaceableByForEach
|
|
||||||
for ( int i = 0; i < fromElements.size(); i++ ) {
|
|
||||||
final FromElement fromElement = fromElements.get( i );
|
|
||||||
try {
|
|
||||||
final PropertyMapping propertyMapping = fromElement.getPropertyMapping( referenceName );
|
|
||||||
//noinspection RedundantClassCall
|
|
||||||
if ( ! CollectionType.class.isInstance( propertyMapping.getType() ) ) {
|
|
||||||
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
|
||||||
}
|
|
||||||
|
|
||||||
discoveredQualifier = fromElement;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// try the next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( discoveredQualifier == null ) {
|
|
||||||
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
|
||||||
}
|
|
||||||
|
|
||||||
final FromElement ownerRef = discoveredQualifier;
|
|
||||||
|
|
||||||
final PropertyMapping collectionPropertyMapping = ownerRef.getPropertyMapping( referenceName );
|
|
||||||
|
|
||||||
//noinspection RedundantClassCall
|
|
||||||
if ( ! CollectionType.class.isInstance( collectionPropertyMapping.getType() ) ) {
|
|
||||||
throw new QueryException( "Could not resolve identifier `" + referenceName + "` as plural-attribute" );
|
|
||||||
}
|
|
||||||
|
|
||||||
final CollectionType collectionType = (CollectionType) collectionPropertyMapping.getType();
|
|
||||||
|
|
||||||
return new CollectionPathNode(
|
|
||||||
ownerRef,
|
|
||||||
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
|
||||||
referenceName,
|
|
||||||
referenceQueryPath,
|
|
||||||
referenceName,
|
|
||||||
walker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// we have a dot-ident structure
|
|
||||||
final FromReferenceNode qualifierFromReferenceNode = (FromReferenceNode) qualifier;
|
|
||||||
|
|
||||||
final String qualifierQueryPath = ( (FromReferenceNode) qualifier ).getPath();
|
|
||||||
referenceQueryPath = qualifierQueryPath + "." + reference;
|
|
||||||
|
|
||||||
try {
|
|
||||||
qualifierFromReferenceNode.resolve( false, false );
|
|
||||||
}
|
|
||||||
catch (SemanticException e) {
|
|
||||||
throw new QueryException( "Unable to resolve collection-path qualifier : " + qualifierQueryPath, e );
|
|
||||||
}
|
|
||||||
|
|
||||||
final Type qualifierType = qualifierFromReferenceNode.getDataType();
|
|
||||||
final FromElement ownerRef = ( (FromReferenceNode) qualifier ).getFromElement();
|
|
||||||
|
|
||||||
final CollectionType collectionType;
|
|
||||||
final String referenceMappedPath;
|
|
||||||
|
|
||||||
if ( qualifierType instanceof CompositeType ) {
|
|
||||||
final CompositeType qualifierCompositeType = (CompositeType) qualifierType;
|
|
||||||
final int collectionPropertyIndex = (qualifierCompositeType).getPropertyIndex( referenceName );
|
|
||||||
collectionType = (CollectionType) qualifierCompositeType.getSubtypes()[collectionPropertyIndex];
|
|
||||||
|
|
||||||
if ( ownerRef instanceof ComponentJoin ) {
|
|
||||||
referenceMappedPath = ( (ComponentJoin) ownerRef ).getComponentPath() + "." + referenceName;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
referenceMappedPath = qualifierQueryPath.substring( qualifierQueryPath.indexOf( "." ) + 1 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ( qualifierType instanceof EntityType ) {
|
|
||||||
final EntityType qualifierEntityType = (EntityType) qualifierType;
|
|
||||||
final String entityName = qualifierEntityType.getAssociatedEntityName();
|
|
||||||
final EntityPersister entityPersister = walker.getSessionFactoryHelper().findEntityPersisterByName( entityName );
|
|
||||||
final int propertyIndex = entityPersister.getEntityMetamodel().getPropertyIndex( referenceName );
|
|
||||||
collectionType = (CollectionType) entityPersister.getPropertyTypes()[ propertyIndex ];
|
|
||||||
referenceMappedPath = referenceName;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new QueryException( "Unexpected collection-path reference qualifier type : " + qualifier );
|
|
||||||
}
|
|
||||||
|
|
||||||
return new CollectionPathNode(
|
|
||||||
( (FromReferenceNode) qualifier ).getFromElement(),
|
|
||||||
walker.getSessionFactoryHelper().requireQueryableCollection( collectionType.getRole() ),
|
|
||||||
referenceName,
|
|
||||||
referenceQueryPath,
|
|
||||||
referenceMappedPath,
|
|
||||||
walker
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public FromElement getCollectionOwnerFromElement() {
|
|
||||||
return ownerFromElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public CollectionPersister getCollectionDescriptor() {
|
|
||||||
return collectionDescriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the collection property - e.g. `theCollection`
|
|
||||||
*/
|
|
||||||
public String getCollectionPropertyName() {
|
|
||||||
return collectionPropertyName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The collection property path relative to the "owning entity" in the mapping model - e.g. `theCollection`
|
|
||||||
* or `someEmbeddable.theCollection`.
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public String getCollectionPropertyPath() {
|
|
||||||
return collectionPropertyPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The "full" path. E.g. `a.theCollection` or `a.someEmbeddable.theCollection`
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public String getCollectionQueryPath() {
|
|
||||||
return collectionQueryPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("WeakerAccess")
|
|
||||||
public String[] resolveOwnerKeyColumnExpressions() {
|
|
||||||
final AST ast = walker.getAST();
|
|
||||||
final String ownerTableAlias;
|
|
||||||
if ( ast instanceof DeleteStatement || ast instanceof UpdateStatement ) {
|
|
||||||
ownerTableAlias = ownerFromElement.getTableName();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ownerTableAlias = ownerFromElement.getTableAlias();
|
|
||||||
}
|
|
||||||
|
|
||||||
final String lhsPropertyName = collectionDescriptor.getCollectionType().getLHSPropertyName();
|
|
||||||
if ( lhsPropertyName == null ) {
|
|
||||||
return StringHelper.qualify(
|
|
||||||
ownerTableAlias,
|
|
||||||
( (Joinable) collectionDescriptor.getOwnerEntityPersister() ).getKeyColumnNames()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ownerFromElement.toColumns( ownerTableAlias, lhsPropertyName, true );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
|
||||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
|
||||||
*/
|
|
||||||
package org.hibernate.hql.internal.ast.tree;
|
|
||||||
|
|
||||||
import org.hibernate.AssertionFailure;
|
|
||||||
import org.hibernate.hql.internal.NameGenerator;
|
|
||||||
import org.hibernate.hql.internal.antlr.HqlSqlTokenTypes;
|
|
||||||
import org.hibernate.internal.util.StringHelper;
|
|
||||||
import org.hibernate.persister.collection.CollectionPropertyMapping;
|
|
||||||
import org.hibernate.persister.collection.CollectionPropertyNames;
|
|
||||||
import org.hibernate.persister.collection.QueryableCollection;
|
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Steve Ebersole
|
|
||||||
*/
|
|
||||||
public class CollectionSizeNode extends SqlNode implements SelectExpression {
|
|
||||||
private static final Logger log = Logger.getLogger( CollectionSizeNode.class );
|
|
||||||
|
|
||||||
private final CollectionPathNode collectionPathNode;
|
|
||||||
private final CollectionPropertyMapping collectionPropertyMapping;
|
|
||||||
|
|
||||||
private String alias;
|
|
||||||
|
|
||||||
public CollectionSizeNode(CollectionPathNode collectionPathNode) {
|
|
||||||
this.collectionPathNode = collectionPathNode;
|
|
||||||
this.collectionPropertyMapping = new CollectionPropertyMapping( (QueryableCollection) collectionPathNode.getCollectionDescriptor() );
|
|
||||||
|
|
||||||
setType( HqlSqlTokenTypes.COLL_SIZE );
|
|
||||||
setDataType( StandardBasicTypes.INTEGER );
|
|
||||||
setText( "collection-size" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public CollectionPathNode getCollectionPathNode() {
|
|
||||||
return collectionPathNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toSqlExpression() {
|
|
||||||
final FromElement collectionOwnerFromElement = collectionPathNode.getCollectionOwnerFromElement();
|
|
||||||
final QueryableCollection collectionDescriptor = (QueryableCollection) collectionPathNode.getCollectionDescriptor();
|
|
||||||
|
|
||||||
// generate subquery in the form:
|
|
||||||
//
|
|
||||||
// select count( alias_.<collection-key-column> )
|
|
||||||
// from <collection-table> as alias_
|
|
||||||
// where <owner-key-column> = alias_.<collection-key-column>
|
|
||||||
|
|
||||||
// Note that `collectionPropertyMapping.toColumns(.., COLLECTION_SIZE)` returns the complete `count(...)` SQL
|
|
||||||
// expression, hence he expectation for a single expression regardless of the number of columns in the key.
|
|
||||||
|
|
||||||
final String collectionTableAlias = collectionOwnerFromElement.getFromClause()
|
|
||||||
.getAliasGenerator()
|
|
||||||
.createName( collectionPathNode.getCollectionPropertyName() );
|
|
||||||
|
|
||||||
final String[] ownerKeyColumns = collectionPathNode.resolveOwnerKeyColumnExpressions();
|
|
||||||
final String[] collectionKeyColumns = StringHelper.qualify( collectionTableAlias, collectionDescriptor.getKeyColumnNames() );
|
|
||||||
|
|
||||||
if ( collectionKeyColumns.length != ownerKeyColumns.length ) {
|
|
||||||
throw new AssertionFailure( "Mismatch between collection key columns" );
|
|
||||||
}
|
|
||||||
|
|
||||||
final String[] sizeColumns = this.collectionPropertyMapping.toColumns(
|
|
||||||
collectionTableAlias,
|
|
||||||
CollectionPropertyNames.COLLECTION_SIZE
|
|
||||||
);
|
|
||||||
assert sizeColumns.length == 1;
|
|
||||||
final String sizeColumn = sizeColumns[0];
|
|
||||||
|
|
||||||
final StringBuilder buffer = new StringBuilder( "(select " ).append( sizeColumn );
|
|
||||||
buffer.append( " from " ).append( collectionDescriptor.getTableName() ).append( " " ).append( collectionTableAlias );
|
|
||||||
buffer.append( " where " );
|
|
||||||
|
|
||||||
boolean firstPass = true;
|
|
||||||
for ( int i = 0; i < ownerKeyColumns.length; i++ ) {
|
|
||||||
if ( firstPass ) {
|
|
||||||
firstPass = false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
buffer.append( " and " );
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append( ownerKeyColumns[i] ).append( " = " ).append( collectionKeyColumns[i] );
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.append( ")" );
|
|
||||||
|
|
||||||
if ( scalarName != null ) {
|
|
||||||
buffer.append( " as " ).append( scalarName );
|
|
||||||
}
|
|
||||||
|
|
||||||
final String subQuery = buffer.toString();
|
|
||||||
|
|
||||||
log.debugf(
|
|
||||||
"toSqlExpression( size(%s) ) -> %s",
|
|
||||||
collectionPathNode.getCollectionQueryPath(),
|
|
||||||
subQuery
|
|
||||||
);
|
|
||||||
|
|
||||||
return subQuery;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// SelectExpression
|
|
||||||
|
|
||||||
private String scalarName;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setScalarColumnText(int i) {
|
|
||||||
log.debugf( "setScalarColumnText(%s)", i );
|
|
||||||
scalarName = NameGenerator.scalarName( i, 0 );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setScalarColumn(int i) {
|
|
||||||
log.debugf( "setScalarColumn(%s)", i );
|
|
||||||
setScalarColumnText( i );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getScalarColumnIndex() {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public FromElement getFromElement() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isConstructor() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isReturnableEntity() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isScalar() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAlias(String alias) {
|
|
||||||
this.alias = alias;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getAlias() {
|
|
||||||
return alias;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +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.hql.internal.ast.tree;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Jan-Willem Gmelig Meyling
|
|
||||||
*/
|
|
||||||
public interface TableReferenceNode {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns table names which are referenced by this node. If the tables
|
|
||||||
* can not be determined it returns null.
|
|
||||||
*
|
|
||||||
* @return table names or null.
|
|
||||||
*/
|
|
||||||
public String[] getReferencedTables();
|
|
||||||
|
|
||||||
}
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.dialect.SybaseAnywhereDialect;
|
||||||
import org.hibernate.dialect.SybaseDialect;
|
import org.hibernate.dialect.SybaseDialect;
|
||||||
import org.hibernate.dialect.TeradataDialect;
|
import org.hibernate.dialect.TeradataDialect;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
|
import org.hibernate.engine.query.spi.HQLQueryPlan;
|
||||||
import org.hibernate.engine.query.spi.ReturnMetadata;
|
import org.hibernate.engine.query.spi.ReturnMetadata;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.hql.internal.antlr.HqlTokenTypes;
|
import org.hibernate.hql.internal.antlr.HqlTokenTypes;
|
||||||
|
@ -59,6 +60,7 @@ import org.hibernate.testing.FailureExpected;
|
||||||
import org.hibernate.testing.RequiresDialectFeature;
|
import org.hibernate.testing.RequiresDialectFeature;
|
||||||
import org.hibernate.testing.SkipForDialect;
|
import org.hibernate.testing.SkipForDialect;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import antlr.RecognitionException;
|
import antlr.RecognitionException;
|
||||||
|
@ -157,20 +159,20 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@FailureExpected( jiraKey = "N/A", message = "Lacking ClassicQueryTranslatorFactory support" )
|
@FailureExpected( jiraKey = "N/A", message = "Lacking ClassicQueryTranslatorFactory support" )
|
||||||
public void testRowValueConstructorSyntaxInInList2() {
|
public void testRowValueConstructorSyntaxInInList2() {
|
||||||
assertTranslation( "from LineItem l where l.id in (:idList)" );
|
assertTranslation( "from LineItem l where l.id in (:idList)" );
|
||||||
assertTranslation( "from LineItem l where l.id in :idList" );
|
assertTranslation( "from LineItem l where l.id in :idList" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@SkipForDialect( value = {
|
@SkipForDialect( value = {
|
||||||
Oracle8iDialect.class,
|
Oracle8iDialect.class,
|
||||||
AbstractHANADialect.class,
|
AbstractHANADialect.class,
|
||||||
PostgreSQL81Dialect.class,
|
PostgreSQL81Dialect.class,
|
||||||
MySQLDialect.class
|
MySQLDialect.class
|
||||||
} )
|
} )
|
||||||
|
|
||||||
public void testRowValueConstructorSyntaxInInListBeingTranslated() {
|
public void testRowValueConstructorSyntaxInInListBeingTranslated() {
|
||||||
QueryTranslatorImpl translator = createNewQueryTranslator( "from LineItem l where l.id in (?1)" );
|
QueryTranslatorImpl translator = createNewQueryTranslator( "from LineItem l where l.id in (?1)" );
|
||||||
assertInExist( "'in' should be translated to 'and'", false, translator );
|
assertInExist( "'in' should be translated to 'and'", false, translator );
|
||||||
translator = createNewQueryTranslator("from LineItem l where l.id in ?1" );
|
translator = createNewQueryTranslator("from LineItem l where l.id in ?1" );
|
||||||
|
@ -183,11 +185,11 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
assertInExist( "only translated tuple has 'in' syntax", true, translator );
|
assertInExist( "only translated tuple has 'in' syntax", true, translator );
|
||||||
translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)" );
|
translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)" );
|
||||||
assertInExist( "do not translate sub-queries", true, translator );
|
assertInExist( "do not translate sub-queries", true, translator );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@RequiresDialectFeature( DialectChecks.SupportsRowValueConstructorSyntaxInInListCheck.class )
|
@RequiresDialectFeature( DialectChecks.SupportsRowValueConstructorSyntaxInInListCheck.class )
|
||||||
public void testRowValueConstructorSyntaxInInList() {
|
public void testRowValueConstructorSyntaxInInList() {
|
||||||
QueryTranslatorImpl translator = createNewQueryTranslator("from LineItem l where l.id in (?1)" );
|
QueryTranslatorImpl translator = createNewQueryTranslator("from LineItem l where l.id in (?1)" );
|
||||||
assertInExist( " 'in' should be kept, since the dialect supports this syntax", true, translator );
|
assertInExist( " 'in' should be kept, since the dialect supports this syntax", true, translator );
|
||||||
translator = createNewQueryTranslator("from LineItem l where l.id in ?1" );
|
translator = createNewQueryTranslator("from LineItem l where l.id in ?1" );
|
||||||
|
@ -200,7 +202,7 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
assertInExist( "only translated tuple has 'in' syntax", true, translator );
|
assertInExist( "only translated tuple has 'in' syntax", true, translator );
|
||||||
translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)" );
|
translator = createNewQueryTranslator("from LineItem l where l.id in (select a1 from Animal a1 left join a1.offspring o where a1.id = 1)" );
|
||||||
assertInExist( "do not translate sub-queries", true, translator );
|
assertInExist( "do not translate sub-queries", true, translator );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertInExist( String message, boolean expected, QueryTranslatorImpl translator ) {
|
private void assertInExist( String message, boolean expected, QueryTranslatorImpl translator ) {
|
||||||
AST ast = translator.getSqlAST().getWalker().getAST();
|
AST ast = translator.getSqlAST().getWalker().getAST();
|
||||||
|
@ -240,7 +242,7 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
public void testCollectionMemberDeclarations(){
|
public void testCollectionMemberDeclarations(){
|
||||||
// both these two query translators throw exeptions for this HQL since
|
// both these two query translators throw exeptions for this HQL since
|
||||||
// IN asks an alias, but the difference is that the error message from AST
|
// IN asks an alias, but the difference is that the error message from AST
|
||||||
// contains the error token location (by lines and columns), which is hardly
|
// contains the error token location (by lines and columns), which is hardly
|
||||||
// to get from Classic query translator --stliu
|
// to get from Classic query translator --stliu
|
||||||
assertTranslation( "from Customer c, in(c.orders)" );
|
assertTranslation( "from Customer c, in(c.orders)" );
|
||||||
}
|
}
|
||||||
|
@ -254,24 +256,24 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
// is not a correlated subquery. HHH-1248
|
// is not a correlated subquery. HHH-1248
|
||||||
assertTranslation(
|
assertTranslation(
|
||||||
"select a.id, a.description" +
|
"select a.id, a.description" +
|
||||||
" from Animal a" +
|
" from Animal a" +
|
||||||
" left join a.offspring" +
|
" left join a.offspring" +
|
||||||
" where a in (" +
|
" where a in (" +
|
||||||
" select a1 from Animal a1" +
|
" select a1 from Animal a1" +
|
||||||
" left join a1.offspring o" +
|
" left join a1.offspring o" +
|
||||||
" where a1.id=1" +
|
" where a1.id=1" +
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
assertTranslation(
|
assertTranslation(
|
||||||
"select h.id, h.description" +
|
"select h.id, h.description" +
|
||||||
" from Human h" +
|
" from Human h" +
|
||||||
" left join h.friends" +
|
" left join h.friends" +
|
||||||
" where h in (" +
|
" where h in (" +
|
||||||
" select h1" +
|
" select h1" +
|
||||||
" from Human h1" +
|
" from Human h1" +
|
||||||
" left join h1.friends f" +
|
" left join h1.friends f" +
|
||||||
" where h1.id=1" +
|
" where h1.id=1" +
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,8 +322,8 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
|
|
||||||
private void check(
|
private void check(
|
||||||
ReturnMetadata returnMetadata,
|
ReturnMetadata returnMetadata,
|
||||||
boolean expectingEmptyTypes,
|
boolean expectingEmptyTypes,
|
||||||
boolean expectingEmptyAliases) {
|
boolean expectingEmptyAliases) {
|
||||||
assertNotNull( "null return metadata", returnMetadata );
|
assertNotNull( "null return metadata", returnMetadata );
|
||||||
assertNotNull( "null return metadata - types", returnMetadata );
|
assertNotNull( "null return metadata - types", returnMetadata );
|
||||||
assertEquals( "unexpected return size", 1, returnMetadata.getReturnTypes().length );
|
assertEquals( "unexpected return size", 1, returnMetadata.getReturnTypes().length );
|
||||||
|
@ -381,7 +383,7 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
assertTranslation("from Animal where abs(:x - :y) < 2.0" );
|
assertTranslation("from Animal where abs(:x - :y) < 2.0" );
|
||||||
assertTranslation("from Animal where lower(upper(:foo)) like 'f%'" );
|
assertTranslation("from Animal where lower(upper(:foo)) like 'f%'" );
|
||||||
if ( ! ( getDialect() instanceof SybaseDialect ) && ! ( getDialect() instanceof Sybase11Dialect ) && ! ( getDialect() instanceof SybaseASE15Dialect ) && ! ( getDialect() instanceof SQLServerDialect ) && ! ( getDialect() instanceof TeradataDialect ) ) {
|
if ( ! ( getDialect() instanceof SybaseDialect ) && ! ( getDialect() instanceof Sybase11Dialect ) && ! ( getDialect() instanceof SybaseASE15Dialect ) && ! ( getDialect() instanceof SQLServerDialect ) && ! ( getDialect() instanceof TeradataDialect ) ) {
|
||||||
// Transact-SQL dialects (except SybaseAnywhereDialect) map the length function -> len;
|
// Transact-SQL dialects (except SybaseAnywhereDialect) map the length function -> len;
|
||||||
// classic translator does not consider that *when nested*;
|
// classic translator does not consider that *when nested*;
|
||||||
// SybaseAnywhereDialect supports the length function
|
// SybaseAnywhereDialect supports the length function
|
||||||
|
|
||||||
|
@ -505,10 +507,10 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-719" )
|
@TestForIssue( jiraKey = "HHH-719" )
|
||||||
public void testHHH719() throws Exception {
|
public void testHHH719() throws Exception {
|
||||||
assertTranslation("from Baz b order by org.bazco.SpecialFunction(b.id)");
|
assertTranslation("from Baz b order by org.bazco.SpecialFunction(b.id)");
|
||||||
assertTranslation("from Baz b order by anypackage.anyFunction(b.id)");
|
assertTranslation("from Baz b order by anypackage.anyFunction(b.id)");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParameterListExpansion() {
|
public void testParameterListExpansion() {
|
||||||
|
@ -530,22 +532,22 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
@TestForIssue( jiraKey = "HHH-557" )
|
@TestForIssue( jiraKey = "HHH-557" )
|
||||||
public void testExplicitJoinsInSubquery() {
|
public void testExplicitJoinsInSubquery() {
|
||||||
assertTranslation(
|
assertTranslation(
|
||||||
"from org.hibernate.test.hql.Animal as animal " +
|
"from org.hibernate.test.hql.Animal as animal " +
|
||||||
"where animal.id in (" +
|
"where animal.id in (" +
|
||||||
" select a.id " +
|
" select a.id " +
|
||||||
" from org.hibernate.test.hql.Animal as a " +
|
" from org.hibernate.test.hql.Animal as a " +
|
||||||
" left join a.mother as mo" +
|
" left join a.mother as mo" +
|
||||||
")"
|
")"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImplicitJoinsInGroupBy() {
|
public void testImplicitJoinsInGroupBy() {
|
||||||
assertTranslation(
|
assertTranslation(
|
||||||
"select o.mother.bodyWeight, count(distinct o) " +
|
"select o.mother.bodyWeight, count(distinct o) " +
|
||||||
"from Animal an " +
|
"from Animal an " +
|
||||||
" join an.offspring as o " +
|
" join an.offspring as o " +
|
||||||
"group by o.mother.bodyWeight"
|
"group by o.mother.bodyWeight"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,6 +572,7 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore( "Old parser generated incorrect SQL for `size()`")
|
||||||
public void testSizeFunctionAndProperty() {
|
public void testSizeFunctionAndProperty() {
|
||||||
assertTranslation("from Animal a where a.offspring.size > 0");
|
assertTranslation("from Animal a where a.offspring.size > 0");
|
||||||
assertTranslation("from Animal a join a.offspring where a.offspring.size > 1");
|
assertTranslation("from Animal a join a.offspring where a.offspring.size > 1");
|
||||||
|
@ -623,16 +626,9 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
assertTranslation( "from Simple s where s = some( select sim from Simple sim where sim.other.count=s.other.count )" );
|
assertTranslation( "from Simple s where s = some( select sim from Simple sim where sim.other.count=s.other.count )" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testCollectionOfValuesSize() throws Exception {
|
|
||||||
//SQL *was* missing a comma
|
|
||||||
assertTranslation( "select size(baz.stringDateMap) from org.hibernate.test.legacy.Baz baz" );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCollectionFunctions() throws Exception {
|
public void testCollectionFunctions() throws Exception {
|
||||||
//these are both broken, a join that belongs in the subselect finds its way into the main query
|
//these are both broken, a join that belongs in the subselect finds its way into the main query
|
||||||
assertTranslation( "from Zoo zoo where size(zoo.animals) > 100" );
|
|
||||||
assertTranslation( "from Zoo zoo where maxindex(zoo.mammals) = 'dog'" );
|
assertTranslation( "from Zoo zoo where maxindex(zoo.mammals) = 'dog'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,8 +646,10 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCollectionSize() throws Exception {
|
@Ignore( "The old parser generated incorrect SQL for selection of size functions" )
|
||||||
|
public void testCollectionSizeSelection() throws Exception {
|
||||||
assertTranslation( "select size(zoo.animals) from Zoo zoo" );
|
assertTranslation( "select size(zoo.animals) from Zoo zoo" );
|
||||||
|
assertTranslation( "select size(baz.stringDateMap) from org.hibernate.test.legacy.Baz baz" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -1016,9 +1014,9 @@ public class HQLTest extends QueryTranslatorTestCase {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestForIssue( jiraKey = "HHH-559" )
|
@TestForIssue( jiraKey = "HHH-559" )
|
||||||
public void testMultibyteCharacterConstant() throws Exception {
|
public void testMultibyteCharacterConstant() throws Exception {
|
||||||
assertTranslation( "from Zoo zoo join zoo.animals an where an.description like '%\u4e2d%'" );
|
assertTranslation( "from Zoo zoo join zoo.animals an where an.description like '%\u4e2d%'" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testImplicitJoins() throws Exception {
|
public void testImplicitJoins() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue