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

📄 hqlsqlwalker.java

📁 好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.2.0
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// $Id: HqlSqlWalker.java 10060 2006-06-28 02:53:39Z 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.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.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 Log log = LogFactory.getLog( HqlSqlWalker.class );

	/**
	 * A delegate that handles the Hiberanate meta data model.
	 */
	private SessionFactoryHelper sessionFactoryHelper;

	/**
	 * A delegate that handles literal constants.
	 */
	private LiteralProcessor literalProcessor;

	/**
	 * Handles parser errors.
	 */
	private ParseErrorHandler parseErrorHandler;

	/**
	 * The current context.
	 */
	private FromClause currentFromClause = null;

	/**
	 * The top-level SelectClause.
	 */
	private SelectClause selectClause;

	/**
	 * Generates alias names for tables.
	 */
	private AliasGenerator aliasGenerator = new AliasGenerator();

	/**
	 * The set of unique query spaces (a.k.a. table names).
	 */
	private Set querySpaces = new HashSet();

	/**
	 * A (string->string) map is used to substitute function names and literals.
	 */
	private Map tokenReplacements;

	private QueryTranslatorImpl queryTranslatorImpl;

	/**
	 * The number of parameters encountered so far.
	 */
	private int parameterCount;

	/**
	 * A map of lists which associates named and numbered parameters to a list of occurrences in the query.
	 */
	private Map namedParameters = new HashMap();

	/**
	 * The filter collection role, or null if this isn't a filter compilation.
	 */
	private String filterCollectionRole;

	/**
	 * The parser that performed phase 1 - parse the HQL into an HQL tree.
	 */
	private HqlParser hqlParser;

	private ASTPrinter printer;

	/**
	 * The join type for any implied joins.
	 */
	private int impliedJoinType;

	private ArrayList parameters = new ArrayList();
	private int numberOfParametersInSetClause;
	private int positionalParameterCount;

	private ArrayList assignmentSpecifications = new ArrayList();

	/**
	 * 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
	 * @param tokenReplacements Registers the token replacement map with the walker.  This map will
	 *                          be used to substitute function names and constants.
	 * @param collectionRole    the role name of the collection used as the basis for the filter, NULL if this
	 */
	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.filterCollectionRole = collectionRole;
		this.hqlParser = parser;
		this.printer = new ASTPrinter( SqlTokenTypes.class );
	}


	protected void prepareFromClauseInputTree(AST fromClauseInput) {
		// Handle fiter compilation.
		// IMPORTANT NOTE: This is modifying the INPUT (HQL) tree, not the output tree!
		if ( isFilter() && !isSubQuery() ) {
			QueryableCollection persister = sessionFactoryHelper.getCollectionPersister( filterCollectionRole );
			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() );
		}
	}

	private boolean isFilter() {
		return filterCollectionRole != 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( filterCollectionRole );
		// 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( filterCollectionRole );
		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();

⌨️ 快捷键说明

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