📄 identnode.java
字号:
// $Id: IdentNode.java,v 1.28 2005/04/29 14:45:03 steveebersole Exp $package org.hibernate.hql.ast;import antlr.SemanticException;import antlr.collections.AST;import org.hibernate.dialect.function.SQLFunction;import org.hibernate.hql.antlr.SqlTokenTypes;import org.hibernate.type.Type;import org.hibernate.type.CollectionType;import org.hibernate.persister.entity.Queryable;import org.hibernate.persister.collection.QueryableCollection;import org.hibernate.util.StringHelper;import org.hibernate.sql.JoinFragment;import java.util.List;/** * Represents an identifier all by itself, which may be a function name, * a class alias, or a form of naked property-ref depending on the * context. * * @author josh Aug 16, 2004 7:20:55 AM */public class IdentNode extends FromReferenceNode implements SelectExpression { private static final int UNKNOWN = 0; private static final int PROPERTY_REF = 1; private static final int COMPONENT_REF = 2; private boolean nakedPropertyRef = false; private boolean root; public void setRoot() { root = true; } public void resolveIndex(AST parent) throws SemanticException { // An ident node can represent an index expression if the ident // represents a naked property ref // *Note: this makes the assumption (which is currently the case // in the hql-sql grammar) that the ident is first resolved // itself (addrExpr -> resolve()). The other option, if that // changes, is to call resolve from here; but it is // currently un-needed overhead. if ( !( isResolved() && nakedPropertyRef ) ) { throw new UnsupportedOperationException(); } String propertyName = getOriginalText(); if ( !getDataType().isCollectionType() ) { throw new SemanticException( "Collection expected; [" + propertyName + "] does not refer to a collection property" ); } // TODO : most of below was taken verbatim from DotNode; should either delegate this logic or super-type it CollectionType type = ( CollectionType ) getDataType(); String role = type.getRole(); QueryableCollection queryableCollection = getSessionFactoryHelper().requireQueryableCollection( role ); String alias = null; // DotNode uses null here... String columnTableAlias = getFromElement().getTableAlias(); int joinType = JoinFragment.INNER_JOIN; boolean fetch = false; FromElementFactory factory = new FromElementFactory( getWalker().getCurrentFromClause(), getFromElement(), propertyName, alias, getFromElement().toColumns( columnTableAlias, propertyName, false ), true ); FromElement elem = factory.createCollection( queryableCollection, role, joinType, fetch, true ); setFromElement( elem ); getWalker().addQuerySpaces( queryableCollection.getCollectionSpaces() ); // Always add the collection's query spaces. } public void resolve(boolean generateJoin, boolean implicitJoin, String classAlias, AST parent) { if ( !isResolved() ) { if ( getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) { if ( resolveAsAlias() ) { setResolved(); // We represent a from-clause alias } } else if ( parent != null && parent.getType() == SqlTokenTypes.DOT ) { DotNode dot = ( DotNode ) parent; if ( parent.getFirstChild() == this ) { if ( resolveAsNakedComponentPropertyRefLHS( dot ) ) { // we are the LHS of the DOT representing a naked comp-prop-ref setResolved(); } } else { if ( resolveAsNakedComponentPropertyRefRHS( dot ) ) { // we are the RHS of the DOT representing a naked comp-prop-ref setResolved(); } } } else { int result = resolveAsNakedPropertyRef(); if ( result == PROPERTY_REF ) { // we represent a naked (simple) prop-ref setResolved(); } else if ( result == COMPONENT_REF ) { // EARLY EXIT!!! return so the resolve call explicitly coming from DotNode can // resolve this... return; } } // if we are still not resolved, we might represent a constant. // needed to add this here because the allowance of // naked-prop-refs in the grammar collides with the // definition of literals/constants ("nondeterminism"). // TODO: cleanup the grammar so that "processConstants" is always just handled from here if ( !isResolved() ) { // Avoid recursion from LiteralProcessor... if ( !getWalker().getCurrentFromClause().isFromElementAlias( getText() ) ) { try { getWalker().processConstant( this ); } catch( Throwable ignore ) { // just ignore it for now, it'll get resolved later... } } } } } private boolean resolveAsAlias() { // This is not actually a constant, but a reference to FROM element. FromElement element = getWalker().getCurrentFromClause().getFromElement( getText() ); if ( element != null ) { setFromElement( element ); setText( element.getIdentityColumn() ); setType( SqlTokenTypes.ALIAS_REF ); return true; } return false; } private int resolveAsNakedPropertyRef() { FromElement fromElement = locateSingleFromElement(); if ( fromElement == null ) { return UNKNOWN; } Queryable persister = fromElement.getQueryable(); if ( persister == null ) { return UNKNOWN; } String property = getText(); Type propertyType = null; try { propertyType = fromElement.getPropertyType( getText(), property ); } catch( Throwable t ) { // assume this ident's text does *not* refer to a property on the given persister return UNKNOWN; } if ( propertyType.isComponentType() && !root ) { return COMPONENT_REF; } setFromElement( fromElement ); if ( persister != null ) { String[] columns = getWalker().isSelectStatement() ? persister.toColumns( fromElement.getTableAlias(), property ) : persister.toColumns( property ); String text = StringHelper.join( ", ", columns ); setText( columns.length==1 ? text : "(" + text + ")" ); setType( SqlTokenTypes.SQL_TOKEN ); } // these pieces are needed for usage in select clause super.setDataType( propertyType ); nakedPropertyRef = true; return PROPERTY_REF; } private boolean resolveAsNakedComponentPropertyRefLHS(DotNode parent) { FromElement fromElement = locateSingleFromElement(); if ( fromElement == null ) { return false; } String propertyPath = getText() + "." + getNextSibling().getText(); Type propertyType = null; // used to inject the dot node try { // check to see if our "propPath" actually // represents a property on the persister propertyType = fromElement.getPropertyType( getText(), propertyPath ); } catch( Throwable t ) { // assume we do *not* refer to a property on the given persister return false; } setFromElement( fromElement ); parent.setPropertyPath( propertyPath ); parent.setDataType( propertyType ); return true; } private boolean resolveAsNakedComponentPropertyRefRHS(DotNode parent) { FromElement fromElement = locateSingleFromElement(); if ( fromElement == null ) { return false; } Type propertyType = null; String propertyPath = parent.getLhs().getText() + "." + getText(); try { // check to see if our "propPath" actually // represents a property on the persister propertyType = fromElement.getPropertyType( getText(), propertyPath ); } catch( Throwable t ) { // assume we do *not* refer to a property on the given persister return false; } setFromElement( fromElement ); // this piece is needed for usage in select clause super.setDataType( propertyType ); nakedPropertyRef = true; return true; } private FromElement locateSingleFromElement() { List fromElements = getWalker().getCurrentFromClause().getFromElements(); if ( fromElements == null || fromElements.size() != 1 ) { // TODO : should this be an error? return null; } FromElement element = ( FromElement ) fromElements.get(0); if ( element.getClassAlias() != null ) { // naked property-refs cannot be used with an aliased from element return null; } return element; } public Type getDataType() { Type type = super.getDataType(); if (type!=null) return type; FromElement fe = getFromElement(); if (fe!=null) return fe.getDataType(); SQLFunction sf = getWalker().getSessionFactoryHelper().findSQLFunction( getText() ); return sf==null ? null : sf.getReturnType(null, null); } public void setScalarColumnText(int i) throws SemanticException { if ( nakedPropertyRef ) { // do *not* over-write the column text, as that has already been // "rendered" during resolve ColumnHelper.generateSingleScalarColumn( this, i ); } else { FromElement fe = getFromElement(); if (fe!=null) { setText( fe.renderScalarIdentifierSelect( i ) ); } else { ColumnHelper.generateSingleScalarColumn( this, i ); } } } public String getDisplayText() { StringBuffer buf = new StringBuffer(); if ( getType() == SqlTokenTypes.ALIAS_REF ) { buf.append( "{alias=" ).append( getOriginalText() ); if ( getFromElement() == null ) { buf.append( ", no from element" ); } else { buf.append( ", className=" ).append( getFromElement().getClassName() ); buf.append( ", tableAlias=" ).append( getFromElement().getTableAlias() ); } buf.append( "}" ); } else { buf.append( "{originalText=" + getOriginalText() ).append( "}" ); } return buf.toString(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -