Package com.avaje.ebeaninternal.server.query

Source Code of com.avaje.ebeaninternal.server.query.CQueryPlan

package com.avaje.ebeaninternal.server.query;

import java.sql.ResultSet;
import java.sql.SQLException;

import com.avaje.ebean.bean.ObjectGraphNode;
import com.avaje.ebean.config.dbplatform.SqlLimitResponse;
import com.avaje.ebeaninternal.api.HashQueryPlan;
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
import com.avaje.ebeaninternal.api.SpiEbeanServer;
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
import com.avaje.ebeaninternal.server.query.CQueryPlanStats.Snapshot;
import com.avaje.ebeaninternal.server.type.DataBind;
import com.avaje.ebeaninternal.server.type.DataReader;
import com.avaje.ebeaninternal.server.type.RsetDataReader;

/**
* Represents a query for a given SQL statement.
* <p>
* This can be executed multiple times with different bind parameters.
* </p>
* <p>
* That is, the sql including the where clause, order by clause etc must be
* exactly the same to share the same query plan with the only difference being
* bind values.
* </p>
* <p>
* This is useful in that is common in OLTP type applications that the same
* query will be executed quite a lot just with different bind values. With this
* query plan we can bypass some of the query statement generation (for
* performance) and collect statistics on the number and average execution
* times. This is turn can be used to identify queries that could be looked at
* for performance tuning.
* </p>
*/
public class CQueryPlan {

  private final SpiEbeanServer server;
 
  private final boolean autofetchTuned;
   
  private final HashQueryPlan hash;
 
  private final boolean rawSql;

  private final boolean rowNumberIncluded;

  private final String sql;

  private final String logWhereSql;

  private final SqlTree sqlTree;

  /**
   * Encrypted properties required additional binding.
   */
  private final BeanProperty[] encryptedProps;
 
  private final CQueryPlanStats stats;

  private final Class<?> beanType;

  /**
   * Create a query plan based on a OrmQueryRequest.
   */
  public CQueryPlan(OrmQueryRequest<?> request, SqlLimitResponse sqlRes, SqlTree sqlTree, boolean rawSql, String logWhereSql) {

    this.server = request.getServer();
    this.beanType = request.getBeanDescriptor().getBeanType();
    this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
    this.hash = request.getQueryPlanHash();
    this.autofetchTuned = request.getQuery().isAutofetchTuned();
    if (sqlRes != null) {
      this.sql = sqlRes.getSql();
      this.rowNumberIncluded = sqlRes.isIncludesRowNumberColumn();
    } else {
      this.sql = null;
      this.rowNumberIncluded = false;
    }
    this.sqlTree = sqlTree;
    this.rawSql = rawSql;
    this.logWhereSql = logWhereSql;
    this.encryptedProps = sqlTree.getEncryptedProps();
  }

  /**
   * Create a query plan for a raw sql query.
   */
  public CQueryPlan(OrmQueryRequest<?> request, String sql, SqlTree sqlTree,
      boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
       
    this.server = request.getServer();
    this.beanType = request.getBeanDescriptor().getBeanType();
    this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
    this.hash = buildHash(sql, rawSql, rowNumberIncluded, logWhereSql);
    this.autofetchTuned = false;
    this.sql = sql;
    this.sqlTree = sqlTree;
    this.rawSql = rawSql;
    this.rowNumberIncluded = rowNumberIncluded;
    this.logWhereSql = logWhereSql;
    this.encryptedProps = sqlTree.getEncryptedProps();
  }


  private HashQueryPlan buildHash(String sql, boolean rawSql, boolean rowNumberIncluded, String logWhereSql) {
    HashQueryPlanBuilder builder = new HashQueryPlanBuilder();
    builder.add(sql).add(rawSql).add(rowNumberIncluded).add(logWhereSql);
    builder.addRawSql(sql);
    return builder.build();
  }

  public String toString() {
    return beanType+" hash:"+hash;
  }
 
  public Class<?> getBeanType() {
    return beanType;
  }

  public DataReader createDataReader(ResultSet rset) {

    return new RsetDataReader(rset);
  }

  public void bindEncryptedProperties(DataBind dataBind) throws SQLException {
    if (encryptedProps != null) {
      for (int i = 0; i < encryptedProps.length; i++) {
        String key = encryptedProps[i].getEncryptKey().getStringValue();
        dataBind.setString(key);
      }
    }
  }
 
  public boolean isAutofetchTuned() {
    return autofetchTuned;
  }

  public HashQueryPlan getHash() {
    return hash;
  }

  public String getSql() {
    return sql;
  }

  public SqlTree getSqlTree() {
    return sqlTree;
  }

  public boolean isRawSql() {
    return rawSql;
  }

  public boolean isRowNumberIncluded() {
    return rowNumberIncluded;
  }

  public String getLogWhereSql() {
    return logWhereSql;
  }

  /**
   * Reset the query statistics.
   */
  public void resetStatistics() {
    stats.reset();
  }
 
  /**
   * Register an execution time against this query plan;
   */
  public void executionTime(long loadedBeanCount, long timeMicros, ObjectGraphNode objectGraphNode) {

    stats.add(loadedBeanCount, timeMicros, objectGraphNode);
    if (objectGraphNode != null) {
      // collect stats based on objectGraphNode for lazy loading reporting
      server.collectQueryStats(objectGraphNode, loadedBeanCount, timeMicros);
    }
  }

  public Snapshot getSnapshot(boolean reset) {
    return stats.getSnapshot(reset);
  }
 
  /**
   * Return the current query statistics.
   */
  public CQueryPlanStats getQueryStats() {
    return stats;
  }
 
  /**
   * Return the time this query plan was last used.
   */
  public long getLastQueryTime(){
      return stats.getLastQueryTime();
  }
 
}
TOP

Related Classes of com.avaje.ebeaninternal.server.query.CQueryPlan

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.