Package org.hibernate.hql.ast.util

Source Code of org.hibernate.hql.ast.util.SyntheticAndFactory

// $Id: SyntheticAndFactory.java 15766 2009-01-09 21:30:33Z cbredesen $
package org.hibernate.hql.ast.util;

import java.util.Map;

import org.hibernate.hql.antlr.HqlSqlTokenTypes;
import org.hibernate.hql.ast.tree.FromElement;
import org.hibernate.hql.ast.tree.QueryNode;
import org.hibernate.hql.ast.tree.RestrictableStatement;
import org.hibernate.hql.ast.tree.SqlFragment;
import org.hibernate.hql.ast.tree.Node;
import org.hibernate.hql.ast.HqlSqlWalker;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.util.StringHelper;
import org.hibernate.type.Type;
import org.hibernate.param.CollectionFilterKeyParameterSpecification;

import antlr.collections.AST;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Creates synthetic and nodes based on the where fragment part of a JoinSequence.
*
* @author josh Dec 5, 2004 12:25:20 PM
*/
public class SyntheticAndFactory implements HqlSqlTokenTypes {
  private static final Log log = LogFactory.getLog( SyntheticAndFactory.class );

  private HqlSqlWalker hqlSqlWalker;
  private AST thetaJoins;
  private AST filters;

  public SyntheticAndFactory(HqlSqlWalker hqlSqlWalker) {
    this.hqlSqlWalker = hqlSqlWalker;
  }

  private Node create(int tokenType, String text) {
    return ( Node ) ASTUtil.create( hqlSqlWalker.getASTFactory(), tokenType, text );
  }

  public void addWhereFragment(
      JoinFragment joinFragment,
      String whereFragment,
      QueryNode query,
      FromElement fromElement,
      HqlSqlWalker hqlSqlWalker) {
    if ( whereFragment == null ) {
      return;
    }

    if ( !fromElement.useWhereFragment() && !joinFragment.hasThetaJoins() ) {
      return;
    }

    whereFragment = whereFragment.trim();
    if ( StringHelper.isEmpty( whereFragment ) ) {
      return;
    }

    // Forcefully remove leading ands from where fragments; the grammar will
    // handle adding them
    if ( whereFragment.startsWith( "and" ) ) {
      whereFragment = whereFragment.substring( 4 );
    }

    if ( log.isDebugEnabled() ) {
      log.debug( "Using unprocessed WHERE-fragment [" + whereFragment + "]");
    }

    SqlFragment fragment = ( SqlFragment ) create( SQL_TOKEN, whereFragment );
    fragment.setJoinFragment( joinFragment );
    fragment.setFromElement( fromElement );

    if ( fromElement.getIndexCollectionSelectorParamSpec() != null ) {
      fragment.addEmbeddedParameter( fromElement.getIndexCollectionSelectorParamSpec() );
      fromElement.setIndexCollectionSelectorParamSpec( null );
    }

    if ( hqlSqlWalker.isFilter() ) {
      if ( whereFragment.indexOf( '?' ) >= 0 ) {
        Type collectionFilterKeyType = hqlSqlWalker.getSessionFactoryHelper()
            .requireQueryableCollection( hqlSqlWalker.getCollectionFilterRole() )
            .getKeyType();
        CollectionFilterKeyParameterSpecification paramSpec = new CollectionFilterKeyParameterSpecification(
            hqlSqlWalker.getCollectionFilterRole(),
            collectionFilterKeyType,
            0
        );
        fragment.addEmbeddedParameter( paramSpec );
      }
    }

    JoinProcessor.processDynamicFilterParameters(
        whereFragment,
        fragment,
        hqlSqlWalker
    );

    log.debug( "Using processed WHERE-fragment [" + fragment.getText() + "]" );

    // Filter conditions need to be inserted before the HQL where condition and the
    // theta join node.  This is because org.hibernate.loader.Loader binds the filter parameters first,
    // then it binds all the HQL query parameters, see org.hibernate.loader.Loader.processFilterParameters().
    if ( fragment.getFromElement().isFilter() || fragment.hasFilterCondition() ) {
      if ( filters == null ) {
        // Find or create the WHERE clause
        AST where = query.getWhereClause();
        // Create a new FILTERS node as a parent of all filters
        filters = create( FILTERS, "{filter conditions}" );
        // Put the FILTERS node before the HQL condition and theta joins
        ASTUtil.insertChild( where, filters );
      }

      // add the current fragment to the FILTERS node
      filters.addChild( fragment );
    }
    else {
      if ( thetaJoins == null ) {
        // Find or create the WHERE clause
        AST where = query.getWhereClause();
        // Create a new THETA_JOINS node as a parent of all filters
        thetaJoins = create( THETA_JOINS, "{theta joins}" );
        // Put the THETA_JOINS node before the HQL condition, after the filters.
        if (filters==null) {
          ASTUtil.insertChild( where, thetaJoins );
        }
        else {
          ASTUtil.insertSibling( thetaJoins, filters );
        }
      }

      // add the current fragment to the THETA_JOINS node
      thetaJoins.addChild(fragment);
    }

  }

  public void addDiscriminatorWhereFragment(
      RestrictableStatement statement,
      Queryable persister,
      Map enabledFilters,
      String alias) {
    String whereFragment = persister.filterFragment( alias, enabledFilters ).trim();
    if ( "".equals( whereFragment ) ) {
      return;
    }
    if ( whereFragment.startsWith( "and" ) ) {
      whereFragment = whereFragment.substring( 4 );
    }

    // Need to parse off the column qualifiers; this is assuming (which is true as of now)
    // that this is only used from update and delete HQL statement parsing
    whereFragment = StringHelper.replace( whereFragment, persister.generateFilterConditionAlias( alias ) + ".", "" );

    // Note: this simply constructs a "raw" SQL_TOKEN representing the
    // where fragment and injects this into the tree.  This "works";
    // however it is probably not the best long-term solution.
    //
    // At some point we probably want to apply an additional grammar to
    // properly tokenize this where fragment into constituent parts
    // focused on the operators embedded within the fragment.
    SqlFragment discrimNode = ( SqlFragment ) create( SQL_TOKEN, whereFragment );

    JoinProcessor.processDynamicFilterParameters(
        whereFragment,
        discrimNode,
        hqlSqlWalker
    );

    if ( statement.getWhereClause().getNumberOfChildren() == 0 ) {
      statement.getWhereClause().setFirstChild( discrimNode );
    }
    else {
      AST and = create( AND, "{and}" );
      AST currentFirstChild = statement.getWhereClause().getFirstChild();
      and.setFirstChild( discrimNode );
      and.addChild( currentFirstChild );
      statement.getWhereClause().setFirstChild( and );
    }
  }
}
TOP

Related Classes of org.hibernate.hql.ast.util.SyntheticAndFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.