📄 dotnode.java
字号:
}
if ( joinIsNeeded ) {
dereferenceEntityJoin( classAlias, entityType, implicitJoin, parent );
}
else {
dereferenceEntityIdentifier( property, parentAsDotNode );
}
}
private boolean unresolvedComponent(boolean generateJoin) {
AST c = getFirstChild();
if ( generateJoin && isDotNode( c ) ) {
DotNode dot = ( DotNode ) c;
if ( dot.dereferenceType == DEREF_COMPONENT || dot.dereferenceType == DEREF_IDENTIFIER ) {
if ( StringHelper.isNotEmpty( propertyPath ) ) {
return true;
}
}
}
return false;
}
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() ) {
int impliedJoinType = getWalker().getImpliedJoinType();
joinType = impliedJoinType;
}
FromClause currentFromClause = getWalker().getCurrentFromClause();
FromElement elem = null;
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;
}
private boolean isReferenceToPrimaryKey(String propertyName, EntityType propertyType) {
if ( EntityPersister.ENTITY_ID.equals( propertyName ) ) {
// the referenced node text is the special 'id'
return propertyType.isReferenceToPrimaryKey();
}
else {
String keyPropertyName = getSessionFactoryHelper()
.getIdentifierOrUniqueKeyPropertyName( propertyType );
return keyPropertyName != null && keyPropertyName.equals( propertyName );
}
}
// private boolean isPrimaryKeyReference(String property, EntityType propertyType) {
// boolean isIdShortcut = EntityPersister.ENTITY_ID.equals( property ) &&
// propertyType.isReferenceToPrimaryKey();
// return isIdShortcut;
// }
//
// private boolean isNamedIdPropertyShortcut(EntityType propertyType, String property) {
// final String idPropertyName = getSessionFactoryHelper()
// .getIdentifierOrUniqueKeyPropertyName( propertyType );
// boolean isNamedIdPropertyShortcut = idPropertyName != null &&
// idPropertyName.equals( property );
// return isNamedIdPropertyShortcut;
// }
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() ) {
// TODO : this exactly matches the output of the old parser, but we might want to be more explicit here
// that will however cause regression issues in HQLTest
throw new SemanticException( "illegal syntax near collection: " + propertyName );
}
}
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 {
// Handle "select foo.component from Foo foo", or even "where foo.component = bar.component"
AST lhs = getFirstChild();
AST rhs = lhs.getNextSibling();
propertyPath = rhs.getText();
}
}
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 );
}
}
}
}
}
/**
* Used ONLY for regression testing!
*/
public static boolean useThetaStyleImplicitJoins = false;
public void setResolvedConstant(String text) {
path = text;
dereferenceType = DEREF_JAVA_CONSTANT;
setResolved(); // Don't resolve the node again.
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -