protected AST lookupProperty(AST dot, boolean root, boolean inSelect) throws SemanticException { DotNode dotNode = (DotNode) dot; FromReferenceNode lhs = dotNode.getLhs(); AST rhs = lhs.getNextSibling(); switch (rhs.getType()) { case SqlTokenTypes.ELEMENTS: case SqlTokenTypes.INDICES: if (log.isDebugEnabled()) { log.debug( "lookupProperty() " + dotNode.getPath() + " => " + rhs.getText() + "(" + lhs.getPath() + ")"); } CollectionFunction f = (CollectionFunction) rhs; // Re-arrange the tree so that the collection function is the root and the lhs is the path. f.setFirstChild(lhs); lhs.setNextSibling(null); dotNode.setFirstChild(f); resolve(lhs); // Don't forget to resolve the argument! f.resolve(inSelect); // Resolve the collection function now. return f; default: // Resolve everything up to this dot, but don't resolve the placeholders yet. dotNode.resolveFirstChild(); return dotNode; } }
public void visit(AST node) { // todo : currently expects that the individual with expressions apply to the same sql table // join. // This may not be the case for joined-subclass where the property values // might be coming from different tables in the joined hierarchy. At some // point we should expand this to support that capability. However, that has // some difficulties: // 1) the biggest is how to handle ORs when the individual comparisons are // linked to different sql joins. // 2) here we would need to track each comparison individually, along with // the join alias to which it applies and then pass that information // back to the FromElement so it can pass it along to the JoinSequence if (node instanceof DotNode) { DotNode dotNode = (DotNode) node; FromElement fromElement = dotNode.getFromElement(); if (referencedFromElement != null) { if (fromElement != referencedFromElement) { throw new HibernateException( "with-clause referenced two different from-clause elements"); } } else { referencedFromElement = fromElement; joinAlias = extractAppliedAlias(dotNode); // todo : temporary // needed because currently persister is the one that // creates and renders the join fragments for inheritence // hierarchies... if (!joinAlias.equals(referencedFromElement.getTableAlias())) { throw new HibernateException( "with clause can only reference columns in the driving table"); } } } }
protected void createFromJoinElement( AST path, AST alias, int joinType, AST fetchNode, AST propertyFetch, AST with) throws SemanticException { boolean fetch = fetchNode != null; if (fetch && isSubQuery()) { throw new QueryException("fetch not allowed in subquery from-elements"); } // The path AST should be a DotNode, and it should have been evaluated already. if (path.getType() != SqlTokenTypes.DOT) { throw new SemanticException("Path expected for join!"); } DotNode dot = (DotNode) path; int hibernateJoinType = JoinProcessor.toHibernateJoinType(joinType); dot.setJoinType(hibernateJoinType); // Tell the dot node about the join type. dot.setFetch(fetch); // Generate an explicit join for the root dot node. The implied joins will be collected and // passed up // to the root dot node. dot.resolve(true, false, alias == null ? null : alias.getText()); FromElement fromElement = dot.getImpliedJoin(); fromElement.setAllPropertyFetch(propertyFetch != null); if (with != null) { if (fetch) { throw new SemanticException("with-clause not allowed on fetched associations; use filters"); } handleWithFragment(fromElement, with); } if (log.isDebugEnabled()) { log.debug( "createFromJoinElement() : " + getASTPrinter().showAsString(fromElement, "-- join tree --")); } }
protected void resolveSelectExpression(AST node) throws SemanticException { // This is called when it's time to fully resolve a path expression. int type = node.getType(); switch (type) { case DOT: DotNode dot = (DotNode) node; dot.resolveSelectExpression(); break; case ALIAS_REF: // Notify the FROM element that it is being referenced by the select. FromReferenceNode aliasRefNode = (FromReferenceNode) node; // aliasRefNode.resolve( false, false, aliasRefNode.getText() ); //TODO: is it kosher to do // it here? aliasRefNode.resolve(false, false); // TODO: is it kosher to do it here? FromElement fromElement = aliasRefNode.getFromElement(); if (fromElement != null) { fromElement.setIncludeSubclasses(true); } default: break; } }
private AST generateSyntheticDotNodeForNonQualifiedPropertyRef( AST property, FromElement fromElement) { AST dot = getASTFactory().create(DOT, "{non-qualified-property-ref}"); // TODO : better way?!? ((DotNode) dot).setPropertyPath(((FromReferenceNode) property).getPath()); IdentNode syntheticAlias = (IdentNode) getASTFactory().create(IDENT, "{synthetic-alias}"); syntheticAlias.setFromElement(fromElement); syntheticAlias.setResolved(); dot.setFirstChild(syntheticAlias); dot.addChild(property); return dot; }
private String extractAppliedAlias(DotNode dotNode) { return dotNode.getText().substring(0, dotNode.getText().indexOf('.')); }