#1857 Add bind values capture for SlowQueryEvent / SlowQueryListener

- changes SqlQueryEvent into an interface.
- captures the bind values the slow query used and makes those available via SlowQueryEvent
- also makes the query label and profileLocation available via SlowQueryEvent
This commit is contained in:
Rob Bygrave
2024-03-25 22:52:04 +13:00
parent ab45ad34e0
commit 40d9c88e34
49 changed files with 349 additions and 156 deletions
@@ -84,7 +84,7 @@ public interface SpiExpression extends Expression {
*
* @param request the associated request.
*/
void addBindValues(SpiExpressionRequest request);
void addBindValues(SpiExpressionBind request);
/**
* Validate all the properties/paths associated with this expression.
@@ -0,0 +1,29 @@
package io.ebeaninternal.api;
import io.ebeaninternal.server.deploy.BeanDescriptor;
/**
* Expression bind values capture.
*/
public interface SpiExpressionBind {
/**
* Return the bean descriptor for the root type.
*/
BeanDescriptor<?> descriptor();
/**
* Add an encryption key to bind to this request.
*/
void addBindEncryptKey(Object encryptKey);
/**
* Add a bind value to this request.
*/
void addBindValue(Object bindValue);
/**
* Escapes a string to use it as exact match in Like clause.
*/
String escapeLikeString(String value);
}
@@ -1,7 +1,6 @@
package io.ebeaninternal.api;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
import io.ebeaninternal.server.expression.platform.DbExpressionRequest;
@@ -10,7 +9,7 @@ import java.util.List;
/**
* Request object used for gathering expression sql and bind values.
*/
public interface SpiExpressionRequest extends DbExpressionRequest {
public interface SpiExpressionRequest extends SpiExpressionBind, DbExpressionRequest {
/**
* Return the DB specific handler for JSON and ARRAY expressions.
@@ -22,11 +21,6 @@ public interface SpiExpressionRequest extends DbExpressionRequest {
*/
String parseDeploy(String logicalProp);
/**
* Return the bean descriptor for the root type.
*/
BeanDescriptor<?> descriptor();
/**
* Return the associated QueryRequest.
*/
@@ -58,16 +52,6 @@ public interface SpiExpressionRequest extends DbExpressionRequest {
*/
SpiExpressionRequest parse(String expression);
/**
* Add an encryption key to bind to this request.
*/
void addBindEncryptKey(Object encryptKey);
/**
* Add a bind value to this request.
*/
void addBindValue(Object bindValue);
/**
* Return the accumulated expression sql for all expressions in this request.
*/
@@ -88,11 +72,6 @@ public interface SpiExpressionRequest extends DbExpressionRequest {
*/
void appendLike(boolean rawLikeExpression);
/**
* Escapes a string to use it as exact match in Like clause.
*/
String escapeLikeString(String value);
/**
* Append IN expression taking into account platform and type support for Multi-value.
*/
@@ -0,0 +1,70 @@
package io.ebeaninternal.server.core;
import io.ebean.ProfileLocation;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.config.SlowQueryEvent;
import java.util.List;
/**
* Slow query event.
*/
final class DSlowQueryEvent implements SlowQueryEvent {
private final String sql;
private final long timeMillis;
private final int rowCount;
private final ObjectGraphNode originNode;
private final List<Object> bindParams;
private final String label;
private final ProfileLocation profileLocation;
/**
* Construct with the SQL and execution time in millis.
*/
DSlowQueryEvent(String sql, long timeMillis, int rowCount, ObjectGraphNode originNode,
List<Object> bindParams, String label, ProfileLocation profileLocation) {
this.sql = sql;
this.timeMillis = timeMillis;
this.rowCount = rowCount;
this.originNode = originNode;
this.bindParams = bindParams;
this.profileLocation = profileLocation;
this.label = label != null ? label : profileLocation == null ? null : profileLocation.label();
}
@Override
public String getSql() {
return sql;
}
@Override
public long getTimeMillis() {
return timeMillis;
}
@Override
public int getRowCount() {
return rowCount;
}
@Override
public ObjectGraphNode getOriginNode() {
return originNode;
}
@Override
public List<Object> getBindParams() {
return bindParams;
}
@Override
public String getLabel() {
return label;
}
@Override
public ProfileLocation getProfileLocation() {
return profileLocation;
}
}
@@ -2184,7 +2184,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
@Override
public void slowQueryCheck(long timeMicros, int rowCount, SpiQuery<?> query) {
if (timeMicros > slowQueryMicros && slowQueryListener != null) {
slowQueryListener.process(new SlowQueryEvent(query.getGeneratedSql(), timeMicros / 1000L, rowCount, query.parentNode()));
List<Object> bindParams = new SlowQueryBindCapture(query).capture();
slowQueryListener.process(new DSlowQueryEvent(query.getGeneratedSql(), timeMicros / 1000L, rowCount,
query.parentNode(), bindParams, query.label(), query.profileLocation()));
}
}
@@ -1,10 +1,12 @@
package io.ebeaninternal.server.core;
import io.avaje.applog.AppLog;
import io.ebean.bean.ObjectGraphNode;
import io.ebean.ProfileLocation;
import io.ebean.config.SlowQueryEvent;
import io.ebean.config.SlowQueryListener;
import java.util.List;
import static java.lang.System.Logger.Level.WARNING;
/**
@@ -16,11 +18,10 @@ final class DefaultSlowQueryListener implements SlowQueryListener {
@Override
public void process(SlowQueryEvent event) {
String firstStack = "";
ObjectGraphNode node = event.getOriginNode();
if (node != null) {
firstStack = node.origin().top();
}
log.log(WARNING, "Slow query warning - millis:{0} rows:{1} caller[{2}] sql[{3}]", event.getTimeMillis(), event.getRowCount(), firstStack, event.getSql());
ProfileLocation profileLocation = event.getProfileLocation();
String loc = profileLocation == null ? "" : profileLocation.fullLocation();
List<Object> bindParams = event.getBindParams();
log.log(WARNING, "Slow query warning - millis:{0} rows:{1} location:{2} sql[{3}] params{4}",
event.getTimeMillis(), event.getRowCount(), loc, event.getSql(), bindParams);
}
}
@@ -0,0 +1,71 @@
package io.ebeaninternal.server.core;
import io.ebeaninternal.api.BindParams;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionList;
import io.ebeaninternal.api.SpiQuery;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.persist.MultiValueWrapper;
import java.util.ArrayList;
import java.util.List;
final class SlowQueryBindCapture implements SpiExpressionBind {
private final SpiQuery<?> query;
private final List<Object> bindParams = new ArrayList<>();
SlowQueryBindCapture(SpiQuery<?> query) {
this.query = query;
}
List<Object> capture() {
var params = query.bindParams();
if (params != null) {
var positionedParameters = params.positionedParameters();
for (BindParams.Param param : positionedParameters) {
if (param.isInParam()) {
add(param.inValue());
}
}
}
Object id = query.getId();
if (id != null) {
add(id);
}
SpiExpressionList<?> spiExpressionList = query.whereExpressions();
if (spiExpressionList != null) {
spiExpressionList.addBindValues(this);
}
return bindParams;
}
private void add(Object value) {
if (value instanceof MultiValueWrapper) {
var mvw = (MultiValueWrapper) value;
bindParams.add(mvw.getValues());
} else {
bindParams.add(value);
}
}
@Override
public BeanDescriptor<?> descriptor() {
return query.descriptor();
}
@Override
public void addBindValue(Object bindValue) {
add(bindValue);
}
@Override
public void addBindEncryptKey(Object encryptKey) {
bindParams.add("*");
}
@Override
public String escapeLikeString(String value) {
return query.descriptor().ebeanServer().databasePlatform().escapeLikeString(value);
}
}
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.deploy.id;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.deploy.BeanProperty;
@@ -143,7 +144,7 @@ public interface IdBinder {
/**
* Binds multiple id value to a request.
*/
void addBindValues(SpiExpressionRequest request, Collection<?> ids);
void addBindValues(SpiExpressionBind request, Collection<?> ids);
/**
* Return the sql for binding the id using an IN clause.
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.id;
import io.ebean.bean.EntityBean;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.deploy.BeanDescriptor;
@@ -269,7 +270,7 @@ public final class IdBinderEmbedded implements IdBinder {
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
public void addBindValues(SpiExpressionBind request, Collection<?> values) {
for (Object value : values) {
final EntityBean bean = (EntityBean) value;
for (BeanProperty prop : props) {
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.deploy.id;
import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.bind.DataBind;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
@@ -130,7 +131,7 @@ final class IdBinderEmpty implements IdBinder {
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> ids) {
public void addBindValues(SpiExpressionBind request, Collection<?> ids) {
}
@Override
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.deploy.id;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.ScalarType;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.core.DefaultSqlUpdate;
import io.ebeaninternal.server.core.InternString;
@@ -143,7 +144,7 @@ public final class IdBinderSimple implements IdBinder {
}
@Override
public void addBindValues(SpiExpressionRequest request, Collection<?> values) {
public void addBindValues(SpiExpressionBind request, Collection<?> values) {
List<Object> copy = new ArrayList<>(values);
copy.replaceAll(idValue -> convertSetId(idValue, null));
request.addBindValue(new MultiValueWrapper(copy));
@@ -97,7 +97,7 @@ abstract class AbstractExpression implements SpiExpression {
validation.validate(propName);
}
protected final ElPropertyValue getElProp(SpiExpressionRequest request) {
protected final ElPropertyValue getElProp(SpiExpressionBind request) {
return request.descriptor().elGetValue(propName);
}
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
/**
@@ -28,7 +29,7 @@ abstract class AbstractTextExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// do nothing, only execute against document store
}
@@ -51,7 +51,7 @@ final class AllEqualsExpression extends NonPrepareExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
if (propMap.isEmpty()) {
return;
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import java.io.IOException;
@@ -72,7 +73,7 @@ final class ArrayContainsExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object value : values) {
request.addBindValue(value);
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import java.io.IOException;
@@ -49,7 +50,7 @@ final class ArrayIsEmptyExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// nothing to bind
}
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -34,7 +35,7 @@ final class BetweenExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key as well as the value
@@ -75,7 +75,7 @@ final class BetweenPropertyExpression extends NonPrepareExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
request.addBindValue(val());
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
/**
@@ -52,7 +53,7 @@ final class BitwiseExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
request.addBindValue(flags);
request.addBindValue(match);
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -33,7 +34,7 @@ final class CaseInsensitiveEqualExpression extends AbstractValueExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key as well as the value
@@ -5,12 +5,7 @@ import io.ebean.LikeType;
import io.ebean.bean.EntityBean;
import io.ebean.event.BeanQueryRequest;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanProperty;
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
@@ -194,8 +189,7 @@ final class DefaultExampleExpression implements SpiExpression, ExampleExpression
* Adds bind values to the request.
*/
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (SpiExpression item : list) {
item.addBindValues(request);
}
@@ -591,7 +591,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (SpiExpression expr : list) {
expr.addBindValues(request);
}
@@ -99,7 +99,7 @@ final class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreE
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object bindParam : bindParams) {
request.addBindValue(bindParam);
}
@@ -77,7 +77,7 @@ final class ExistsSqlQueryExpression implements SpiExpression, UnsupportedDocSto
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object bindParam : bindParams) {
request.addBindValue(bindParam);
}
@@ -45,7 +45,7 @@ final class IdExpression extends NonPrepareExpression implements SpiExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// 'flatten' EmbeddedId and multiple ID cases
// into an array of the underlying scalar field values
for (Object bindIdValue : request.descriptor().bindIdValues(value)) {
@@ -61,7 +61,7 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
if (idCollection.isEmpty()) {
return;
}
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.bean.EntityBean;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.persist.MultiValueWrapper;
@@ -103,7 +100,7 @@ public final class InExpression extends AbstractExpression implements IdInCommon
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
if (empty) {
return;
}
@@ -3,10 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.Pairs;
import io.ebean.Pairs.Entry;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.persist.MultiValueWrapper;
import java.util.ArrayList;
@@ -58,8 +55,7 @@ final class InPairsExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// Note at this point entries may have been removed when used with l2 caching
// ... for each l2 cache hit an entry was removed
this.concatBindValues = new ArrayList<>(entries.size());
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -32,7 +33,7 @@ final class InRangeExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key twice, for both values
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.InTuples;
import io.ebean.service.SpiInTuples;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import java.util.List;
@@ -37,7 +34,7 @@ final class InTuplesExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object[] entry : entries) {
for (Object value : entry) {
requireNonNull(value);
@@ -1,10 +1,7 @@
package io.ebeaninternal.server.expression;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -53,7 +50,7 @@ final class IsEmptyExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// no bind values
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import java.io.IOException;
@@ -102,7 +103,7 @@ final class JsonPathExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
if (value != null) {
// value is null for EXISTS/NOT EXISTS
request.addBindValue(value);
@@ -141,7 +141,7 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (SpiExpression expr : exprList.internalList()) {
expr.addBindValues(request);
}
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.LikeType;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -25,7 +26,7 @@ final class LikeExpression extends AbstractValueExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key as well as the value
@@ -78,7 +79,7 @@ final class LikeExpression extends AbstractValueExpression {
return strValue().equals(that.strValue());
}
private static String getValue(String value, boolean caseInsensitive, LikeType type, SpiExpressionRequest request) {
private static String getValue(String value, boolean caseInsensitive, LikeType type, SpiExpressionBind request) {
if (caseInsensitive) {
value = value.toLowerCase();
}
@@ -3,12 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.Expression;
import io.ebean.Junction;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.IOException;
@@ -133,7 +128,7 @@ abstract class LogicExpression implements SpiExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
expOne.addBindValues(request);
expTwo.addBindValues(request);
}
@@ -3,6 +3,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.LikeType;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -23,8 +24,7 @@ final class NativeILikeExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null && prop.isDbEncrypted()) {
// bind the key as well as the value
@@ -1,13 +1,8 @@
package io.ebeaninternal.server.expression;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.api.NaturalKeyQueryData;
import java.io.IOException;
@@ -94,7 +89,7 @@ final class NestedPathWrapperExpression implements SpiExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
delegate.addBindValues(request);
}
@@ -78,7 +78,7 @@ final class NoopExpression implements SpiExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
// nothing to do
}
@@ -2,12 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.Expression;
import io.ebean.event.BeanQueryRequest;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.SpiExpressionValidation;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import java.io.IOException;
@@ -73,7 +68,7 @@ final class NotExpression implements SpiExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
exp.addBindValues(request);
}
@@ -1,10 +1,7 @@
package io.ebeaninternal.server.expression;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.ManyWhereJoins;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.el.ElPropertyValue;
@@ -51,7 +48,7 @@ final class NullExpression extends AbstractExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
}
@@ -42,7 +42,7 @@ final class RawExpression extends NonPrepareExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
if (values != null) {
for (Object value : values) {
if (value instanceof Collection<?>) {
@@ -2,10 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebean.bean.EntityBean;
import io.ebean.plugin.ExpressionPath;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.NaturalKeyQueryData;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.api.*;
import io.ebeaninternal.server.el.ElPropertyValue;
import java.io.IOException;
@@ -68,8 +65,7 @@ public final class SimpleExpression extends AbstractValueExpression {
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
ElPropertyValue prop = getElProp(request);
if (prop != null) {
if (prop.isAssocId()) {
@@ -79,7 +79,7 @@ final class SubQueryExpression extends AbstractExpression implements Unsupported
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object bindParam : bindParams) {
request.addBindValue(bindParam);
}
@@ -2,6 +2,7 @@ package io.ebeaninternal.server.expression;
import io.ebeaninternal.api.BindValuesKey;
import io.ebeaninternal.api.SpiExpression;
import io.ebeaninternal.api.SpiExpressionBind;
import io.ebeaninternal.api.SpiExpressionRequest;
import java.util.Arrays;
@@ -47,7 +48,7 @@ final class SubQueryRawExpression extends AbstractExpression implements Unsuppor
}
@Override
public void addBindValues(SpiExpressionRequest request) {
public void addBindValues(SpiExpressionBind request) {
for (Object bindParam : bindParams) {
request.addBindValue(bindParam);
}
@@ -0,0 +1,74 @@
package io.ebeaninternal.server.core;
import io.ebean.DB;
import io.ebean.Database;
import io.ebean.Query;
import io.ebeaninternal.api.SpiQuery;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class SlowQueryBindCaptureTest {
static Database db;
@BeforeAll
static void beforeAll() {
db = DB.getDefault();
db.script().run("/h2-init.sql");
}
@Test
void bindParams_capture() {
String sql = "select * from o_customer p where p.status = ?";
Query<Customer> query = db.findNative(Customer.class, sql)
.setParameter("N");
query.findList();
var sbc = new SlowQueryBindCapture((SpiQuery<?>) query);
List<Object> bindParams = sbc.capture();
assertThat(bindParams).hasSize(1);
assertThat(bindParams.get(0)).isEqualTo("N");
}
@Test
void expressionsCapture() {
Query<Customer> query = db.find(Customer.class)
.where()
.startsWith("name", "rob")
.eq("status", "N")
.query();
query.findList();
var sbc = new SlowQueryBindCapture((SpiQuery<?>) query);
List<Object> bindParams = sbc.capture();
assertThat(bindParams).hasSize(2);
assertThat(bindParams.get(0)).isEqualTo("rob%");
assertThat(bindParams.get(1)).isEqualTo("N");
}
@SuppressWarnings("unchecked")
@Test
void multiValueCapture() {
Query<Customer> query = db.find(Customer.class)
.where()
.in("id", List.of(1, 2, 3, 4))
.query();
query.findList();
var sbc = new SlowQueryBindCapture((SpiQuery<?>) query);
List<Object> bindParams = sbc.capture();
assertThat(bindParams).hasSize(1);
Object bindParam0 = bindParams.get(0);
assertThat(bindParam0).isInstanceOf(ArrayList.class);
var values = (ArrayList<Object>) bindParam0;
assertThat(values).contains(1, 2, 3, 4);
}
}
+3 -3
View File
@@ -1,5 +1,5 @@
create table animal (
create table if not exists animal (
species varchar(255) not null,
id bigint generated by default as identity not null,
shelter_id bigint,
@@ -11,14 +11,14 @@ create table animal (
constraint pk_animal primary key (id)
);
create table animal_shelter (
create table if not exists animal_shelter (
id bigint generated by default as identity not null,
name varchar(255),
version bigint not null,
constraint pk_animal_shelter primary key (id)
);
create table o_customer (
create table if not exists o_customer (
id integer generated by default as identity not null,
status varchar(1),
name varchar(40) not null,