⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hqlsqlwalker.java

📁 一个Java持久层类库
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// $Id: HqlSqlWalker.java 10945 2006-12-07 14:50:42Z steve.ebersole@jboss.com $package org.hibernate.hql.ast;import java.io.Serializable;import java.util.ArrayList;import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.hibernate.QueryException;import org.hibernate.HibernateException;import org.hibernate.engine.JoinSequence;import org.hibernate.engine.ParameterBinder;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.hql.QueryTranslator;import org.hibernate.hql.antlr.HqlSqlBaseWalker;import org.hibernate.hql.antlr.HqlSqlTokenTypes;import org.hibernate.hql.antlr.HqlTokenTypes;import org.hibernate.hql.antlr.SqlTokenTypes;import org.hibernate.hql.ast.tree.AssignmentSpecification;import org.hibernate.hql.ast.tree.CollectionFunction;import org.hibernate.hql.ast.tree.ConstructorNode;import org.hibernate.hql.ast.tree.DeleteStatement;import org.hibernate.hql.ast.tree.DotNode;import org.hibernate.hql.ast.tree.FromClause;import org.hibernate.hql.ast.tree.FromElement;import org.hibernate.hql.ast.tree.FromReferenceNode;import org.hibernate.hql.ast.tree.IdentNode;import org.hibernate.hql.ast.tree.IndexNode;import org.hibernate.hql.ast.tree.InsertStatement;import org.hibernate.hql.ast.tree.IntoClause;import org.hibernate.hql.ast.tree.MethodNode;import org.hibernate.hql.ast.tree.ParameterNode;import org.hibernate.hql.ast.tree.QueryNode;import org.hibernate.hql.ast.tree.ResolvableNode;import org.hibernate.hql.ast.tree.RestrictableStatement;import org.hibernate.hql.ast.tree.SelectClause;import org.hibernate.hql.ast.tree.SelectExpression;import org.hibernate.hql.ast.tree.UpdateStatement;import org.hibernate.hql.ast.tree.Node;import org.hibernate.hql.ast.tree.OperatorNode;import org.hibernate.hql.ast.util.ASTPrinter;import org.hibernate.hql.ast.util.ASTUtil;import org.hibernate.hql.ast.util.AliasGenerator;import org.hibernate.hql.ast.util.JoinProcessor;import org.hibernate.hql.ast.util.LiteralProcessor;import org.hibernate.hql.ast.util.SessionFactoryHelper;import org.hibernate.hql.ast.util.SyntheticAndFactory;import org.hibernate.hql.ast.util.NodeTraverser;import org.hibernate.id.IdentifierGenerator;import org.hibernate.id.PostInsertIdentifierGenerator;import org.hibernate.id.SequenceGenerator;import org.hibernate.param.NamedParameterSpecification;import org.hibernate.param.ParameterSpecification;import org.hibernate.param.PositionalParameterSpecification;import org.hibernate.param.VersionTypeSeedParameterSpecification;import org.hibernate.param.CollectionFilterKeyParameterSpecification;import org.hibernate.persister.collection.QueryableCollection;import org.hibernate.persister.entity.Queryable;import org.hibernate.sql.JoinFragment;import org.hibernate.type.AssociationType;import org.hibernate.type.Type;import org.hibernate.type.VersionType;import org.hibernate.type.DbTimestampType;import org.hibernate.usertype.UserVersionType;import org.hibernate.util.ArrayHelper;import antlr.ASTFactory;import antlr.RecognitionException;import antlr.SemanticException;import antlr.collections.AST;/** * Implements methods used by the HQL->SQL tree transform grammar (a.k.a. the second phase). * <ul> * <li>Isolates the Hibernate API-specific code from the ANTLR generated code.</li> * <li>Handles the SQL framgents generated by the persisters in order to create the SELECT and FROM clauses, * taking into account the joins and projections that are implied by the mappings (persister/queryable).</li> * <li>Uses SqlASTFactory to create customized AST nodes.</li> * </ul> * * @see SqlASTFactory */public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, ParameterBinder.NamedParameterSource {	private static final Logger log = LoggerFactory.getLogger( HqlSqlWalker.class );	private final QueryTranslatorImpl queryTranslatorImpl;	private final HqlParser hqlParser;	private final SessionFactoryHelper sessionFactoryHelper;	private final Map tokenReplacements;	private final AliasGenerator aliasGenerator = new AliasGenerator();	private final LiteralProcessor literalProcessor;	private final ParseErrorHandler parseErrorHandler;	private final ASTPrinter printer;	private final String collectionFilterRole;	private FromClause currentFromClause = null;	private SelectClause selectClause;	private Set querySpaces = new HashSet();	private int parameterCount;	private Map namedParameters = new HashMap();	private ArrayList parameters = new ArrayList();	private int numberOfParametersInSetClause;	private int positionalParameterCount;	private ArrayList assignmentSpecifications = new ArrayList();	private int impliedJoinType;	/**	 * Create a new tree transformer.	 *	 * @param qti Back pointer to the query translator implementation that is using this tree transform.	 * @param sfi The session factory implementor where the Hibernate mappings can be found.	 * @param parser A reference to the phase-1 parser	 * @param tokenReplacements Registers the token replacement map with the walker.  This map will	 * be used to substitute function names and constants.	 * @param collectionRole The collection role name of the collection used as the basis for the	 * filter, NULL if this is not a collection filter compilation.	 */	public HqlSqlWalker(			QueryTranslatorImpl qti,			SessionFactoryImplementor sfi,			HqlParser parser,			Map tokenReplacements,			String collectionRole) {		setASTFactory( new SqlASTFactory( this ) );		// Initialize the error handling delegate.		this.parseErrorHandler = new ErrorCounter();		this.queryTranslatorImpl = qti;		this.sessionFactoryHelper = new SessionFactoryHelper( sfi );		this.literalProcessor = new LiteralProcessor( this );		this.tokenReplacements = tokenReplacements;		this.collectionFilterRole = collectionRole;		this.hqlParser = parser;		this.printer = new ASTPrinter( SqlTokenTypes.class );	}	protected void prepareFromClauseInputTree(AST fromClauseInput) {		if ( !isSubQuery() ) {//			// inject param specifications to account for dynamic filter param values//			if ( ! getEnabledFilters().isEmpty() ) {//				Iterator filterItr = getEnabledFilters().values().iterator();//				while ( filterItr.hasNext() ) {//					FilterImpl filter = ( FilterImpl ) filterItr.next();//					if ( ! filter.getFilterDefinition().getParameterNames().isEmpty() ) {//						Iterator paramItr = filter.getFilterDefinition().getParameterNames().iterator();//						while ( paramItr.hasNext() ) {//							String parameterName = ( String ) paramItr.next();//							// currently param filters *only* work with single-column parameter types;//							// if that limitation is ever lifted, this logic will need to change to account for that//							ParameterNode collectionFilterKeyParameter = ( ParameterNode ) astFactory.create( PARAM, "?" );//							DynamicFilterParameterSpecification paramSpec = new DynamicFilterParameterSpecification(//									filter.getName(),//									parameterName,//									filter.getFilterDefinition().getParameterType( parameterName ),//									 positionalParameterCount++//							);//							collectionFilterKeyParameter.setHqlParameterSpecification( paramSpec );//							parameters.add( paramSpec );//						}//					}//				}//			}			if ( isFilter() ) {				// Handle collection-fiter compilation.				// IMPORTANT NOTE: This is modifying the INPUT (HQL) tree, not the output tree!				QueryableCollection persister = sessionFactoryHelper.getCollectionPersister( collectionFilterRole );				Type collectionElementType = persister.getElementType();				if ( !collectionElementType.isEntityType() ) {					throw new QueryException( "collection of values in filter: this" );				}				String collectionElementEntityName = persister.getElementPersister().getEntityName();				ASTFactory inputAstFactory = hqlParser.getASTFactory();				AST fromElement = ASTUtil.create( inputAstFactory, HqlTokenTypes.FILTER_ENTITY, collectionElementEntityName );				ASTUtil.createSibling( inputAstFactory, HqlTokenTypes.ALIAS, "this", fromElement );				fromClauseInput.addChild( fromElement );				// Show the modified AST.				if ( log.isDebugEnabled() ) {					log.debug( "prepareFromClauseInputTree() : Filter - Added 'this' as a from element..." );				}				queryTranslatorImpl.showHqlAst( hqlParser.getAST() );				// Create a parameter specification for the collection filter...				Type collectionFilterKeyType = sessionFactoryHelper.requireQueryableCollection( collectionFilterRole ).getKeyType();				ParameterNode collectionFilterKeyParameter = ( ParameterNode ) astFactory.create( PARAM, "?" );				CollectionFilterKeyParameterSpecification collectionFilterKeyParameterSpec = new CollectionFilterKeyParameterSpecification(						collectionFilterRole, collectionFilterKeyType, positionalParameterCount++				);				collectionFilterKeyParameter.setHqlParameterSpecification( collectionFilterKeyParameterSpec );				parameters.add( collectionFilterKeyParameterSpec );			}		}	}	public boolean isFilter() {		return collectionFilterRole != null;	}	public SessionFactoryHelper getSessionFactoryHelper() {		return sessionFactoryHelper;	}	public Map getTokenReplacements() {		return tokenReplacements;	}	public AliasGenerator getAliasGenerator() {		return aliasGenerator;	}	public FromClause getCurrentFromClause() {		return currentFromClause;	}	public ParseErrorHandler getParseErrorHandler() {		return parseErrorHandler;	}	public void reportError(RecognitionException e) {		parseErrorHandler.reportError( e ); // Use the delegate.	}	public void reportError(String s) {		parseErrorHandler.reportError( s ); // Use the delegate.	}	public void reportWarning(String s) {		parseErrorHandler.reportWarning( s );	}	/**	 * Returns the set of unique query spaces (a.k.a.	 * table names) that occurred in the query.	 *	 * @return A set of table names (Strings).	 */	public Set getQuerySpaces() {		return querySpaces;	}	protected AST createFromElement(String path, AST alias, AST propertyFetch) throws SemanticException {		FromElement fromElement = currentFromClause.addFromElement( path, alias );		fromElement.setAllPropertyFetch(propertyFetch!=null);		return fromElement;	}	protected AST createFromFilterElement(AST filterEntity, AST alias) throws SemanticException {		FromElement fromElement = currentFromClause.addFromElement( filterEntity.getText(), alias );		FromClause fromClause = fromElement.getFromClause();		QueryableCollection persister = sessionFactoryHelper.getCollectionPersister( collectionFilterRole );		// Get the names of the columns used to link between the collection		// owner and the collection elements.		String[] keyColumnNames = persister.getKeyColumnNames();		String fkTableAlias = persister.isOneToMany()				? fromElement.getTableAlias()				: fromClause.getAliasGenerator().createName( collectionFilterRole );		JoinSequence join = sessionFactoryHelper.createJoinSequence();		join.setRoot( persister, fkTableAlias );		if ( !persister.isOneToMany() ) {			join.addJoin( ( AssociationType ) persister.getElementType(),					fromElement.getTableAlias(),					JoinFragment.INNER_JOIN,					persister.getElementColumnNames( fkTableAlias ) );		}		join.addCondition( fkTableAlias, keyColumnNames, " = ?" );		fromElement.setJoinSequence( join );		fromElement.setFilter( true );		if ( log.isDebugEnabled() ) {			log.debug( "createFromFilterElement() : processed filter FROM element." );		}		return fromElement;	}	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 --" ) );		}	}	private void handleWithFragment(FromElement fromElement, AST hqlWithNode) throws SemanticException	{		try {			withClause( hqlWithNode );			AST hqlSqlWithNode = returnAST;			if ( log.isDebugEnabled() ) {				log.debug( "handleWithFragment() : " + getASTPrinter().showAsString( hqlSqlWithNode, "-- with clause --" ) );			}			WithClauseVisitor visitor = new WithClauseVisitor();			NodeTraverser traverser = new NodeTraverser( visitor );			traverser.traverseDepthFirst( hqlSqlWithNode );			FromElement referencedFromElement = visitor.getReferencedFromElement();			if ( referencedFromElement != fromElement ) {				throw new InvalidWithClauseException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" );			}			SqlGenerator sql = new SqlGenerator( getSessionFactoryHelper().getFactory() );			sql.whereExpr( hqlSqlWithNode.getFirstChild() );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -