Open Source Repository

Home /hibernate/hibernate-3.2.7.ga | Repository Home


org/hibernate/engine/query/HQLQueryPlan.java
package org.hibernate.engine.query;

import org.hibernate.hql.QuerySplitter;
import org.hibernate.hql.QueryTranslator;
import org.hibernate.hql.ParameterTranslations;
import org.hibernate.hql.FilterTranslator;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.EmptyIterator;
import org.hibernate.util.JoinedIterator;
import org.hibernate.util.IdentitySet;
import org.hibernate.HibernateException;
import org.hibernate.ScrollableResults;
import org.hibernate.QueryException;
import org.hibernate.type.Type;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.QueryParameters;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.RowSelection;
import org.hibernate.event.EventSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.HashMap;

/**
 * Defines a query execution plan for an HQL query (or filter).
 *
 @author <a href="mailto:[email protected]">Steve Ebersole </a>
 */
public class HQLQueryPlan implements Serializable {

  // TODO : keep seperate notions of QT[] here for shallow/non-shallow queries...

  private static final Log log = LogFactory.getLogHQLQueryPlan.class );

  private final String sourceQuery;
  private final QueryTranslator[] translators;
  private final String[] sqlStrings;

  private final ParameterMetadata parameterMetadata;
  private final ReturnMetadata returnMetadata;
  private final Set querySpaces;

  private final Set enabledFilterNames;
  private final boolean shallow;


  public HQLQueryPlan(String hql, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory) {
    thishql, null, shallow, enabledFilters, factory );
  }

  protected HQLQueryPlan(String hql, String collectionRole, boolean shallow, Map enabledFilters, SessionFactoryImplementor factory) {
    this.sourceQuery = hql;
    this.shallow = shallow;

    Set copy = new HashSet();
    copy.addAllenabledFilters.keySet() );
    this.enabledFilterNames = java.util.Collections.unmodifiableSetcopy );

    Set combinedQuerySpaces = new HashSet();
    String[] concreteQueryStrings = QuerySplitter.concreteQuerieshql, factory );
    final int length = concreteQueryStrings.length;
    translators = new QueryTranslator[length];
    List sqlStringList = new ArrayList();
    for int i=0; i<length; i++ ) {
      if collectionRole == null ) {
        translators[i= factory.getSettings()
            .getQueryTranslatorFactory()
            .createQueryTranslatorhql, concreteQueryStrings[i], enabledFilters, factory );
        translators[i].compilefactory.getSettings().getQuerySubstitutions(), shallow );
      }
      else {
        translators[i= factory.getSettings()
            .getQueryTranslatorFactory()
            .createFilterTranslatorhql, concreteQueryStrings[i], enabledFilters, factory );
        ( ( FilterTranslator translators[i] ).compilecollectionRole, factory.getSettings().getQuerySubstitutions(), shallow );
      }
      combinedQuerySpaces.addAlltranslators[i].getQuerySpaces() );
      sqlStringList.addAlltranslators[i].collectSqlStrings() );
    }

    this.sqlStrings = ArrayHelper.toStringArraysqlStringList );
    this.querySpaces = combinedQuerySpaces;

    if length == ) {
      parameterMetadata = new ParameterMetadatanull, null );
      returnMetadata = null;
    }
    else {
      this.parameterMetadata = buildParameterMetadatatranslators[0].getParameterTranslations(), hql );
      if translators[0].isManipulationStatement() ) {
        returnMetadata = null;
      }
      else {
        if length > ) {
          final int returns = translators[0].getReturnTypes().length;
          returnMetadata = new ReturnMetadatatranslators[0].getReturnAliases()new Type[returns] );
        }
        else {
          returnMetadata = new ReturnMetadatatranslators[0].getReturnAliases(), translators[0].getReturnTypes() );
        }
      }
    }
  }

  public String getSourceQuery() {
    return sourceQuery;
  }

  public Set getQuerySpaces() {
    return querySpaces;
  }

  public ParameterMetadata getParameterMetadata() {
    return parameterMetadata;
  }

  public ReturnMetadata getReturnMetadata() {
    return returnMetadata;
  }

  public Set getEnabledFilterNames() {
    return enabledFilterNames;
  }

  public String[] getSqlStrings() {
    return sqlStrings;
  }

  public Set getUtilizedFilterNames() {
    // TODO : add this info to the translator and aggregate it here...
    return null;
  }

  public boolean isShallow() {
    return shallow;
  }

  public List performList(
      QueryParameters queryParameters,
          SessionImplementor sessionthrows HibernateException {
    if log.isTraceEnabled() ) {
      log.trace"find: " + getSourceQuery() );
      queryParameters.traceParameterssession.getFactory() );
    }
    boolean hasLimit = queryParameters.getRowSelection() != null &&
                       queryParameters.getRowSelection().definesLimits();
    boolean needsLimit = hasLimit && translators.length > 1;
    QueryParameters queryParametersToUse;
    if needsLimit ) {
      log.warn"firstResult/maxResults specified on polymorphic query; applying in memory!" );
      RowSelection selection = new RowSelection();
      selection.setFetchSizequeryParameters.getRowSelection().getFetchSize() );
      selection.setTimeoutqueryParameters.getRowSelection().getTimeout() );
      queryParametersToUse = queryParameters.createCopyUsingselection );
    }
    else {
      queryParametersToUse = queryParameters;
    }

    List combinedResults = new ArrayList();
    IdentitySet distinction = new IdentitySet();
    int includedCount = -1;
    translator_loop: for int i = 0; i < translators.length; i++ ) {
      List tmp = translators[i].listsession, queryParametersToUse );
      if needsLimit ) {
        // NOTE : firstRow is zero-based
        int first = queryParameters.getRowSelection().getFirstRow() == null
                    0
                      : queryParameters.getRowSelection().getFirstRow().intValue();
        int max = queryParameters.getRowSelection().getMaxRows() == null
                    ? -1
                      : queryParameters.getRowSelection().getMaxRows().intValue();
        final int size = tmp.size();
        for int x = 0; x < size; x++ ) {
          final Object result = tmp.get);
          if ! distinction.addresult ) ) {
            continue;
          }
          includedCount++;
          if includedCount < first ) {
            continue;
          }
          combinedResults.addresult );
          if max >= && includedCount > max ) {
            // break the outer loop !!!
            break translator_loop;
          }
        }
      }
      else {
        combinedResults.addAlltmp );
      }
    }
    return combinedResults;
  }

  public Iterator performIterate(
      QueryParameters queryParameters,
          EventSource sessionthrows HibernateException {
    if log.isTraceEnabled() ) {
      log.trace"iterate: " + getSourceQuery() );
      queryParameters.traceParameterssession.getFactory() );
    }
    if translators.length == ) {
      return EmptyIterator.INSTANCE;
    }

    Iterator[] results = null;
    boolean many = translators.length > 1;
    if (many) {
      results = new Iterator[translators.length];
    }

    Iterator result = null;
    for int i = 0; i < translators.length; i++ ) {
      result = translators[i].iteratequeryParameters, session );
      if (manyresults[i= result;
    }

    return many ? new JoinedIterator(results: result;
  }

  public ScrollableResults performScroll(
      QueryParameters queryParameters,
          SessionImplementor sessionthrows HibernateException {
    if log.isTraceEnabled() ) {
      log.trace"iterate: " + getSourceQuery() );
      queryParameters.traceParameterssession.getFactory() );
    }
    if translators.length != ) {
      throw new QueryException"implicit polymorphism not supported for scroll() queries" );
    }
    if queryParameters.getRowSelection().definesLimits() && translators[0].containsCollectionFetches() ) {
      throw new QueryException"firstResult/maxResults not supported in conjunction with scroll() of a query containing collection fetches" );
    }

    return translators[0].scrollqueryParameters, session );
  }

  public int performExecuteUpdate(QueryParameters queryParameters, SessionImplementor session)
      throws HibernateException {
    if log.isTraceEnabled() ) {
      log.trace"executeUpdate: " + getSourceQuery() );
      queryParameters.traceParameterssession.getFactory() );
    }
    if translators.length != ) {
      log.warn"manipulation query [" + getSourceQuery() "] resulted in [" + translators.length + "] split queries" );
    }
    int result = 0;
    for int i = 0; i < translators.length; i++ ) {
      result += translators[i].executeUpdatequeryParameters, session );
    }
    return result;
  }

  private ParameterMetadata buildParameterMetadata(ParameterTranslations parameterTranslations, String hql) {
    long start = System.currentTimeMillis();
    ParamLocationRecognizer recognizer = ParamLocationRecognizer.parseLocationshql );
    long end = System.currentTimeMillis();
    if log.isTraceEnabled() ) {
      log.trace"HQL param location recognition took " (end - start" mills (" + hql + ")" );
    }

    int ordinalParamCount = parameterTranslations.getOrdinalParameterCount();
    int[] locations = ArrayHelper.toIntArrayrecognizer.getOrdinalParameterLocationList() );
    if parameterTranslations.supportsOrdinalParameterMetadata() && locations.length != ordinalParamCount ) {
      throw new HibernateException"ordinal parameter mismatch" );
    }
    ordinalParamCount = locations.length;
    OrdinalParameterDescriptor[] ordinalParamDescriptors = new OrdinalParameterDescriptor[ordinalParamCount];
    for int i = 1; i <= ordinalParamCount; i++ ) {
      ordinalParamDescriptorsi - new OrdinalParameterDescriptor(
          i,
              parameterTranslations.supportsOrdinalParameterMetadata()
                        ? parameterTranslations.getOrdinalParameterExpectedType)
                        : null,
              locationsi - ]
      );
    }

    Iterator itr = recognizer.getNamedParameterDescriptionMap().entrySet().iterator();
    Map namedParamDescriptorMap = new HashMap();
    whileitr.hasNext() ) {
      final Map.Entry entry = Map.Entry itr.next();
      final String name = String entry.getKey();
      final ParamLocationRecognizer.NamedParameterDescription description =
          ParamLocationRecognizer.NamedParameterDescription entry.getValue();
      namedParamDescriptorMap.put(
          name,
          new NamedParameterDescriptor(
              name,
                  parameterTranslations.getNamedParameterExpectedTypename ),
                  description.buildPositionsArray(),
                  description.isJpaStyle()
          )
      );
    }

    return new ParameterMetadataordinalParamDescriptors, namedParamDescriptorMap );
  }

  public QueryTranslator[] getTranslators() {
    QueryTranslator[] copy = new QueryTranslator[translators.length];
    System.arraycopy(translators, 0, copy, 0, copy.length);
    return copy;
  }
}