#1238 - Refactor MetaInfoManager - collect query plan stats, fix collection of stats on UpdateQuery

This commit is contained in:
Rob Bygrave
2018-01-19 01:07:37 +13:00
parent b9ae76d465
commit 07cdf64ece
27 changed files with 355 additions and 108 deletions
@@ -34,4 +34,10 @@ public interface ProfileLocation {
* Obtain the location description.
*/
String obtain();
/**
* Return a short version of the location description.
*/
String shortDescription();
}
@@ -1,17 +0,0 @@
package io.ebean.meta;
import java.util.List;
public interface MetaBeanInfo {
/**
* Collect the current query plan statistics return the non-empty statistics.
*/
List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset);
/**
* Collect the current query plan statistics return all the statistics (include query plans that haven't had query executions).
*/
List<MetaQueryPlanStatistic> collectAllQueryPlanStatistics(boolean reset);
}
@@ -8,17 +8,7 @@ import java.util.List;
public interface MetaInfoManager {
/**
* Return the MetaBeanInfo for a bean type.
*/
MetaBeanInfo getMetaBeanInfo(Class<?> beanClass);
/**
* Return all the MetaBeanInfo.
*/
List<MetaBeanInfo> getMetaBeanInfoList();
/**
* Collect and return the query plan statistics for all the beans.
* Collect and return the non-empty query plan statistics for all the beans.
* <p>
* Note that this excludes the query plan statistics where there has been no
* executions (since the last collection with reset).
@@ -1,5 +1,7 @@
package io.ebean.meta;
import io.ebean.ProfileLocation;
import java.util.List;
/**
@@ -14,6 +16,11 @@ public interface MetaQueryPlanStatistic {
*/
Class<?> getBeanType();
/**
* Return the profile location.
*/
ProfileLocation getProfileLocation();
/**
* Return true if this query plan was tuned by AutoTune.
*/
@@ -180,9 +180,14 @@ public interface SpiQuery<T> extends Query<T>, TxnProfileEventCodes {
ProfileLocation getProfileLocation();
/**
* Check for a single "equal to" expression for the Id.
* Return true if this is a "find by id" query. This includes a check for a single "equal to" expression for the Id.
*/
void checkIdEqualTo();
boolean isFindById();
/**
* Return true if this is a "find all" query. Used to set a "find all" profile location if necessary.
*/
boolean isFindAll();
/**
* Return true if AutoTune should be attempted on this query.
@@ -21,10 +21,14 @@ public class CObjectGraphNodeStatistics {
private final AtomicLong startTime = new AtomicLong(System.currentTimeMillis());
public CObjectGraphNodeStatistics(ObjectGraphNode node) {
CObjectGraphNodeStatistics(ObjectGraphNode node) {
this.node = node;
}
public boolean isEmpty() {
return count.sum() == 0;
}
public void add(long beanCount, long exeMicros) {
count.increment();
totalTime.add(exeMicros);
@@ -1,9 +1,10 @@
package io.ebeaninternal.server.core;
import io.ebean.meta.MetaBeanInfo;
import io.ebean.meta.MetaInfoManager;
import io.ebean.meta.MetaObjectGraphNodeStats;
import io.ebean.meta.MetaQueryPlanStatistic;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.query.CQueryPlanStatsCollector;
import java.util.ArrayList;
import java.util.List;
@@ -15,41 +16,27 @@ public class DefaultMetaInfoManager implements MetaInfoManager {
private final DefaultServer server;
public DefaultMetaInfoManager(DefaultServer server) {
DefaultMetaInfoManager(DefaultServer server) {
this.server = server;
}
@Override
public MetaBeanInfo getMetaBeanInfo(Class<?> beanClass) {
return server.getBeanDescriptor(beanClass);
}
@Override
public List<MetaBeanInfo> getMetaBeanInfoList() {
return new ArrayList<>(server.getBeanDescriptors());
}
@Override
public List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset) {
List<MetaQueryPlanStatistic> list = new ArrayList<>();
for (MetaBeanInfo metaBeanInfo : getMetaBeanInfoList()) {
list.addAll(metaBeanInfo.collectQueryPlanStatistics(reset));
CQueryPlanStatsCollector collector = new CQueryPlanStatsCollector(reset);
for (BeanDescriptor<?> desc : server.getBeanDescriptors()) {
desc.collectQueryPlanStatistics(collector);
}
return list;
return collector.getList();
}
@Override
public List<MetaObjectGraphNodeStats> collectNodeStatistics(boolean reset) {
List<MetaObjectGraphNodeStats> list = new ArrayList<>();
for (CObjectGraphNodeStatistics nodeStatistics : server.objectGraphStats.values()) {
MetaObjectGraphNodeStats nodeStats = nodeStatistics.get(reset);
if (nodeStats.getCount() > 0) {
// Only collection non-empty statistics
list.add(nodeStats);
if (!nodeStatistics.isEmpty()) {
list.add(nodeStatistics.get(reset));
}
}
return list;
@@ -1133,6 +1133,10 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
query.selectAllForLazyLoadProperty();
ProfileLocation profileLocation = query.getProfileLocation();
if (profileLocation != null) {
profileLocation.obtain();
}
// if determine cost and no origin for AutoTune
if (query.getParentNode() == null) {
query.setOrigin(createCallStack());
@@ -1213,6 +1217,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
}
SpiOrmQueryRequest<T> request = createQueryRequest(spiQuery, t);
request.profileLocationById();
if (request.isUseDocStore()) {
return docStore().find(request);
}
@@ -1234,9 +1239,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
public <T> T findOne(Query<T> query, Transaction transaction) {
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
spiQuery.checkIdEqualTo();
Object id = spiQuery.getId();
if (id != null) {
if (spiQuery.isFindById()) {
// actually a find by Id query
return findId(query, transaction);
}
@@ -1537,6 +1540,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
private <T> List<T> findList(Query<T> query, Transaction t, boolean findOne) {
SpiOrmQueryRequest<T> request = createQueryRequest(Type.LIST, query, t);
request.profileLocationAll();
request.resetBeanCacheAutoMode(findOne);
Object result = request.getFromQueryCache();
if (result != null) {
@@ -96,6 +96,20 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
return queryEngine.translate(this, bindLog, sql, e);
}
@Override
public void profileLocationById() {
if (query.getProfileLocation() == null) {
query.setProfileLocation(beanDescriptor.profileLocationById());
}
}
@Override
public void profileLocationAll() {
if (query.getProfileLocation() == null && query.isFindAll()) {
query.setProfileLocation(beanDescriptor.profileLocationAll());
}
}
@Override
public boolean isMultiValueIdSupported() {
return beanDescriptor.isMultiValueIdSupported();
@@ -155,4 +155,14 @@ public interface SpiOrmQueryRequest<T> extends DocQueryRequest<T> {
* Return true if this query is expected to use the doc store.
*/
boolean isUseDocStore();
/**
* Set profile location for "find by id" if not set.
*/
void profileLocationById();
/**
* Set profile location for "find all" if not set.
*/
void profileLocationAll();
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy;
import io.ebean.OrderBy;
import io.ebean.PersistenceContextScope;
import io.ebean.ProfileLocation;
import io.ebean.Query;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
@@ -27,8 +28,6 @@ import io.ebean.event.changelog.ChangeType;
import io.ebean.event.readaudit.ReadAuditLogger;
import io.ebean.event.readaudit.ReadAuditPrepare;
import io.ebean.event.readaudit.ReadEvent;
import io.ebean.meta.MetaBeanInfo;
import io.ebean.meta.MetaQueryPlanStatistic;
import io.ebean.plugin.BeanDocType;
import io.ebean.plugin.BeanType;
import io.ebean.plugin.ExpressionPath;
@@ -63,7 +62,7 @@ import io.ebeaninternal.server.el.ElPropertyDeploy;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.persist.DmlUtil;
import io.ebeaninternal.server.query.CQueryPlan;
import io.ebeaninternal.server.query.CQueryPlanStats.Snapshot;
import io.ebeaninternal.server.query.CQueryPlanStatsCollector;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import io.ebeaninternal.server.rawsql.SpiRawSql;
import io.ebeaninternal.server.text.json.ReadJson;
@@ -100,7 +99,7 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Describes Beans including their deployment information.
*/
public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
public class BeanDescriptor<T> implements BeanType<T> {
private static final Logger logger = LoggerFactory.getLogger(BeanDescriptor.class);
@@ -119,6 +118,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
private final Map<String, String> namedQuery;
private final short profileBeanId;
private final ProfileLocation locationById;
private final ProfileLocation locationAll;
private final boolean multiValueSupported;
@@ -415,6 +416,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
this.name = InternString.intern(deploy.getName());
this.baseTableAlias = "t0";
this.fullName = InternString.intern(deploy.getFullName());
this.locationById = ProfileLocation.create(fullName+".byId");
this.locationAll = ProfileLocation.create(fullName+".all");
this.profileBeanId = deploy.getProfileId();
this.beanType = deploy.getBeanType();
this.rootBeanType = PersistenceContextUtil.root(beanType);
@@ -537,6 +540,20 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
}
}
/**
* Return a location for "find by id".
*/
public ProfileLocation profileLocationById() {
return locationById;
}
/**
* Return a location for "find all".
*/
public ProfileLocation profileLocationAll() {
return locationAll;
}
/**
* Return the id used in profiling to identify the bean type.
*/
@@ -1528,25 +1545,12 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
return new DeployUpdateParser(this).parse(ormUpdateStatement);
}
@Override
public List<MetaQueryPlanStatistic> collectQueryPlanStatistics(boolean reset) {
return collectQueryPlanStatisticsInternal(reset, false);
}
@Override
public List<MetaQueryPlanStatistic> collectAllQueryPlanStatistics(boolean reset) {
return collectQueryPlanStatisticsInternal(reset, false);
}
public List<MetaQueryPlanStatistic> collectQueryPlanStatisticsInternal(boolean reset, boolean collectAll) {
List<MetaQueryPlanStatistic> list = new ArrayList<>(queryPlanCache.size());
public void collectQueryPlanStatistics(CQueryPlanStatsCollector collector) {
for (CQueryPlan queryPlan : queryPlanCache.values()) {
Snapshot snapshot = queryPlan.getSnapshot(reset);
if (collectAll || snapshot.getExecutionCount() > 0) {
list.add(snapshot);
if (!queryPlan.isEmptyStats()) {
collector.add(queryPlan.getSnapshot(collector.isReset()));
}
}
return list;
}
/**
@@ -8,17 +8,35 @@ import io.ebean.ProfileLocation;
class BasicProfileLocation implements ProfileLocation {
private final String location;
private final String shortDescription;
BasicProfileLocation(String location) {
this.location = location;
this.shortDescription = shortDesc(location);
}
public String toString() {
return "location: " + location;
return shortDescription;
}
public String obtain() {
return location;
}
@Override
public String shortDescription() {
return shortDescription;
}
private String shortDesc(String location) {
int lastPer = location.lastIndexOf('.');
if (lastPer > -1) {
lastPer = location.lastIndexOf('.', lastPer-1);
if (lastPer > -1) {
return location.substring(lastPer+1);
}
}
return location;
}
}
@@ -13,6 +13,8 @@ class DProfileLocation implements ProfileLocation {
private String location;
private String shortDescription;
private final int lineNumber;
DProfileLocation() {
@@ -31,10 +33,16 @@ class DProfileLocation implements ProfileLocation {
// atomic assignment so happy with this
if (location == null) {
location = create();
shortDescription = shortDesc(location);
}
return location;
}
@Override
public String shortDescription() {
return shortDescription;
}
private String create() {
StackTraceElement[] trace = Thread.currentThread().getStackTrace();
for (int i = 3; i < trace.length; i++) {
@@ -52,4 +60,20 @@ class DProfileLocation implements ProfileLocation {
return traceLine.substring(0, traceLine.length() - 1) + ":" + lineNumber + ")";
}
}
private String shortDesc(String location) {
int pos = location.lastIndexOf('(');
if (pos == -1) {
pos = location.length();
}
pos = location.lastIndexOf('.', pos);
if (pos > -1) {
pos = location.lastIndexOf('.', pos - 1);
if (pos > -1) {
return location.substring(pos + 1);
}
}
return location;
}
}
@@ -108,7 +108,7 @@ class CQueryBuilder {
if (queryPlan != null) {
// skip building the SqlTree and Sql string
predicates.prepare(false);
return new CQueryUpdate(type, request, predicates, queryPlan.getSql());
return new CQueryUpdate(type, request, predicates, queryPlan);
}
predicates.prepare(true);
@@ -125,7 +125,7 @@ class CQueryBuilder {
// cache the query plan
queryPlan = new CQueryPlan(request, sql, sqlTree, false, false, predicates.getLogWhereSql());
request.putQueryPlan(queryPlan);
return new CQueryUpdate(type, request, predicates, sql);
return new CQueryUpdate(type, request, predicates, queryPlan);
}
private <T> String buildDeleteSql(OrmQueryRequest<T> request, String rootTableAlias, CQueryPredicates predicates, SqlTree sqlTree) {
@@ -251,8 +251,7 @@ class CQueryBuilder {
if (queryPlan != null) {
// skip building the SqlTree and Sql string
predicates.prepare(false);
String sql = queryPlan.getSql();
return new CQueryRowCount(queryPlan, request, predicates, sql);
return new CQueryRowCount(queryPlan, request, predicates);
}
predicates.prepare(true);
@@ -283,7 +282,7 @@ class CQueryBuilder {
queryPlan = new CQueryPlan(request, sql, sqlTree, false, s.isIncludesRowNumberColumn(), predicates.getLogWhereSql());
request.putQueryPlan(queryPlan);
return new CQueryRowCount(queryPlan, request, predicates, sql);
return new CQueryRowCount(queryPlan, request, predicates);
}
/**
@@ -55,7 +55,6 @@ public class CQueryEngine {
this.defaultFetchSizeFindEach = serverConfig.getJdbcFetchSizeFindEach();
this.defaultFetchSizeFindList = serverConfig.getJdbcFetchSizeFindList();
this.forwardOnlyHintOnFindIterate = dbPlatform.isForwardOnlyHintOnFindIterate();
this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, serverConfig.getAsOfSysPeriod());
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
}
@@ -331,8 +330,6 @@ public class CQueryEngine {
* deemed to be a be a paging query - check that the order by contains the id
* property to ensure unique row ordering for predicable paging but only in
* case, this is not a distinct query
*
* @param request
*/
private <T> void prepareForPaging(OrmQueryRequest<T> request) {
SpiQuery<T> query = request.getQuery();
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebeaninternal.api.SpiProfileTransactionEvent;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.OrmQueryRequest;
@@ -18,10 +19,12 @@ import java.util.List;
/**
* Base compiled query request for single attribute queries.
*/
class CQueryFetchSingleAttribute {
class CQueryFetchSingleAttribute implements SpiProfileTransactionEvent {
private static final Logger logger = LoggerFactory.getLogger(CQueryFetchSingleAttribute.class);
private final CQueryPlan queryPlan;
/**
* The overall find request wrapper object.
*/
@@ -56,17 +59,19 @@ class CQueryFetchSingleAttribute {
private final ScalarType<?> scalarType;
private long profileOffset;
/**
* Create the Sql select based on the request.
*/
CQueryFetchSingleAttribute(OrmQueryRequest<?> request, CQueryPredicates predicates, CQueryPlan plan) {
CQueryFetchSingleAttribute(OrmQueryRequest<?> request, CQueryPredicates predicates, CQueryPlan queryPlan) {
this.request = request;
this.queryPlan = queryPlan;
this.query = request.getQuery();
this.sql = plan.getSql();
this.sql = queryPlan.getSql();
this.desc = request.getBeanDescriptor();
this.predicates = predicates;
this.scalarType = plan.getSingleAttributeScalarType();
this.scalarType = queryPlan.getSingleAttributeScalarType();
query.setGeneratedSql(sql);
}
@@ -102,6 +107,9 @@ class CQueryFetchSingleAttribute {
executionTimeMicros = (System.nanoTime() - startNano) / 1000L;
request.slowQueryCheck(executionTimeMicros, rowCount);
queryPlan.executionTime(rowCount, executionTimeMicros, null);
getTransaction().profileEvent(this);
return result;
} finally {
@@ -109,6 +117,10 @@ class CQueryFetchSingleAttribute {
}
}
private SpiTransaction getTransaction() {
return request.getTransaction();
}
/**
* Return the bind log.
*/
@@ -125,7 +137,8 @@ class CQueryFetchSingleAttribute {
private void prepareExecute() throws SQLException {
SpiTransaction t = request.getTransaction();
SpiTransaction t = getTransaction();
profileOffset = t.profileOffset();
Connection conn = t.getInternalConnection();
pstmt = conn.prepareStatement(sql);
@@ -166,4 +179,10 @@ class CQueryFetchSingleAttribute {
}
}
@Override
public void profile() {
getTransaction()
.profileStream()
.addQueryEvent(query.profileEventId(), profileOffset, desc.getProfileId(), rowCount, query.getProfileId());
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.dbplatform.SqlLimitResponse;
import io.ebeaninternal.api.CQueryPlanKey;
@@ -48,6 +49,8 @@ public class CQueryPlan {
private final boolean autoTuned;
private final ProfileLocation profileLocation;
private final CQueryPlanKey planKey;
private final boolean rawSql;
@@ -87,6 +90,7 @@ public class CQueryPlan {
this.dataTimeZone = server.getDataTimeZone();
this.beanType = request.getBeanDescriptor().getBeanType();
this.planKey = request.getQueryPlanKey();
this.profileLocation = request.getQuery().getProfileLocation();
this.autoTuned = request.getQuery().isAutoTuned();
this.asOfTableCount = request.getQuery().getAsOfTableCount();
this.sql = sqlRes.getSql();
@@ -107,6 +111,7 @@ public class CQueryPlan {
this.server = request.getServer();
this.dataTimeZone = server.getDataTimeZone();
this.beanType = request.getBeanDescriptor().getBeanType();
this.profileLocation = request.getQuery().getProfileLocation();
this.planKey = buildPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
this.autoTuned = false;
this.asOfTableCount = 0;
@@ -134,6 +139,10 @@ public class CQueryPlan {
return beanType;
}
public ProfileLocation getProfileLocation() {
return profileLocation;
}
public DataReader createDataReader(ResultSet rset) {
return new RsetDataReader(dataTimeZone, rset);
}
@@ -252,4 +261,11 @@ public class CQueryPlan {
ScalarType<?> getSingleAttributeScalarType() {
return sqlTree.getRootNode().getSingleAttributeScalarType();
}
/**
* Return true if there are no statistics collected since the last reset.
*/
public boolean isEmptyStats() {
return stats.isEmpty();
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.meta.MetaQueryPlanOriginCount;
import io.ebean.meta.MetaQueryPlanStatistic;
@@ -43,6 +44,13 @@ public final class CQueryPlanStats {
this.origins = !collectQueryOrigins ? null : new ConcurrentHashMap<>();
}
/**
* Return true if there are no statistics collected since the last reset.
*/
public boolean isEmpty() {
return count.sum() == 0;
}
/**
* Add a query execution to the statistics.
*/
@@ -188,8 +196,9 @@ public final class CQueryPlanStats {
@Override
public String toString() {
return queryPlan + " count:" + count + " time:" + totalTime + " maxTime:" + maxTime + " beans:" + totalBeans
+ " start:" + startTime + " lastQuery:" + lastQueryTime + " origins:" + origins;
ProfileLocation profileLocation = queryPlan.getProfileLocation();
String loc = (profileLocation == null) ? "" : profileLocation.shortDescription();
return "location:" + loc + " count:" + count + " time:" + totalTime + " maxTime:" + maxTime + " beans:" + totalBeans + " sql:" + getSql();
}
@Override
@@ -197,6 +206,11 @@ public final class CQueryPlanStats {
return queryPlan.getBeanType();
}
@Override
public ProfileLocation getProfileLocation() {
return queryPlan.getProfileLocation();
}
@Override
public long getExecutionCount() {
return count;
@@ -0,0 +1,32 @@
package io.ebeaninternal.server.query;
import io.ebean.meta.MetaQueryPlanStatistic;
import java.util.ArrayList;
import java.util.List;
/**
* Helper to collect query plan execution statistics.
*/
public class CQueryPlanStatsCollector {
private final boolean reset;
List<MetaQueryPlanStatistic> list = new ArrayList<>();
public CQueryPlanStatsCollector(boolean reset) {
this.reset = reset;
}
public boolean isReset() {
return reset;
}
public void add(MetaQueryPlanStatistic planStatistic) {
list.add(planStatistic);
}
public List<MetaQueryPlanStatistic> getList() {
return list;
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebeaninternal.api.SpiProfileTransactionEvent;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.OrmQueryRequest;
@@ -14,7 +15,7 @@ import java.sql.SQLException;
/**
* Executes the select row count query.
*/
class CQueryRowCount {
class CQueryRowCount implements SpiProfileTransactionEvent {
private final CQueryPlan queryPlan;
@@ -53,17 +54,19 @@ class CQueryRowCount {
private int rowCount;
private long profileOffset;
/**
* Create the Sql select based on the request.
*/
CQueryRowCount(CQueryPlan queryPlan, OrmQueryRequest<?> request, CQueryPredicates predicates, String sql) {
CQueryRowCount(CQueryPlan queryPlan, OrmQueryRequest<?> request, CQueryPredicates predicates) {
this.queryPlan = queryPlan;
this.request = request;
this.query = request.getQuery();
this.sql = sql;
query.setGeneratedSql(sql);
this.sql = queryPlan.getSql();
this.desc = request.getBeanDescriptor();
this.predicates = predicates;
query.setGeneratedSql(sql);
}
/**
@@ -102,7 +105,8 @@ class CQueryRowCount {
long startNano = System.nanoTime();
try {
SpiTransaction t = request.getTransaction();
SpiTransaction t = getTransaction();
profileOffset = t.profileOffset();
Connection conn = t.getInternalConnection();
pstmt = conn.prepareStatement(sql);
@@ -121,6 +125,7 @@ class CQueryRowCount {
executionTimeMicros = (System.nanoTime() - startNano) / 1000L;
queryPlan.executionTime(rowCount, executionTimeMicros, query.getParentNode());
request.slowQueryCheck(executionTimeMicros, rowCount);
getTransaction().profileEvent(this);
return rowCount;
} finally {
@@ -128,6 +133,10 @@ class CQueryRowCount {
}
}
private SpiTransaction getTransaction() {
return request.getTransaction();
}
/**
* Close the resources.
*/
@@ -138,4 +147,10 @@ class CQueryRowCount {
pstmt = null;
}
@Override
public void profile() {
getTransaction()
.profileStream()
.addQueryEvent(query.profileEventId(), profileOffset, desc.getProfileId(), rowCount, query.getProfileId());
}
}
@@ -1,5 +1,6 @@
package io.ebeaninternal.server.query;
import io.ebeaninternal.api.SpiProfileTransactionEvent;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.api.SpiTransaction;
import io.ebeaninternal.server.core.OrmQueryRequest;
@@ -12,7 +13,9 @@ import java.sql.SQLException;
/**
* Executes the delete query.
*/
class CQueryUpdate {
class CQueryUpdate implements SpiProfileTransactionEvent {
private final CQueryPlan queryPlan;
private final OrmQueryRequest<?> request;
@@ -43,17 +46,20 @@ class CQueryUpdate {
private int rowCount;
private long profileOffset;
/**
* Create the Sql select based on the request.
*/
CQueryUpdate(String type, OrmQueryRequest<?> request, CQueryPredicates predicates, String sql) {
CQueryUpdate(String type, OrmQueryRequest<?> request, CQueryPredicates predicates, CQueryPlan queryPlan) {
this.type = type;
this.request = request;
this.queryPlan = queryPlan;
this.query = request.getQuery();
this.sql = sql;
query.setGeneratedSql(sql);
this.sql = queryPlan.getSql();
this.desc = request.getBeanDescriptor();
this.predicates = predicates;
query.setGeneratedSql(sql);
}
/**
@@ -90,7 +96,8 @@ class CQueryUpdate {
long startNano = System.nanoTime();
try {
SpiTransaction t = request.getTransaction();
SpiTransaction t = getTransaction();
profileOffset = t.profileOffset();
Connection conn = t.getInternalConnection();
pstmt = conn.prepareStatement(sql);
@@ -103,6 +110,8 @@ class CQueryUpdate {
executionTimeMicros = (System.nanoTime() - startNano) / 1000L;
request.slowQueryCheck(executionTimeMicros, rowCount);
queryPlan.executionTime(rowCount, executionTimeMicros, null);
getTransaction().profileEvent(this);
return rowCount;
} finally {
@@ -110,6 +119,10 @@ class CQueryUpdate {
}
}
private SpiTransaction getTransaction() {
return request.getTransaction();
}
/**
* Close the resources.
*/
@@ -118,4 +131,10 @@ class CQueryUpdate {
pstmt = null;
}
@Override
public void profile() {
getTransaction()
.profileStream()
.addQueryEvent(query.profileEventId(), profileOffset, desc.getProfileId(), rowCount, query.getProfileId());
}
}
@@ -277,14 +277,20 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
return beanDescriptor;
}
public boolean isFindAll() {
return whereExpressions == null && nativeSql == null && rawSql == null;
}
@Override
public void checkIdEqualTo() {
public boolean isFindById() {
if (id == null && whereExpressions != null) {
id = whereExpressions.idEqualTo(beanDescriptor.getIdName());
if (id != null) {
whereExpressions = null;
}
}
return id != null;
}
@Override
@@ -715,6 +721,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
DefaultOrmQuery<T> copy = new DefaultOrmQuery<>(beanDescriptor, server, expressionFactory);
copy.m2mIncludeJoin = m2mIncludeJoin;
copy.profilingListener = profilingListener;
copy.profileLocation = profileLocation;
copy.rootTableAlias = rootTableAlias;
copy.distinct = distinct;