📄 dotnode.java
字号:
property = parentAsDotNode.propertyName; joinIsNeeded = generateJoin && !isReferenceToPrimaryKey( parentAsDotNode.propertyName, entityType ); } else if ( ! getWalker().isSelectStatement() ) { // in non-select queries, the only time we should need to join is if we are in a subquery from clause joinIsNeeded = getWalker().getCurrentStatementType() == SqlTokenTypes.SELECT && getWalker().isInFrom(); } else if ( REGRESSION_STYLE_JOIN_SUPPRESSION ) { // this is the regression style determination which matches the logic of the classic translator joinIsNeeded = generateJoin && ( !getWalker().isInSelect() || !getWalker().isShallowQuery() ); } else { joinIsNeeded = generateJoin || ( getWalker().isInSelect() || getWalker().isInFrom() ); } if ( joinIsNeeded ) { dereferenceEntityJoin( classAlias, entityType, implicitJoin, parent ); } else { dereferenceEntityIdentifier( property, parentAsDotNode ); } } private boolean isDotNode(AST n) { return n != null && n.getType() == SqlTokenTypes.DOT; } private void dereferenceEntityJoin(String classAlias, EntityType propertyType, boolean impliedJoin, AST parent) throws SemanticException { dereferenceType = DEREF_ENTITY; if ( log.isDebugEnabled() ) { log.debug( "dereferenceEntityJoin() : generating join for " + propertyName + " in " + getFromElement().getClassName() + " " + ( ( classAlias == null ) ? "{no alias}" : "(" + classAlias + ")" ) + " parent = " + 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;// }// }// }///////////////////////////////////////////////////////////////////////////////// if ( elem == null ) { // 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 ); FromElementFactory factory = new FromElementFactory( currentFromClause, getLhs().getFromElement(), joinPath, classAlias, joinColumns, impliedJoin ); elem = factory.createEntityJoin( associatedEntityName, tableAlias, joinSequence, fetch, getWalker().isInFrom(), propertyType ); } else { currentFromClause.addDuplicateAlias(classAlias, elem); } setImpliedJoin( elem ); getWalker().addQuerySpaces( elem.getEntityPersister().getQuerySpaces() ); setFromElement( elem ); // This 'dot' expression now refers to the resulting from element. } private void setImpliedJoin(FromElement elem) { this.impliedJoin = elem; if ( getFirstChild().getType() == SqlTokenTypes.DOT ) { DotNode dotLhs = ( DotNode ) getFirstChild(); if ( dotLhs.getImpliedJoin() != null ) { this.impliedJoin = dotLhs.getImpliedJoin(); } } } public FromElement getImpliedJoin() { return impliedJoin; } /** * Is the given property name a reference to the primary key of the associated * entity construed by the given entity type? * <p/> * For example, consider a fragment like order.customer.id * (where order is a from-element alias). Here, we'd have: * propertyName = "id" AND * owningType = ManyToOneType(Customer) * and are being asked to determine whether "customer.id" is a reference * to customer's PK... * * @param propertyName The name of the property to check. * @param owningType The type represeting the entity "owning" the property * @return True if propertyName references the entity's (owningType->associatedEntity) * primary key; false otherwise. */ private boolean isReferenceToPrimaryKey(String propertyName, EntityType owningType) { EntityPersister persister = getSessionFactoryHelper() .getFactory() .getEntityPersister( owningType.getAssociatedEntityName() ); if ( persister.getEntityMetamodel().hasNonIdentifierPropertyNamedId() ) { // only the identifier property field name can be a reference to the associated entity's PK... return propertyName.equals( persister.getIdentifierPropertyName() ) && owningType.isReferenceToPrimaryKey(); } else { // here, we have two possibilities: // 1) the property-name matches the explicitly identifier property name // 2) the property-name matches the implicit 'id' property name if ( EntityPersister.ENTITY_ID.equals( propertyName ) ) { // the referenced node text is the special 'id' return owningType.isReferenceToPrimaryKey(); } else { String keyPropertyName = getSessionFactoryHelper().getIdentifierOrUniqueKeyPropertyName( owningType ); return keyPropertyName != null && keyPropertyName.equals( propertyName ) && owningType.isReferenceToPrimaryKey(); } } } private void checkForCorrelatedSubquery(String methodName) { if ( isCorrelatedSubselect() ) { if ( log.isDebugEnabled() ) { log.debug( methodName + "() : correlated subquery" ); } } } private boolean isCorrelatedSubselect() { return getWalker().isSubQuery() && getFromElement().getFromClause() != getWalker().getCurrentFromClause(); } private void checkLhsIsNotCollection() throws SemanticException { if ( getLhs().getDataType() != null && getLhs().getDataType().isCollectionType() ) { throw ILLEGAL_COLL_DEREF_EXCP_BUILDER.buildIllegalCollectionDereferenceException( propertyName, getLhs() ); } } private void dereferenceComponent(AST parent) { dereferenceType = DEREF_COMPONENT; setPropertyNameAndPath( parent ); } private void dereferenceEntityIdentifier(String propertyName, DotNode dotParent) { // special shortcut for id properties, skip the join! // this must only occur at the _end_ of a path expression if ( log.isDebugEnabled() ) { log.debug( "dereferenceShortcut() : property " + propertyName + " in " + getFromElement().getClassName() + " does not require a join." ); } initText(); setPropertyNameAndPath( dotParent ); // Set the unresolved path in this node and the parent. // Set the text for the parent. if ( dotParent != null ) { dotParent.dereferenceType = DEREF_IDENTIFIER; dotParent.setText( getText() ); dotParent.columns = getColumns(); } } private void setPropertyNameAndPath(AST parent) { if ( isDotNode( parent ) ) { DotNode dotNode = ( DotNode ) parent; AST lhs = dotNode.getFirstChild(); AST rhs = lhs.getNextSibling(); propertyName = rhs.getText(); propertyPath = propertyPath + "." + propertyName; // Append the new property name onto the unresolved path. dotNode.propertyPath = propertyPath; if ( log.isDebugEnabled() ) { log.debug( "Unresolved property path is now '" + dotNode.propertyPath + "'" ); } } else { if ( log.isDebugEnabled() ) { log.debug( "terminal propertyPath = [" + propertyPath + "]" ); } } } public Type getDataType() { if ( super.getDataType() == null ) { FromElement fromElement = getLhs().getFromElement(); if ( fromElement == null ) { return null; } // If the lhs is a collection, use CollectionPropertyMapping Type propertyType = fromElement.getPropertyType( propertyName, propertyPath ); if ( log.isDebugEnabled() ) { log.debug( "getDataType() : " + propertyPath + " -> " + propertyType ); } super.setDataType( propertyType ); } return super.getDataType(); } public void setPropertyPath(String propertyPath) { this.propertyPath = propertyPath; } public String getPropertyPath() { return propertyPath; } public FromReferenceNode getLhs() { FromReferenceNode lhs = ( ( FromReferenceNode ) getFirstChild() ); if ( lhs == null ) { throw new IllegalStateException( "DOT node with no left-hand-side!" ); } return lhs; } /** * Returns the full path of the node. * * @return the full path of the node. */ public String getPath() { if ( path == null ) { FromReferenceNode lhs = getLhs(); if ( lhs == null ) { path = getText(); } else { SqlNode rhs = ( SqlNode ) lhs.getNextSibling(); path = lhs.getPath() + "." + rhs.getOriginalText(); } } return path; } public void setFetch(boolean fetch) { this.fetch = fetch; } public void setScalarColumnText(int i) throws SemanticException { String[] sqlColumns = getColumns(); ColumnHelper.generateScalarColumns( this, sqlColumns, i ); } /** * Special method to resolve expressions in the SELECT list. * * @throws SemanticException if this cannot be resolved. */ public void resolveSelectExpression() throws SemanticException { if ( getWalker().isShallowQuery() || getWalker().getCurrentFromClause().isSubQuery() ) { resolve(false, true); } else { resolve(true, false); Type type = getDataType(); if ( type.isEntityType() ) { FromElement fromElement = getFromElement(); fromElement.setIncludeSubclasses( true ); // Tell the destination fromElement to 'includeSubclasses'. if ( useThetaStyleImplicitJoins ) { fromElement.getJoinSequence().setUseThetaStyle( true ); // Use theta style (for regression) // Move the node up, after the origin node. FromElement origin = fromElement.getOrigin(); if ( origin != null ) { ASTUtil.makeSiblingOfParent( origin, fromElement ); } } } } FromReferenceNode lhs = getLhs(); while ( lhs != null ) { checkSubclassOrSuperclassPropertyReference( lhs, lhs.getNextSibling().getText() ); lhs = ( FromReferenceNode ) lhs.getFirstChild(); } } public void setResolvedConstant(String text) { path = text; dereferenceType = DEREF_JAVA_CONSTANT; setResolved(); // Don't resolve the node again. } private boolean checkSubclassOrSuperclassPropertyReference(FromReferenceNode lhs, String propertyName) { if ( lhs != null && !( lhs instanceof IndexNode ) ) { final FromElement source = lhs.getFromElement(); if ( source != null ) { source.handlePropertyBeingDereferenced( lhs.getDataType(), propertyName ); } } return false; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -