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

📄 hqlsqlwalker.java

📁 好东西,hibernate-3.2.0,他是一开元的树杖hibernate-3.2.0
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
			NodeTraverser traverser = new NodeTraverser( visitor );
			traverser.traverseDepthFirst( hqlSqlWithNode );
			FromElement referencedFromElement = visitor.getReferencedFromElement();
			if ( referencedFromElement != fromElement ) {
				throw new SemanticException( "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() );
			fromElement.setWithClauseFragment( visitor.getJoinAlias(), "(" + sql.getSQL() + ")" );

		}
		catch( SemanticException e ) {
			throw e;
		}
		catch ( Exception e) {
			throw new SemanticException( e.getMessage() );
		}
	}

	private static class WithClauseVisitor implements NodeTraverser.VisitationStrategy {
		private FromElement referencedFromElement;
		private String joinAlias;

		public void visit(AST node) {
			// todo : currently expects that the individual with expressions apply to the same sql table join.
			//      This may not be the case for joined-subclass where the property values
			//      might be coming from different tables in the joined hierarchy.  At some
			//      point we should expand this to support that capability.  However, that has
			//      some difficulties:
			//          1) the biggest is how to handle ORs when the individual comparisons are
			//              linked to different sql joins.
			//          2) here we would need to track each comparison individually, along with
			//              the join alias to which it applies and then pass that information
			//              back to the FromElement so it can pass it along to the JoinSequence

			if ( node instanceof DotNode ) {
				DotNode dotNode = ( DotNode ) node;
				FromElement fromElement = dotNode.getFromElement();
				if ( referencedFromElement != null ) {
					if ( fromElement != referencedFromElement ) {
						throw new HibernateException( "with-clause referenced two different from-clause elements" );
					}
				}
				else {
					referencedFromElement = fromElement;
					joinAlias = extractAppliedAlias( dotNode );
					// todo : temporary
					//      needed because currently persister is the one that
					//      creates and renders the join fragments for inheritence
					//      hierarchies...
					if ( !joinAlias.equals( referencedFromElement.getTableAlias() ) ) {
						throw new HibernateException( "with clause can only reference columns in the driving table" );
					}
				}
			}
		}

		private String extractAppliedAlias(DotNode dotNode) {
			return dotNode.getText().substring( 0, dotNode.getText().indexOf( '.' ) );
		}

		public FromElement getReferencedFromElement() {
			return referencedFromElement;
		}

		public String getJoinAlias() {
			return joinAlias;
		}
	}

	/**
	 * Sets the current 'FROM' context.
	 *
	 * @param fromNode      The new 'FROM' context.
	 * @param inputFromNode The from node from the input AST.
	 */
	protected void pushFromClause(AST fromNode, AST inputFromNode) {
		FromClause newFromClause = ( FromClause ) fromNode;
		newFromClause.setParentFromClause( currentFromClause );
		currentFromClause = newFromClause;
	}

	/**
	 * Returns to the previous 'FROM' context.
	 */
	private void popFromClause() {
		currentFromClause = currentFromClause.getParentFromClause();
	}

	protected void lookupAlias(AST aliasRef)
			throws SemanticException {
		FromElement alias = currentFromClause.getFromElement( aliasRef.getText() );
		FromReferenceNode aliasRefNode = ( FromReferenceNode ) aliasRef;
		aliasRefNode.setFromElement( alias );
	}

	protected void setImpliedJoinType(int joinType) {
		impliedJoinType = JoinProcessor.toHibernateJoinType( joinType );
	}

	public int getImpliedJoinType() {
		return impliedJoinType;
	}

	protected AST lookupProperty(AST dot, boolean root, boolean inSelect) throws SemanticException {
		DotNode dotNode = ( DotNode ) dot;
		FromReferenceNode lhs = dotNode.getLhs();
		AST rhs = lhs.getNextSibling();
		switch ( rhs.getType() ) {
			case SqlTokenTypes.ELEMENTS:
			case SqlTokenTypes.INDICES:
				if ( log.isDebugEnabled() ) {
					log.debug( "lookupProperty() " + dotNode.getPath() + " => " + rhs.getText() + "(" + lhs.getPath() + ")" );
				}
				CollectionFunction f = ( CollectionFunction ) rhs;
				// Re-arrange the tree so that the collection function is the root and the lhs is the path.
				f.setFirstChild( lhs );
				lhs.setNextSibling( null );
				dotNode.setFirstChild( f );
				resolve( lhs );			// Don't forget to resolve the argument!
				f.resolve( inSelect );	// Resolve the collection function now.
				return f;
			default:
				// Resolve everything up to this dot, but don't resolve the placeholders yet.
				dotNode.resolveFirstChild();
				return dotNode;
		}
	}

	protected boolean isNonQualifiedPropertyRef(AST ident) {
		final String identText = ident.getText();
		if ( currentFromClause.isFromElementAlias( identText ) ) {
			return false;
		}

		List fromElements = currentFromClause.getExplicitFromElements();
		if ( fromElements.size() == 1 ) {
			final FromElement fromElement = ( FromElement ) fromElements.get( 0 );
			try {
				log.trace( "attempting to resolve property [" + identText + "] as a non-qualified ref" );
				return fromElement.getPropertyMapping( identText ).toType( identText ) != null;
			}
			catch( QueryException e ) {
				// Should mean that no such property was found
			}
		}

		return false;
	}

	protected AST lookupNonQualifiedProperty(AST property) throws SemanticException {
		final FromElement fromElement = ( FromElement ) currentFromClause.getExplicitFromElements().get( 0 );
		AST syntheticDotNode = generateSyntheticDotNodeForNonQualifiedPropertyRef( property, fromElement );
		return lookupProperty( syntheticDotNode, false, getCurrentClauseType() == HqlSqlTokenTypes.SELECT );
	}

	private AST generateSyntheticDotNodeForNonQualifiedPropertyRef(AST property, FromElement fromElement) {
		AST dot = getASTFactory().create( DOT, "{non-qualified-property-ref}" );
		// TODO : better way?!?
		( ( DotNode ) dot ).setPropertyPath( ( ( FromReferenceNode ) property ).getPath() );

		IdentNode syntheticAlias = ( IdentNode ) getASTFactory().create( IDENT, "{synthetic-alias}" );
		syntheticAlias.setFromElement( fromElement );
		syntheticAlias.setResolved();

		dot.setFirstChild( syntheticAlias );
		dot.addChild( property );

		return dot;
	}

	protected void processQuery(AST select, AST query) throws SemanticException {
		if ( log.isDebugEnabled() ) {
			log.debug( "processQuery() : " + query.toStringTree() );
		}

		try {
			QueryNode qn = ( QueryNode ) query;

			// Was there an explicit select expression?
			boolean explicitSelect = select != null && select.getNumberOfChildren() > 0;

			if ( !explicitSelect ) {
				// No explicit select expression; render the id and properties
				// projection lists for every persister in the from clause into
				// a single 'token node'.
				//TODO: the only reason we need this stuff now is collection filters,
				//      we should get rid of derived select clause completely!
				createSelectClauseFromFromClause( qn );
			}
			else {
				// Use the explicitly declared select expression; determine the
				// return types indicated by each select token
				useSelectClause( select );
			}

			// After that, process the JOINs.
			// Invoke a delegate to do the work, as this is farily complex.
			JoinProcessor joinProcessor = new JoinProcessor( astFactory, queryTranslatorImpl );
			joinProcessor.processJoins( qn, isSubQuery() );

			// Attach any mapping-defined "ORDER BY" fragments
			Iterator itr = qn.getFromClause().getProjectionList().iterator();
			while ( itr.hasNext() ) {
				final FromElement fromElement = ( FromElement ) itr.next();
//			if ( fromElement.isFetch() && fromElement.isCollectionJoin() ) {
				if ( fromElement.isFetch() && fromElement.getQueryableCollection() != null ) {
					// Does the collection referenced by this FromElement
					// specify an order-by attribute?  If so, attach it to
					// the query's order-by
					if ( fromElement.getQueryableCollection().hasOrdering() ) {
						String orderByFragment = fromElement
								.getQueryableCollection()
								.getSQLOrderByString( fromElement.getCollectionTableAlias() );
						qn.getOrderByClause().addOrderFragment( orderByFragment );
					}
					if ( fromElement.getQueryableCollection().hasManyToManyOrdering() ) {
						String orderByFragment = fromElement.getQueryableCollection()
								.getManyToManyOrderByString( fromElement.getTableAlias() );
						qn.getOrderByClause().addOrderFragment( orderByFragment );
					}
				}
			}
		}
		finally {
			popFromClause();
		}
	}

	protected void postProcessDML(RestrictableStatement statement) throws SemanticException {
		statement.getFromClause().resolve();

		FromElement fromElement = ( FromElement ) statement.getFromClause().getFromElements().get( 0 );
		Queryable persister = fromElement.getQueryable();
		// Make #@%$^#^&# sure no alias is applied to the table name
		fromElement.setText( persister.getTableName() );

		// append any filter fragments; the EMPTY_MAP is used under the assumption that
		// currently enabled filters should not affect this process
		if ( persister.getDiscriminatorType() != null ) {
			new SyntheticAndFactory( getASTFactory() ).addDiscriminatorWhereFragment(
			        statement,
			        persister,
			        java.util.Collections.EMPTY_MAP,
			        fromElement.getTableAlias()
			);
		}

	}

	protected void postProcessUpdate(AST update) throws SemanticException {
		UpdateStatement updateStatement = ( UpdateStatement ) update;

		postProcessDML( updateStatement );
	}

	protected void postProcessDelete(AST delete) throws SemanticException {
		postProcessDML( ( DeleteStatement ) delete );
	}

	public static boolean supportsIdGenWithBulkInsertion(IdentifierGenerator generator) {
		return SequenceGenerator.class.isAssignableFrom( generator.getClass() )
		        || PostInsertIdentifierGenerator.class.isAssignableFrom( generator.getClass() );
	}

	protected void postProcessInsert(AST insert) throws SemanticException, QueryException {
		InsertStatement insertStatement = ( InsertStatement ) insert;
		insertStatement.validate();

		SelectClause selectClause = insertStatement.getSelectClause();
		Queryable persister = insertStatement.getIntoClause().getQueryable();

		if ( !insertStatement.getIntoClause().isExplicitIdInsertion() ) {
			// We need to generate ids as part of this bulk insert.
			//
			// Note that this is only supported for sequence-style generators and
			// post-insert-style generators; basically, only in-db generators
			IdentifierGenerator generator = persister.getIdentifierGenerator();
			if ( !supportsIdGenWithBulkInsertion( generator ) ) {
				throw new QueryException( "can only generate ids as part of bulk insert with either sequence or post-insert style generators" );
			}

			AST idSelectExprNode = null;

			if ( SequenceGenerator.class.isAssignableFrom( generator.getClass() ) ) {
				String seqName = ( String ) ( ( SequenceGenerator ) generator ).generatorKey();
				String nextval = sessionFactoryHelper.getFactory().getDialect().getSelectSequenceNextValString( seqName );
				idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, nextval );
			}
			else {
				//Don't need this, because we should never ever be selecting no columns in an insert ... select...
				//and because it causes a bug on DB2
				/*String idInsertString = sessionFactoryHelper.getFactory().getDialect().getIdentityInsertString();
				if ( idInsertString != null ) {
					idSelectExprNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, idInsertString );
				}*/
			}

			if ( idSelectExprNode != null ) {
				AST currentFirstSelectExprNode = selectClause.getFirstChild();
				selectClause.setFirstChild( idSelectExprNode );
				idSelectExprNode.setNextSibling( currentFirstSelectExprNode );

				insertStatement.getIntoClause().prependIdColumnSpec();
			}
		}

		final boolean includeVersionProperty = persister.isVersioned() &&
				!insertStatement.getIntoClause().isExplicitVersionInsertion() &&
				persister.isVersionPropertyInsertable();
		if ( includeVersionProperty ) {
			// We need to seed the version value as part of this bulk insert
			VersionType versionType = persister.getVersionType();
			AST versionValueNode = null;

			if ( sessionFactoryHelper.getFactory().getDialect().supportsParametersInInsertSelect() ) {
				versionValueNode = getASTFactory().create( HqlSqlTokenTypes.PARAM, "?" );
				ParameterSpecification paramSpec = new VersionTypeSeedParameterSpecification( versionType );
				( ( ParameterNode ) versionValueNode ).setHqlParameterSpecification( paramSpec );
				parameters.add( 0, paramSpec );
			}
			else {
				if ( isIntegral( versionType ) ) {
					try {
						Object seedValue = versionType.seed( null );
						versionValueNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, seedValue.toString() );
					}
					catch( Throwable t ) {
						throw new QueryException( "could not determine seed value for version on bulk insert [" + versionType + "]" );
					}
				}
				else if ( isDatabaseGeneratedTimestamp( versionType ) ) {
					String functionName = sessionFactoryHelper.getFactory().getDialect().getCurrentTimestampSQLFunctionName();
					versionValueNode = getASTFactory().create( HqlSqlTokenTypes.SQL_TOKEN, functionName );
				}
				else {
					throw new QueryException( "cannot handle version type [" + versionType + "] on bulk inserts with dialects not supporting parameters in insert-select statements" );
				}
			}

			AST currentFirstSelectExprNode = selectClause.getFirstChild();
			selectClause.setFirstChild( versionValueNode );

⌨️ 快捷键说明

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