use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.
the class QueryTranslatorImpl method addFromAssociation.
/**
* Used for collection filters
*/
private void addFromAssociation(final String elementName, final String collectionRole) throws QueryException {
//q.addCollection(collectionName, collectionRole);
QueryableCollection persister = getCollectionPersister(collectionRole);
Type collectionElementType = persister.getElementType();
if (!collectionElementType.isEntityType()) {
throw new QueryException("collection of values in filter: " + elementName);
}
String[] keyColumnNames = persister.getKeyColumnNames();
//if (keyColumnNames.length!=1) throw new QueryException("composite-key collection in filter: " + collectionRole);
String collectionName;
JoinSequence join = new JoinSequence(getFactory());
collectionName = persister.isOneToMany() ? elementName : createNameForCollection(collectionRole);
join.setRoot(persister, collectionName);
if (!persister.isOneToMany()) {
//many-to-many
addCollection(collectionName, collectionRole);
try {
join.addJoin((AssociationType) persister.getElementType(), elementName, JoinType.INNER_JOIN, persister.getElementColumnNames(collectionName));
} catch (MappingException me) {
throw new QueryException(me);
}
}
join.addCondition(collectionName, keyColumnNames, " = ?");
//if ( persister.hasWhere() ) join.addCondition( persister.getSQLWhereString(collectionName) );
EntityType elemType = (EntityType) collectionElementType;
addFrom(elementName, elemType.getAssociatedEntityName(), join);
}
use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.
the class QueryTranslatorImpl method mergeJoins.
private void mergeJoins(JoinFragment ojf) throws MappingException, QueryException {
Iterator iter = joins.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry me = (Map.Entry) iter.next();
String name = (String) me.getKey();
JoinSequence join = (JoinSequence) me.getValue();
join.setSelector(new JoinSequence.Selector() {
@Override
public boolean includeSubclasses(String alias) {
return returnedTypes.contains(alias) && !isShallowQuery();
}
});
if (typeMap.containsKey(name)) {
ojf.addFragment(join.toJoinFragment(enabledFilters, true));
} else if (collections.containsKey(name)) {
ojf.addFragment(join.toJoinFragment(enabledFilters, true));
}
}
}
use of org.hibernate.engine.internal.JoinSequence in project hibernate-orm by hibernate.
the class JoinProcessor method processJoins.
public void processJoins(QueryNode query) {
final FromClause fromClause = query.getFromClause();
final List fromElements;
if (DotNode.useThetaStyleImplicitJoins) {
// for regression testing against output from the old parser...
// found it easiest to simply reorder the FromElements here into ascending order
// in terms of injecting them into the resulting sql ast in orders relative to those
// expected by the old parser; this is definitely another of those "only needed
// for regression purposes". The SyntheticAndFactory, then, simply injects them as it
// encounters them.
fromElements = new ArrayList();
ListIterator liter = fromClause.getFromElements().listIterator(fromClause.getFromElements().size());
while (liter.hasPrevious()) {
fromElements.add(liter.previous());
}
} else {
fromElements = new ArrayList(fromClause.getFromElements().size());
ListIterator<FromElement> liter = fromClause.getFromElements().listIterator();
while (liter.hasNext()) {
FromElement fromElement = liter.next();
// We found an implied from element that is used in the WITH clause of another from element, so it need to become part of it's join sequence
if (fromElement instanceof ImpliedFromElement && fromElement.getOrigin().getWithClauseFragment() != null && fromElement.getOrigin().getWithClauseFragment().contains(fromElement.getTableAlias())) {
fromElement.getOrigin().getJoinSequence().addJoin((ImpliedFromElement) fromElement);
// This from element will be rendered as part of the origins join sequence
fromElement.setText("");
} else {
fromElements.add(fromElement);
}
}
}
// Iterate through the alias,JoinSequence pairs and generate SQL token nodes.
Iterator iter = fromElements.iterator();
while (iter.hasNext()) {
final FromElement fromElement = (FromElement) iter.next();
JoinSequence join = fromElement.getJoinSequence();
join.setSelector(new JoinSequence.Selector() {
public boolean includeSubclasses(String alias) {
// The uber-rule here is that we need to include subclass joins if
// the FromElement is in any way dereferenced by a property from
// the subclass table; otherwise we end up with column references
// qualified by a non-existent table reference in the resulting SQL...
boolean containsTableAlias = fromClause.containsTableAlias(alias);
if (fromElement.isDereferencedBySubclassProperty()) {
// TODO : or should we return 'containsTableAlias'??
LOG.tracev("Forcing inclusion of extra joins [alias={0}, containsTableAlias={1}]", alias, containsTableAlias);
return true;
}
boolean shallowQuery = walker.isShallowQuery();
boolean includeSubclasses = fromElement.isIncludeSubclasses();
boolean subQuery = fromClause.isSubQuery();
return includeSubclasses && containsTableAlias && !subQuery && !shallowQuery;
}
});
addJoinNodes(query, join, fromElement);
}
}
use of org.hibernate.engine.internal.JoinSequence 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.engine.internal.JoinSequence in project hibernate-orm by hibernate.
the class DotNode method dereferenceEntityJoin.
private void dereferenceEntityJoin(String classAlias, EntityType propertyType, boolean impliedJoin, AST parent) throws SemanticException {
dereferenceType = DereferenceType.ENTITY;
if (LOG.isDebugEnabled()) {
LOG.debugf("dereferenceEntityJoin() : generating join for %s in %s (%s) parent = %s", propertyName, getFromElement().getClassName(), classAlias == null ? "<no alias>" : classAlias, ASTUtil.getDebugString(parent));
}
// Create a new FROM node for the referenced class.
String associatedEntityName = propertyType.getAssociatedEntityName();
String tableAlias = getAliasGenerator().createName(associatedEntityName);
String[] joinColumns = getColumns();
String joinPath = getPath();
if (impliedJoin && getWalker().isInFrom()) {
joinType = getWalker().getImpliedJoinType();
}
FromClause currentFromClause = getWalker().getCurrentFromClause();
FromElement elem = currentFromClause.findJoinByPath(joinPath);
///////////////////////////////////////////////////////////////////////////////
//
// This is the piece which recognizes the condition where an implicit join path
// resolved earlier in a correlated subquery is now being referenced in the
// outer query. For 3.0final, we just let this generate a second join (which
// is exactly how the old parser handles this). Eventually we need to add this
// logic back in and complete the logic in FromClause.promoteJoin; however,
// FromClause.promoteJoin has its own difficulties (see the comments in
// FromClause.promoteJoin).
//
// if ( elem == null ) {
// // see if this joinPath has been used in a "child" FromClause, and if so
// // promote that element to the outer query
// FromClause currentNodeOwner = getFromElement().getFromClause();
// FromClause currentJoinOwner = currentNodeOwner.locateChildFromClauseWithJoinByPath( joinPath );
// if ( currentJoinOwner != null && currentNodeOwner != currentJoinOwner ) {
// elem = currentJoinOwner.findJoinByPathLocal( joinPath );
// if ( elem != null ) {
// currentFromClause.promoteJoin( elem );
// // EARLY EXIT!!!
// return;
// }
// }
// }
//
///////////////////////////////////////////////////////////////////////////////
boolean found = elem != null;
// even though we might find a pre-existing element by join path, we may not be able to reuse it...
boolean useFoundFromElement = found && canReuse(classAlias, elem);
if (!useFoundFromElement) {
// If this is an implied join in a from element, then use the impled join type which is part of the
// tree parser's state (set by the gramamar actions).
JoinSequence joinSequence = getSessionFactoryHelper().createJoinSequence(impliedJoin, propertyType, tableAlias, joinType, joinColumns);
// If the lhs of the join is a "component join", we need to go back to the
// first non-component-join as the origin to properly link aliases and
// join columns
FromElement lhsFromElement = getLhs().getFromElement();
while (lhsFromElement != null && ComponentJoin.class.isInstance(lhsFromElement)) {
lhsFromElement = lhsFromElement.getOrigin();
}
if (lhsFromElement == null) {
throw new QueryException("Unable to locate appropriate lhs");
}
String role = lhsFromElement.getClassName() + "." + propertyName;
FromElementFactory factory = new FromElementFactory(currentFromClause, lhsFromElement, joinPath, classAlias, joinColumns, impliedJoin);
elem = factory.createEntityJoin(associatedEntityName, tableAlias, joinSequence, fetch, getWalker().isInFrom(), propertyType, role, joinPath);
} else {
// NOTE : addDuplicateAlias() already performs nullness checks on the alias.
currentFromClause.addDuplicateAlias(classAlias, elem);
}
setImpliedJoin(elem);
getWalker().addQuerySpaces(elem.getEntityPersister().getQuerySpaces());
// This 'dot' expression now refers to the resulting from element.
setFromElement(elem);
}
Aggregations