use of org.hibernate.type.CollectionType in project hibernate-orm by hibernate.
the class IndexNode method resolve.
@Override
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException {
if (isResolved()) {
return;
}
FromReferenceNode collectionNode = (FromReferenceNode) getFirstChild();
SessionFactoryHelper sessionFactoryHelper = getSessionFactoryHelper();
// Fully resolve the map reference, create implicit joins.
collectionNode.resolveIndex(this);
Type type = collectionNode.getDataType();
if (!type.isCollectionType()) {
throw new SemanticException("The [] operator cannot be applied to type " + type.toString());
}
String collectionRole = ((CollectionType) type).getRole();
QueryableCollection queryableCollection = sessionFactoryHelper.requireQueryableCollection(collectionRole);
if (!queryableCollection.hasIndex()) {
throw new QueryException("unindexed fromElement beforeQuery []: " + collectionNode.getPath());
}
// Generate the inner join -- The elements need to be joined to the collection they are in.
FromElement fromElement = collectionNode.getFromElement();
String elementTable = fromElement.getTableAlias();
FromClause fromClause = fromElement.getFromClause();
String path = collectionNode.getPath();
FromElement elem = fromClause.findCollectionJoin(path);
if (elem == null) {
FromElementFactory factory = new FromElementFactory(fromClause, fromElement, path);
elem = factory.createCollectionElementsJoin(queryableCollection, elementTable);
LOG.debugf("No FROM element found for the elements of collection join path %s, created %s", path, elem);
} else {
LOG.debugf("FROM element found for collection join path %s", path);
}
// The 'from element' that represents the elements of the collection.
setFromElement(fromElement);
// Add the condition to the join sequence that qualifies the indexed element.
AST selector = collectionNode.getNextSibling();
if (selector == null) {
throw new QueryException("No index value!");
}
// Sometimes use the element table alias, sometimes use the... umm... collection table alias (many to many)
String collectionTableAlias = elementTable;
if (elem.getCollectionTableAlias() != null) {
collectionTableAlias = elem.getCollectionTableAlias();
}
// TODO: get SQL rendering out of here, create an AST for the join expressions.
// Use the SQL generator grammar to generate the SQL text for the index expression.
JoinSequence joinSequence = fromElement.getJoinSequence();
String[] indexCols = queryableCollection.getIndexColumnNames();
if (indexCols.length != 1) {
throw new QueryException("composite-index appears in []: " + collectionNode.getPath());
}
SqlGenerator gen = new SqlGenerator(getSessionFactoryHelper().getFactory());
try {
//TODO: used to be exprNoParens! was this needed?
gen.simpleExpr(selector);
} catch (RecognitionException e) {
throw new QueryException(e.getMessage(), e);
}
String selectorExpression = gen.getSQL();
joinSequence.addCondition(collectionTableAlias + '.' + indexCols[0] + " = " + selectorExpression);
List<ParameterSpecification> paramSpecs = gen.getCollectedParameters();
if (paramSpecs != null) {
switch(paramSpecs.size()) {
case 0:
// nothing to do
break;
case 1:
ParameterSpecification paramSpec = paramSpecs.get(0);
paramSpec.setExpectedType(queryableCollection.getIndexType());
fromElement.setIndexCollectionSelectorParamSpec(paramSpec);
break;
default:
fromElement.setIndexCollectionSelectorParamSpec(new AggregatedIndexCollectionSelectorParameterSpecifications(paramSpecs));
break;
}
}
// Now, set the text for this node. It should be the element columns.
String[] elementColumns = queryableCollection.getElementColumnNames(elementTable);
setText(elementColumns[0]);
setResolved();
}
use of org.hibernate.type.CollectionType in project hibernate-orm by hibernate.
the class AbstractMapComponentNode method resolve.
@Override
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException {
if (mapFromElement == null) {
final FromReferenceNode mapReference = getMapReference();
mapReference.resolve(true, true);
FromElement sourceFromElement = null;
if (isAliasRef(mapReference)) {
final QueryableCollection collectionPersister = mapReference.getFromElement().getQueryableCollection();
if (Map.class.isAssignableFrom(collectionPersister.getCollectionType().getReturnedClass())) {
sourceFromElement = mapReference.getFromElement();
}
} else {
if (mapReference.getDataType().isCollectionType()) {
final CollectionType collectionType = (CollectionType) mapReference.getDataType();
if (Map.class.isAssignableFrom(collectionType.getReturnedClass())) {
sourceFromElement = mapReference.getFromElement();
}
}
}
if (sourceFromElement == null) {
throw nonMap();
}
mapFromElement = sourceFromElement;
}
setFromElement(mapFromElement);
setDataType(resolveType(mapFromElement.getQueryableCollection()));
this.columns = resolveColumns(mapFromElement.getQueryableCollection());
initText(this.columns);
setFirstChild(null);
}
use of org.hibernate.type.CollectionType in project hibernate-orm by hibernate.
the class DotNode method resolve.
public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent, AST parentPredicate) throws SemanticException {
// If this dot has already been resolved, stop now.
if (isResolved()) {
return;
}
// Prepare the left hand side and get the data type.
Type propertyType = prepareLhs();
if (parent == null && AbstractEntityPersister.ENTITY_CLASS.equals(propertyName)) {
DeprecationLogger.DEPRECATION_LOGGER.logDeprecationOfClassEntityTypeSelector(getLhs().getPath());
}
// this might be a Java constant.
if (propertyType == null) {
if (parent == null) {
getWalker().getLiteralProcessor().lookupConstant(this);
}
// stop now... there was a problem resolving the node anyway.
return;
}
if (propertyType.isComponentType()) {
// The property is a component...
checkLhsIsNotCollection();
dereferenceComponent(parent);
initText();
} else if (propertyType.isEntityType()) {
// The property is another class..
checkLhsIsNotCollection();
dereferenceEntity((EntityType) propertyType, implicitJoin, classAlias, generateJoin, parent, parentPredicate);
initText();
} else if (propertyType.isCollectionType()) {
// The property is a collection...
checkLhsIsNotCollection();
dereferenceCollection((CollectionType) propertyType, implicitJoin, false, classAlias, parent);
} else {
// Otherwise, this is a primitive type.
if (!CollectionProperties.isAnyCollectionProperty(propertyName)) {
checkLhsIsNotCollection();
}
dereferenceType = DereferenceType.PRIMITIVE;
initText();
}
setResolved();
}
use of org.hibernate.type.CollectionType in project hibernate-orm by hibernate.
the class FromElementFactory method createElementJoin.
FromElement createElementJoin(QueryableCollection queryableCollection) throws SemanticException {
FromElement elem;
//TODO: always true for now, but not if we later decide to support elements() in the from clause
implied = true;
inElementsFunction = true;
Type elementType = queryableCollection.getElementType();
if (!elementType.isEntityType()) {
throw new IllegalArgumentException("Cannot create element join for a collection of non-entities!");
}
this.queryableCollection = queryableCollection;
SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper();
FromElement destination = null;
String tableAlias = null;
EntityPersister entityPersister = queryableCollection.getElementPersister();
tableAlias = fromClause.getAliasGenerator().createName(entityPersister.getEntityName());
String associatedEntityName = entityPersister.getEntityName();
EntityPersister targetEntityPersister = sfh.requireClassPersister(associatedEntityName);
// Create the FROM element for the target (the elements of the collection).
destination = createAndAddFromElement(associatedEntityName, classAlias, targetEntityPersister, (EntityType) queryableCollection.getElementType(), tableAlias);
// If the join is implied, then don't include sub-classes on the element.
if (implied) {
destination.setIncludeSubclasses(false);
}
fromClause.addCollectionJoinFromElementByPath(path, destination);
// origin.addDestination(destination);
// Add the query spaces.
fromClause.getWalker().addQuerySpaces(entityPersister.getQuerySpaces());
CollectionType type = queryableCollection.getCollectionType();
String role = type.getRole();
String roleAlias = origin.getTableAlias();
String[] targetColumns = sfh.getCollectionElementColumns(role, roleAlias);
AssociationType elementAssociationType = sfh.getElementAssociationType(type);
// Create the join element under the from element.
JoinType joinType = JoinType.INNER_JOIN;
JoinSequence joinSequence = sfh.createJoinSequence(implied, elementAssociationType, tableAlias, joinType, targetColumns);
elem = initializeJoin(path, destination, joinSequence, targetColumns, origin, false);
// The associated entity is implied, but it must be included in the FROM.
elem.setUseFromFragment(true);
// The collection alias is the role.
elem.setCollectionTableAlias(roleAlias);
return elem;
}
use of org.hibernate.type.CollectionType in project hibernate-orm by hibernate.
the class FromElementFactory method createCollection.
public FromElement createCollection(QueryableCollection queryableCollection, String role, JoinType joinType, boolean fetchFlag, boolean indexed) throws SemanticException {
if (!collection) {
throw new IllegalStateException("FromElementFactory not initialized for collections!");
}
this.inElementsFunction = indexed;
FromElement elem;
this.queryableCollection = queryableCollection;
collectionType = queryableCollection.getCollectionType();
String roleAlias = fromClause.getAliasGenerator().createName(role);
// Correlated subqueries create 'special' implied from nodes
// because correlated subselects can't use an ANSI-style join
boolean explicitSubqueryFromElement = fromClause.isSubQuery() && !implied;
if (explicitSubqueryFromElement) {
String pathRoot = StringHelper.root(path);
FromElement origin = fromClause.getFromElement(pathRoot);
if (origin == null || origin.getFromClause() != fromClause) {
implied = true;
}
}
// super-duper-classic-parser-regression-testing-mojo-magic...
if (explicitSubqueryFromElement && DotNode.useThetaStyleImplicitJoins) {
implied = true;
}
Type elementType = queryableCollection.getElementType();
if (elementType.isEntityType()) {
// A collection of entities...
elem = createEntityAssociation(role, roleAlias, joinType);
} else if (elementType.isComponentType()) {
// A collection of components...
JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
elem = createCollectionJoin(joinSequence, roleAlias);
} else {
// A collection of scalar elements...
JoinSequence joinSequence = createJoinSequence(roleAlias, joinType);
elem = createCollectionJoin(joinSequence, roleAlias);
}
elem.setRole(role);
elem.setQueryableCollection(queryableCollection);
// Don't include sub-classes for implied collection joins or subquery joins.
if (implied) {
elem.setIncludeSubclasses(false);
}
if (explicitSubqueryFromElement) {
// Treat explict from elements in sub-queries properly.
elem.setInProjectionList(true);
}
if (fetchFlag) {
elem.setFetch(true);
}
return elem;
}
Aggregations