mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
@@ -1,10 +1,6 @@
|
||||
package io.ebean;
|
||||
|
||||
import io.ebean.search.Match;
|
||||
import io.ebean.search.MultiMatch;
|
||||
import io.ebean.search.TextCommonTerms;
|
||||
import io.ebean.search.TextQueryString;
|
||||
import io.ebean.search.TextSimple;
|
||||
import io.ebean.search.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -423,6 +419,94 @@ public interface ExpressionFactory {
|
||||
*/
|
||||
Expression inOrEmpty(String propertyName, Collection<?> values);
|
||||
|
||||
/**
|
||||
* EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression exists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression notExists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
Expression ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not In - property has a value in the array of values.
|
||||
*/
|
||||
|
||||
@@ -1141,6 +1141,94 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> inPairs(Pairs pairs);
|
||||
|
||||
/**
|
||||
* EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> exists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not EXISTS a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> notExists(String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Not Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Greater Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* Less Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param propertyName The bean property
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
ExpressionList<T> leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues);
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
|
||||
@@ -13,7 +13,7 @@ public interface BeanLoader {
|
||||
/**
|
||||
* Return the name of the associated Database.
|
||||
*/
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
/**
|
||||
* Invoke the lazy loading for this bean.
|
||||
|
||||
@@ -192,13 +192,13 @@ public final class InterceptReadWrite implements EntityBeanIntercept {
|
||||
public void setBeanLoader(BeanLoader beanLoader, PersistenceContext ctx) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.persistenceContext = ctx;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanLoader(BeanLoader beanLoader) {
|
||||
this.beanLoader = beanLoader;
|
||||
this.ebeanServerName = beanLoader.getName();
|
||||
this.ebeanServerName = beanLoader.name();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@ public abstract class SingleBeanLoader implements BeanLoader {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return database.name();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public interface LoadContext {
|
||||
/**
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
int getSecondaryQueriesMinBatchSize();
|
||||
int secondaryQueriesMinBatchSize();
|
||||
|
||||
/**
|
||||
* Execute any secondary (+query) queries if there are any defined.
|
||||
@@ -29,12 +29,12 @@ public interface LoadContext {
|
||||
/**
|
||||
* Return the node for a given path which is used by AutoTune profiling.
|
||||
*/
|
||||
ObjectGraphNode getObjectGraphNode(String path);
|
||||
ObjectGraphNode objectGraphNode(String path);
|
||||
|
||||
/**
|
||||
* Return the persistence context used by this query and future lazy loading.
|
||||
*/
|
||||
PersistenceContext getPersistenceContext();
|
||||
PersistenceContext persistenceContext();
|
||||
|
||||
/**
|
||||
* Register a Bean for lazy loading.
|
||||
|
||||
@@ -31,15 +31,15 @@ public interface LoadManyBuffer {
|
||||
*/
|
||||
boolean removeFromBuffer(BeanCollection<?> collection);
|
||||
|
||||
BeanPropertyAssocMany<?> getBeanProperty();
|
||||
BeanPropertyAssocMany<?> beanProperty();
|
||||
|
||||
ObjectGraphNode getObjectGraphNode();
|
||||
ObjectGraphNode objectGraphNode();
|
||||
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
BeanDescriptor<?> descriptor();
|
||||
|
||||
PersistenceContext getPersistenceContext();
|
||||
PersistenceContext persistenceContext();
|
||||
|
||||
String getFullPath();
|
||||
String fullPath();
|
||||
|
||||
void configureQuery(SpiQuery<?> query);
|
||||
|
||||
|
||||
@@ -50,11 +50,11 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
|
||||
@Override
|
||||
public Class<?> beanType() {
|
||||
return loadContext.getBeanDescriptor().type();
|
||||
return loadContext.descriptor().type();
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return loadContext.getFullPath();
|
||||
return loadContext.fullPath();
|
||||
}
|
||||
|
||||
private List<Object> parentIdList(SpiEbeanServer server) {
|
||||
@@ -82,7 +82,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
}
|
||||
|
||||
private BeanPropertyAssocMany<?> many() {
|
||||
return loadContext.getBeanProperty();
|
||||
return loadContext.beanProperty();
|
||||
}
|
||||
|
||||
public SpiQuery<?> createQuery(SpiEbeanServer server) {
|
||||
@@ -100,7 +100,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
}
|
||||
query.setLazyLoadForParents(many);
|
||||
many.addWhereParentIdIn(query, parentIdList(server), loadContext.isUseDocStore());
|
||||
query.setPersistenceContext(loadContext.getPersistenceContext());
|
||||
query.setPersistenceContext(loadContext.persistenceContext());
|
||||
query.setLoadDescription(lazy ? "+lazy" : "+query", description());
|
||||
if (lazy) {
|
||||
query.setLazyLoadBatchSize(loadContext.batchSize());
|
||||
@@ -120,7 +120,7 @@ public final class LoadManyRequest extends LoadRequest {
|
||||
* After the query execution check for empty collections and load L2 cache if desired.
|
||||
*/
|
||||
public void postLoad() {
|
||||
BeanDescriptor<?> desc = loadContext.getBeanDescriptor();
|
||||
BeanDescriptor<?> desc = loadContext.descriptor();
|
||||
BeanPropertyAssocMany<?> many = many();
|
||||
// check for BeanCollection's that where never processed
|
||||
// in the +query or +lazy load due to no rows (predicates)
|
||||
|
||||
@@ -14,7 +14,7 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Return the DB specific handler for JSON and ARRAY expressions.
|
||||
*/
|
||||
DbExpressionHandler getDbPlatformHandler();
|
||||
DbExpressionHandler platformHandler();
|
||||
|
||||
/**
|
||||
* Parse the logical property name to the deployment name.
|
||||
@@ -24,17 +24,30 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Return the bean descriptor for the root type.
|
||||
*/
|
||||
BeanDescriptor<?> getBeanDescriptor();
|
||||
BeanDescriptor<?> descriptor();
|
||||
|
||||
/**
|
||||
* Return the associated QueryRequest.
|
||||
*/
|
||||
SpiOrmQueryRequest<?> getQueryRequest();
|
||||
SpiOrmQueryRequest<?> queryRequest();
|
||||
|
||||
/**
|
||||
* Append to the expression sql.
|
||||
* Append to the expression sql without any parsing.
|
||||
*/
|
||||
SpiExpressionRequest append(String sql);
|
||||
SpiExpressionRequest append(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql with logical property parsing to db columns with logical path prefix.
|
||||
* <p>
|
||||
* This is a fast path case when expression is a bean property path and falls back to using parse()
|
||||
* when that isn't the case.
|
||||
*/
|
||||
SpiExpressionRequest property(String expression);
|
||||
|
||||
/**
|
||||
* Append to the expression sql with logical property parsing to db columns with logical path prefix.
|
||||
*/
|
||||
SpiExpressionRequest parse(String expression);
|
||||
|
||||
/**
|
||||
* Add an encryption key to bind to this request.
|
||||
@@ -49,12 +62,12 @@ public interface SpiExpressionRequest {
|
||||
/**
|
||||
* Return the accumulated expression sql for all expressions in this request.
|
||||
*/
|
||||
String getSql();
|
||||
String sql();
|
||||
|
||||
/**
|
||||
* Return the ordered list of bind values for all expressions in this request.
|
||||
*/
|
||||
List<Object> getBindValues();
|
||||
List<Object> bindValues();
|
||||
|
||||
/**
|
||||
* Increments the parameter index and returns that value.
|
||||
|
||||
@@ -127,7 +127,7 @@ public final class OrmQueryRequest<T> extends BeanRequest implements SpiOrmQuery
|
||||
* iteration is fine.
|
||||
*/
|
||||
public int secondaryQueriesMinBatchSize() {
|
||||
return loadContext.getSecondaryQueriesMinBatchSize();
|
||||
return loadContext.secondaryQueriesMinBatchSize();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -416,8 +416,8 @@ public class BeanPropertyAssocMany<T> extends BeanPropertyAssoc<T> implements ST
|
||||
public String assocIsEmpty(SpiExpressionRequest request, String path) {
|
||||
boolean softDelete = targetDescriptor.isSoftDelete();
|
||||
boolean needsX2Table = softDelete || extraWhere() != null;
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
SpiQuery<?> query = request.getQueryRequest().query();
|
||||
StringBuilder sb = new StringBuilder(50).append("from "); // use from to stop parsing on table name
|
||||
SpiQuery<?> query = request.queryRequest().query();
|
||||
if (hasJoinTable()) {
|
||||
sb.append(query.isAsDraft() ? intersectionDraftTable : intersectionPublishTable);
|
||||
} else {
|
||||
|
||||
@@ -46,25 +46,37 @@ public abstract class DeployParser {
|
||||
|
||||
protected abstract String convertWord();
|
||||
|
||||
public abstract String getDeployWord(String expression);
|
||||
public abstract String deployWord(String expression);
|
||||
|
||||
/**
|
||||
* Return the join includes.
|
||||
*/
|
||||
public abstract Set<String> getIncludes();
|
||||
public abstract Set<String> includes();
|
||||
|
||||
public void setEncrypted(boolean encrypted) {
|
||||
this.encrypted = encrypted;
|
||||
}
|
||||
|
||||
public String parse(String source) {
|
||||
if (source == null) {
|
||||
/**
|
||||
* Fast path parse() which first checks that the source is a bean property.
|
||||
*/
|
||||
public String property(String expression) {
|
||||
String deployWord = deployWord(expression);
|
||||
if (deployWord != null) {
|
||||
return deployWord;
|
||||
}
|
||||
// fallback to use parse()
|
||||
return parse(expression);
|
||||
}
|
||||
|
||||
public String parse(String expression) {
|
||||
if (expression == null) {
|
||||
return null;
|
||||
}
|
||||
pos = -1;
|
||||
this.source = source;
|
||||
this.sourceLength = source.length();
|
||||
this.sb = new StringBuilder(source.length() + 20);
|
||||
this.source = expression;
|
||||
this.sourceLength = expression.length();
|
||||
this.sb = new StringBuilder(expression.length() + 20);
|
||||
while (nextWord()) {
|
||||
if (skipWordConvert()) {
|
||||
sb.append(word);
|
||||
|
||||
@@ -37,12 +37,12 @@ public final class DeployPropertyParser extends DeployParser {
|
||||
/**
|
||||
* Return the first property found by the parser.
|
||||
*/
|
||||
public ElPropertyDeploy getFirstProp() {
|
||||
public ElPropertyDeploy firstProp() {
|
||||
return firstProp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getIncludes() {
|
||||
public Set<String> includes() {
|
||||
return includes;
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public final class DeployPropertyParser extends DeployParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
public String deployWord(String expression) {
|
||||
ElPropertyDeploy elProp = beanDescriptor.elPropertyDeploy(expression);
|
||||
if (elProp == null) {
|
||||
return null;
|
||||
@@ -70,7 +70,7 @@ public final class DeployPropertyParser extends DeployParser {
|
||||
|
||||
@Override
|
||||
public String convertWord() {
|
||||
String r = getDeployWord(word);
|
||||
String r = deployWord(word);
|
||||
return r == null ? word : r;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -19,18 +19,18 @@ public class DeployPropertyParserMap extends DeployParser {
|
||||
* Returns null for raw sql queries.
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getIncludes() {
|
||||
public Set<String> includes() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertWord() {
|
||||
String r = getDeployWord(word);
|
||||
String r = deployWord(word);
|
||||
return r == null ? word : r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
public String deployWord(String expression) {
|
||||
return map.get(expression);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
* Return null as not used for updates.
|
||||
*/
|
||||
@Override
|
||||
public Set<String> getIncludes() {
|
||||
public Set<String> includes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String convertWord() {
|
||||
String dbWord = getDeployWord(word);
|
||||
String dbWord = deployWord(word);
|
||||
if (dbWord != null) {
|
||||
return dbWord;
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
start = dotPos + 1;
|
||||
String remainder = currentWord.substring(start);
|
||||
|
||||
String dbWord = getDeployWord(remainder);
|
||||
String dbWord = deployWord(remainder);
|
||||
if (dbWord != null) {
|
||||
// we have found a match for the remainder
|
||||
localBuffer.append(dbWord);
|
||||
@@ -72,7 +72,7 @@ public final class DeployUpdateParser extends DeployParser {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
public String deployWord(String expression) {
|
||||
if (expression.equalsIgnoreCase(beanDescriptor.name())) {
|
||||
return beanDescriptor.baseTable();
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ final class FormulaPropertyPath {
|
||||
parsed = parsed.replace("${}", "${" + path + "}");
|
||||
}
|
||||
this.parsedAggregation = buildFormula(parsed);
|
||||
this.firstProp = parser.getFirstProp();
|
||||
this.firstProp = parser.firstProp();
|
||||
}
|
||||
|
||||
private void parseSuffix(String suffix) {
|
||||
|
||||
@@ -82,9 +82,9 @@ public final class IntersectionRow {
|
||||
idIn.addSqlNoAlias(er);
|
||||
idIn.addBindValues(er);
|
||||
sb.append(" and not ( ");
|
||||
sb.append(er.getSql());
|
||||
sb.append(er.sql());
|
||||
sb.append(" ) ");
|
||||
List<Object> bindValues = er.getBindValues();
|
||||
List<Object> bindValues = er.bindValues();
|
||||
for (Object bindValue : bindValues) {
|
||||
bindParams.setParameter(++count, bindValue);
|
||||
}
|
||||
|
||||
+4
-27
@@ -8,31 +8,14 @@ import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.config.TableName;
|
||||
import io.ebean.config.dbplatform.IdType;
|
||||
import io.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import io.ebean.event.BeanFindController;
|
||||
import io.ebean.event.BeanPersistController;
|
||||
import io.ebean.event.BeanPersistListener;
|
||||
import io.ebean.event.BeanPostConstructListener;
|
||||
import io.ebean.event.BeanPostLoad;
|
||||
import io.ebean.event.BeanQueryAdapter;
|
||||
import io.ebean.event.*;
|
||||
import io.ebean.event.changelog.ChangeLogFilter;
|
||||
import io.ebean.text.PathProperties;
|
||||
import io.ebean.util.SplitName;
|
||||
import io.ebeaninternal.api.ConcurrencyMode;
|
||||
import io.ebeaninternal.server.core.CacheOptions;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
|
||||
import io.ebeaninternal.server.deploy.ChainedBeanPersistController;
|
||||
import io.ebeaninternal.server.deploy.ChainedBeanPersistListener;
|
||||
import io.ebeaninternal.server.deploy.ChainedBeanPostConstructListener;
|
||||
import io.ebeaninternal.server.deploy.ChainedBeanPostLoad;
|
||||
import io.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import io.ebeaninternal.server.deploy.DeployPropertyParserMap;
|
||||
import io.ebeaninternal.server.deploy.IdentityMode;
|
||||
import io.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import io.ebeaninternal.server.deploy.InheritInfo;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import io.ebeaninternal.server.deploy.TableJoin;
|
||||
import io.ebeaninternal.server.deploy.TablespaceMeta;
|
||||
import io.ebeaninternal.server.deploy.*;
|
||||
import io.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import io.ebeaninternal.server.idgen.UuidV1IdGenerator;
|
||||
import io.ebeaninternal.server.idgen.UuidV1RndIdGenerator;
|
||||
@@ -41,13 +24,7 @@ import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.MappedSuperclass;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Describes Beans including their deployment information.
|
||||
@@ -1102,7 +1079,7 @@ public class DeployBeanDescriptor<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDeployWord(String expression) {
|
||||
public String deployWord(String expression) {
|
||||
return descriptor.getDeployWord(expression);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,7 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.util.SplitName;
|
||||
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.el.ElPropertyDeploy;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
@@ -102,6 +98,6 @@ abstract class AbstractExpression implements SpiExpression {
|
||||
}
|
||||
|
||||
protected final ElPropertyValue getElProp(SpiExpressionRequest request) {
|
||||
return request.getBeanDescriptor().elGetValue(propName);
|
||||
return request.descriptor().elGetValue(propName);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-6
@@ -1,10 +1,6 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
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.server.el.ElPropertyDeploy;
|
||||
|
||||
@@ -80,7 +76,7 @@ final class AllEqualsExpression extends NonPrepareExpression {
|
||||
if (count > 0) {
|
||||
request.append("and ");
|
||||
}
|
||||
request.append(name(propName));
|
||||
request.property(name(propName));
|
||||
if (value == null) {
|
||||
request.append(" is null ");
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ final class ArrayContainsExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.getDbPlatformHandler().arrayContains(request, propName, contains, values);
|
||||
request.platformHandler().arrayContains(request, propName, contains, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ final class ArrayIsEmptyExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.getDbPlatformHandler().arrayIsEmpty(request, propName, empty);
|
||||
request.platformHandler().arrayIsEmpty(request, propName, empty);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -52,7 +52,7 @@ final class BetweenExpression extends AbstractExpression {
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
pname = prop.beanProperty().decryptProperty(propName);
|
||||
}
|
||||
request.append(pname).append(_BETWEEN);
|
||||
request.property(pname).append(_BETWEEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-6
@@ -1,11 +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.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
|
||||
@@ -85,7 +81,7 @@ final class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(" ?").append(BETWEEN).append(name(lowProperty)).append(" and ").append(name(highProperty));
|
||||
request.append(" ?").append(BETWEEN).property(name(lowProperty)).append(" and ").property(name(highProperty));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,7 +48,7 @@ final class BitwiseExpression extends AbstractExpression {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
// Use DB specific expression handling
|
||||
request.getDbPlatformHandler().bitwise(request, propName, operator, flags, compare, match);
|
||||
request.platformHandler().bitwise(request, propName, operator, flags, compare, match);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -52,9 +52,9 @@ final class CaseInsensitiveEqualExpression extends AbstractValueExpression {
|
||||
pname = prop.beanProperty().decryptProperty(propName);
|
||||
}
|
||||
if (not) {
|
||||
request.append("lower(").append(pname).append(") != ?");
|
||||
request.append("lower(").property(pname).append(") != ?");
|
||||
} else {
|
||||
request.append("lower(").append(pname).append(") = ?");
|
||||
request.append("lower(").property(pname).append(") = ?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+64
-9
@@ -5,7 +5,6 @@ import io.ebean.bean.EntityBean;
|
||||
import io.ebean.search.*;
|
||||
import io.ebeaninternal.api.SpiExpressionFactory;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.expression.SubQueryExpression.SQOp;
|
||||
import io.ebeaninternal.server.grammer.EqlParser;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -149,7 +148,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression eq(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.EQ, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.EQ, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +169,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression ne(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.NE, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.NE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,7 +259,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression gt(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.GT, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.GT, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,7 +285,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression ge(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.GE, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.GE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,7 +312,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression lt(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.LT, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.LT, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -326,7 +325,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
|
||||
@Override
|
||||
public Expression le(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.LE, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.LE, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -480,12 +479,68 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
return new InExpression(propertyName, values, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
@Override
|
||||
public Expression exists(String subQuery, Object... bindValues) {
|
||||
return new ExistsSqlQueryExpression(false, subQuery, bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
@Override
|
||||
public Expression notExists(String subQuery, Object... bindValues) {
|
||||
return new ExistsSqlQueryExpression(true, subQuery, bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* In - using a subQuery.
|
||||
*/
|
||||
@Override
|
||||
public Expression in(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.IN, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.IN, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression inSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.IN, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression notInSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.NOTIN, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression eqSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.EQ, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression neSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.NE, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression geSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.GE, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression gtSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.GT, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression leSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.LE, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Expression ltSubQuery(String propertyName, String subQuery, Object... bindValues) {
|
||||
return new SubQueryRawExpression(SubQueryOp.LT, propertyName, subQuery, bindValues);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -527,7 +582,7 @@ public class DefaultExpressionFactory implements SpiExpressionFactory {
|
||||
*/
|
||||
@Override
|
||||
public Expression notIn(String propertyName, Query<?> subQuery) {
|
||||
return new SubQueryExpression(SQOp.NOTIN, propertyName, (SpiQuery<?>) subQuery);
|
||||
return new SubQueryExpression(SubQueryOp.NOTIN, propertyName, (SpiQuery<?>) subQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+55
-39
@@ -2,51 +2,16 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.CountDistinctOrder;
|
||||
import io.ebean.DtoQuery;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionFactory;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.FutureRowCount;
|
||||
import io.ebean.Junction;
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebean.PagedList;
|
||||
import io.ebean.Pairs;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.UpdateQuery;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.*;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.search.Match;
|
||||
import io.ebean.search.MultiMatch;
|
||||
import io.ebean.search.TextCommonTerms;
|
||||
import io.ebean.search.TextQueryString;
|
||||
import io.ebean.search.TextSimple;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.ManyWhereJoins;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.api.SpiExpressionValidation;
|
||||
import io.ebeaninternal.api.SpiJunction;
|
||||
import io.ebean.search.*;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -953,6 +918,57 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.inPairs(pairs));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> exists(String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.exists(sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> notExists(String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.notExists(sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.inSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.notInSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.eqSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.neSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.gtSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.geSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.ltSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return add(expr.leSubQuery(propertyName, sqlSubQuery, bindValues));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> in(String propertyName, Query<?> subQuery) {
|
||||
return add(expr.in(propertyName, subQuery));
|
||||
|
||||
+30
-11
@@ -2,12 +2,12 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.DeployParser;
|
||||
import io.ebeaninternal.server.expression.platform.DbExpressionHandler;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
@@ -67,14 +67,13 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbExpressionHandler getDbPlatformHandler() {
|
||||
public DbExpressionHandler platformHandler() {
|
||||
return binder.getDbExpressionHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseDeploy(String logicalProp) {
|
||||
|
||||
String s = deployParser.getDeployWord(logicalProp);
|
||||
String s = deployParser.deployWord(logicalProp);
|
||||
return s == null ? logicalProp : s;
|
||||
}
|
||||
|
||||
@@ -102,12 +101,12 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
public BeanDescriptor<?> descriptor() {
|
||||
return beanDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiOrmQueryRequest<?> getQueryRequest() {
|
||||
public SpiOrmQueryRequest<?> queryRequest() {
|
||||
return queryRequest;
|
||||
}
|
||||
|
||||
@@ -115,8 +114,28 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
* Append text the underlying sql expression.
|
||||
*/
|
||||
@Override
|
||||
public SpiExpressionRequest append(String sqlExpression) {
|
||||
sql.append(sqlExpression);
|
||||
public SpiExpressionRequest append(String expression) {
|
||||
sql.append(expression);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionRequest property(String expression) {
|
||||
if (deployParser == null) {
|
||||
sql.append(expression);
|
||||
} else {
|
||||
sql.append(deployParser.property(expression));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionRequest parse(String expression) {
|
||||
if (deployParser == null) {
|
||||
sql.append(expression);
|
||||
} else {
|
||||
sql.append(deployParser.parse(expression));
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -143,17 +162,17 @@ public final class DefaultExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
}
|
||||
|
||||
public String getBindLog() {
|
||||
public String bindLog() {
|
||||
return bindLog == null ? "" : bindLog.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
public String sql() {
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getBindValues() {
|
||||
public List<Object> bindValues() {
|
||||
return bindValues;
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -93,11 +93,9 @@ final class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreE
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
if (not) {
|
||||
request.append(" not");
|
||||
request.append("not ");
|
||||
}
|
||||
request.append(" exists (");
|
||||
request.append(sql);
|
||||
request.append(")");
|
||||
request.append("exists (").parse(sql).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
final class ExistsSqlQueryExpression implements SpiExpression, UnsupportedDocStoreExpression {
|
||||
|
||||
private final boolean not;
|
||||
private final String subQuery;
|
||||
private final Object[] bindParams;
|
||||
|
||||
ExistsSqlQueryExpression(boolean not, String subQuery, Object[] bindParams) {
|
||||
this.not = not;
|
||||
this.subQuery = subQuery;
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prefixProperty(String path) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean naturalKey(NaturalKeyQueryData<?> data) {
|
||||
// can't use naturalKey cache
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void simplify() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) {
|
||||
throw new IllegalStateException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(StringBuilder builder) {
|
||||
builder.append("ExistsSqlQuery[").append(" not:").append(not);
|
||||
builder.append(" sql:").append(subQuery).append(" ?:").append(bindParams.length).append("]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryBindKey(BindValuesKey key) {
|
||||
for (Object value : bindParams) {
|
||||
key.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
if (not) {
|
||||
request.append("not ");
|
||||
}
|
||||
request.append("exists (").parse(subQuery).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
final ExistsSqlQueryExpression that = (ExistsSqlQueryExpression) other;
|
||||
return Arrays.equals(bindParams, that.bindParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
// Nothing to do for exists expression
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(SpiExpressionValidation validation) {
|
||||
// Nothing to do for exists expression
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
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 java.io.IOException;
|
||||
@@ -50,23 +46,16 @@ final class IdExpression extends NonPrepareExpression implements SpiExpression {
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
// 'flatten' EmbeddedId and multiple ID cases
|
||||
// into an array of the underlying scalar field values
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
Object[] bindIdValues = r.getBeanDescriptor().bindIdValues(value);
|
||||
for (Object bindIdValue : bindIdValues) {
|
||||
for (Object bindIdValue : request.descriptor().bindIdValues(value)) {
|
||||
request.addBindValue(bindIdValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
String idSql = r.getBeanDescriptor().idBinderIdSql(null);
|
||||
|
||||
request.append(idSql);
|
||||
request.parse(request.descriptor().idBinderIdSql(null));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
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.core.BindPadding;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.id.IdBinder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* In a collection of ID values.
|
||||
@@ -74,42 +66,34 @@ public final class IdInExpression extends NonPrepareExpression implements IdInCo
|
||||
return;
|
||||
}
|
||||
// Bind the ID values including EmbeddedId and multiple ID
|
||||
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
|
||||
IdBinder idBinder = descriptor.idBinder();
|
||||
idBinder.addIdInBindValues(request, idCollection);
|
||||
request.descriptor().idBinder().addIdInBindValues(request, idCollection);
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with deleting non-attached detail beans during stateless update.
|
||||
*/
|
||||
public void addSqlNoAlias(SpiExpressionRequest request) {
|
||||
|
||||
DefaultExpressionRequest r = (DefaultExpressionRequest) request;
|
||||
BeanDescriptor<?> descriptor = r.getBeanDescriptor();
|
||||
IdBinder idBinder = descriptor.idBinder();
|
||||
if (idCollection.isEmpty()) {
|
||||
request.append(SQL_FALSE); // append false for this stage
|
||||
} else {
|
||||
request.append(descriptor.idBinder().getBindIdInSql(null));
|
||||
String inClause = idBinder.getIdInValueExpr(false, idCollection.size());
|
||||
request.append(inClause);
|
||||
final BeanDescriptor<?> descriptor = request.descriptor();
|
||||
request.property(descriptor.idBinder().getBindIdInSql(null));
|
||||
request.append(descriptor.idBinder().getIdInValueExpr(false, idCollection.size()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
BeanDescriptor<?> descriptor = request.getBeanDescriptor();
|
||||
IdBinder idBinder = descriptor.idBinder();
|
||||
if (idCollection.isEmpty()) {
|
||||
request.append(SQL_FALSE); // append false for this stage
|
||||
} else {
|
||||
final BeanDescriptor<?> descriptor = request.descriptor();
|
||||
final IdBinder idBinder = descriptor.idBinder();
|
||||
if (idBinder.isComplexId()) {
|
||||
request.append(descriptor.idBinderInLHSSql());
|
||||
request.parse(descriptor.idBinderInLHSSql());
|
||||
request.append(idBinder.getIdInValueExpr(false, idCollection.size()));
|
||||
} else {
|
||||
request.append(idBinder.getBeanProperty().name());
|
||||
request.property(idBinder.getBeanProperty().name());
|
||||
request.appendInExpression(false, idCollection);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,21 +156,20 @@ public final class InExpression extends AbstractExpression implements IdInCommon
|
||||
request.append(not ? SQL_TRUE : SQL_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
request.append(prop.assocIdInExpr(propName));
|
||||
request.parse(prop.assocIdInExpr(propName));
|
||||
request.append(prop.assocIdInValueExpr(not, bindValues.size()));
|
||||
return;
|
||||
}
|
||||
if (prop.isDbEncrypted()) {
|
||||
request.append(prop.beanProperty().decryptProperty(propName));
|
||||
request.parse(prop.beanProperty().decryptProperty(propName));
|
||||
request.appendInExpression(not, bindValues);
|
||||
return;
|
||||
}
|
||||
}
|
||||
request.append(propName);
|
||||
request.property(propName);
|
||||
request.appendInExpression(not, bindValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -85,14 +85,11 @@ final class InPairsExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
if (entries.isEmpty()) {
|
||||
String expr = not ? SQL_TRUE : SQL_FALSE;
|
||||
request.append(expr);
|
||||
request.append(not ? SQL_TRUE : SQL_FALSE);
|
||||
return;
|
||||
}
|
||||
|
||||
request.append(request.getDbPlatformHandler().concat(property0, separator, property1, suffix));
|
||||
request.parse(request.platformHandler().concat(property0, separator, property1, suffix));
|
||||
request.appendInExpression(not, concatBindValues);
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ final class InRangeExpression extends AbstractExpression {
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
pname = prop.beanProperty().decryptProperty(propName);
|
||||
}
|
||||
request.append("(").append(pname).append(" >= ? and ").append(pname).append(" < ?)");
|
||||
request.append("(").property(pname).append(" >= ? and ").property(pname).append(" < ?)");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
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.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebean.util.SplitName;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -78,13 +78,12 @@ final class IsEmptyExpression extends AbstractExpression {
|
||||
* Append an exists subQuery for the property.
|
||||
*/
|
||||
static void isEmptySql(SpiExpressionRequest request, ElPropertyValue prop, boolean empty, String propertyPath) {
|
||||
|
||||
if (empty) {
|
||||
request.append("not ");
|
||||
}
|
||||
request
|
||||
.append("exists (select 1 from ")
|
||||
.append(prop.assocIsEmpty(request, propertyPath))
|
||||
.append("exists (select 1 ")
|
||||
.parse(prop.assocIsEmpty(request, propertyPath))
|
||||
.append(")");
|
||||
}
|
||||
|
||||
|
||||
@@ -97,14 +97,12 @@ final class JsonPathExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
// Use DB specific expression handling (Postgres and Oracle supported)
|
||||
request.getDbPlatformHandler().json(request, propName, path, operator, value);
|
||||
request.platformHandler().json(request, propName, path, operator, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
|
||||
if (value != null) {
|
||||
// value is null for EXISTS/NOT EXISTS
|
||||
request.addBindValue(value);
|
||||
|
||||
+54
-36
@@ -2,48 +2,16 @@ package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.avaje.lang.NonNullApi;
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.CountDistinctOrder;
|
||||
import io.ebean.DtoQuery;
|
||||
import io.ebean.Expression;
|
||||
import io.ebean.ExpressionList;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.FetchPath;
|
||||
import io.ebean.FutureIds;
|
||||
import io.ebean.FutureList;
|
||||
import io.ebean.FutureRowCount;
|
||||
import io.ebean.Junction;
|
||||
import io.ebean.OrderBy;
|
||||
import io.ebean.PagedList;
|
||||
import io.ebean.Pairs;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.QueryIterator;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.UpdateQuery;
|
||||
import io.ebean.Version;
|
||||
import io.ebean.*;
|
||||
import io.ebean.event.BeanQueryRequest;
|
||||
import io.ebean.search.Match;
|
||||
import io.ebean.search.MultiMatch;
|
||||
import io.ebean.search.TextCommonTerms;
|
||||
import io.ebean.search.TextQueryString;
|
||||
import io.ebean.search.TextSimple;
|
||||
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.SpiJunction;
|
||||
import io.ebean.search.*;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@@ -762,6 +730,56 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.in(propertyName, subQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> exists(String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.exists(sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> notExists(String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.notExists(sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> inSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.inSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> notInSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.notInSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.eqSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> neSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.neSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> gtSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.gtSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> geSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.geSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> ltSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.ltSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> leSubQuery(String propertyName, String sqlSubQuery, Object... bindValues) {
|
||||
return exprList.leSubQuery(propertyName, sqlSubQuery, bindValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> notIn(String propertyName, Collection<?> values) {
|
||||
return exprList.notIn(propertyName, values);
|
||||
|
||||
@@ -44,9 +44,9 @@ final class LikeExpression extends AbstractValueExpression {
|
||||
pname = prop.beanProperty().decryptProperty(propName);
|
||||
}
|
||||
if (caseInsensitive) {
|
||||
request.append("lower(").append(pname).append(")");
|
||||
request.append("lower(").property(pname).append(")");
|
||||
} else {
|
||||
request.append(pname);
|
||||
request.property(pname);
|
||||
}
|
||||
if (type == LikeType.EQUAL_TO) {
|
||||
request.append(" = ?");
|
||||
|
||||
+1
-3
@@ -36,14 +36,12 @@ final class NativeILikeExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
String pname = propName;
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null && prop.isDbEncrypted()) {
|
||||
pname = prop.beanProperty().decryptProperty(propName);
|
||||
}
|
||||
|
||||
request.append(pname).append(" ilike ?");
|
||||
request.property(pname).append(" ilike ?");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,18 +57,16 @@ final class NullExpression extends AbstractExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
if (assocMany) {
|
||||
// translate to exists subquery
|
||||
// translate to exists sub-query
|
||||
IsEmptyExpression.isEmptySql(request, elProperty, !notNull, propertyPath);
|
||||
return;
|
||||
}
|
||||
|
||||
String nullExpr = notNull ? " is not null" : " is null";
|
||||
if (elProperty != null && elProperty.isAssocId()) {
|
||||
request.append(elProperty.assocIdExpression(propName, nullExpr));
|
||||
request.parse(elProperty.assocIdExpression(propName, nullExpr));
|
||||
} else {
|
||||
request.append(propName).append(nullExpr);
|
||||
request.property(propName).append(nullExpr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
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.server.persist.MultiValueWrapper;
|
||||
|
||||
@@ -57,7 +53,7 @@ final class RawExpression extends NonPrepareExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(sql);
|
||||
request.parse(sql);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,11 +2,11 @@ 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.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.NaturalKeyQueryData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -97,20 +97,19 @@ public final class SimpleExpression extends AbstractValueExpression {
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
ElPropertyValue prop = getElProp(request);
|
||||
if (prop != null) {
|
||||
if (prop.isAssocId()) {
|
||||
request.append(prop.assocIdExpression(propName, type.bind()));
|
||||
request.parse(prop.assocIdExpression(propName, type.bind()));
|
||||
return;
|
||||
}
|
||||
if (prop.isDbEncrypted()) {
|
||||
String dsql = prop.beanProperty().decryptProperty(propName);
|
||||
request.append(dsql).append(type.bind());
|
||||
request.parse(dsql).append(type.bind());
|
||||
return;
|
||||
}
|
||||
}
|
||||
request.append(propName).append(type.bind());
|
||||
request.property(propName).append(type.bind());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+4
-19
@@ -12,33 +12,18 @@ import java.util.List;
|
||||
*/
|
||||
final class SubQueryExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
|
||||
|
||||
enum SQOp {
|
||||
EQ(" = "),
|
||||
NE(" <> "),
|
||||
GT(" > "),
|
||||
GE(" >= "),
|
||||
LT(" < "),
|
||||
LE(" <= "),
|
||||
IN(" in "),
|
||||
NOTIN(" not in ");
|
||||
final String expression;
|
||||
SQOp(String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
|
||||
private final SQOp op;
|
||||
private final SubQueryOp op;
|
||||
private final SpiQuery<?> subQuery;
|
||||
private List<Object> bindParams;
|
||||
private String sql;
|
||||
|
||||
SubQueryExpression(SQOp op, String propertyName, SpiQuery<?> subQuery) {
|
||||
SubQueryExpression(SubQueryOp op, String propertyName, SpiQuery<?> subQuery) {
|
||||
super(propertyName);
|
||||
this.op = op;
|
||||
this.subQuery = subQuery;
|
||||
}
|
||||
|
||||
SubQueryExpression(SQOp op, String propertyName, String sql, List<Object> bindParams) {
|
||||
SubQueryExpression(SubQueryOp op, String propertyName, String sql, List<Object> bindParams) {
|
||||
super(propertyName);
|
||||
this.op = op;
|
||||
this.subQuery = null;
|
||||
@@ -90,7 +75,7 @@ final class SubQueryExpression extends AbstractExpression implements Unsupported
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.append(propName).append(op.expression).append("(").append(sql).append(")");
|
||||
request.property(propName).append(op.expression).append("(").parse(sql).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
enum SubQueryOp {
|
||||
EQ(" = "),
|
||||
NE(" <> "),
|
||||
GT(" > "),
|
||||
GE(" >= "),
|
||||
LT(" < "),
|
||||
LE(" <= "),
|
||||
IN(" in "),
|
||||
NOTIN(" not in ");
|
||||
final String expression;
|
||||
|
||||
SubQueryOp(String expression) {
|
||||
this.expression = expression;
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
package io.ebeaninternal.server.expression;
|
||||
|
||||
import io.ebeaninternal.api.BindValuesKey;
|
||||
import io.ebeaninternal.api.SpiExpression;
|
||||
import io.ebeaninternal.api.SpiExpressionRequest;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Raw SQL based Sub-Query expression.
|
||||
*/
|
||||
final class SubQueryRawExpression extends AbstractExpression implements UnsupportedDocStoreExpression {
|
||||
|
||||
private final SubQueryOp op;
|
||||
private final String subQuery;
|
||||
private final Object[] bindParams;
|
||||
|
||||
SubQueryRawExpression(SubQueryOp op, String propertyName, String subQuery, Object[] bindParams) {
|
||||
super(propertyName);
|
||||
this.op = op;
|
||||
this.subQuery = subQuery;
|
||||
this.bindParams = bindParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) {
|
||||
throw new IllegalStateException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(StringBuilder builder) {
|
||||
builder.append("SubQueryRaw[").append(propName).append(op.expression)
|
||||
.append(" subQuery:").append(subQuery)
|
||||
.append(" ?:").append(bindParams.length).append("]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryBindKey(BindValuesKey key) {
|
||||
for (Object value : bindParams) {
|
||||
key.add(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
request.property(propName).append(op.expression).append("(").append(subQuery).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
for (Object bindParam : bindParams) {
|
||||
request.addBindValue(bindParam);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
final SubQueryRawExpression that = (SubQueryRawExpression) other;
|
||||
return Arrays.equals(bindParams, that.bindParams);
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -10,8 +10,8 @@ abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
String bitOp = bitOp(operator);
|
||||
request.append("(").append(propName).append(" ").append(bitOp).append(" ? ").append(compare).append(" ?)");
|
||||
final String bitOp = bitOp(operator);
|
||||
request.append("(").property(propName).append(" ").append(bitOp).append(" ? ").append(compare).append(" ?)");
|
||||
}
|
||||
|
||||
private String bitOp(BitwiseOp operator) {
|
||||
@@ -29,8 +29,8 @@ abstract class BaseDbExpression implements DbExpressionHandler {
|
||||
* Common alternative where the bitwise operation is a function (specifically bitand is used - H2 and Oracle).
|
||||
*/
|
||||
protected void bitwiseFunction(SpiExpressionRequest request, String propName, BitwiseOp operator, String compare) {
|
||||
String funcName = functionName(operator);
|
||||
request.append(funcName).append("(").append(propName).append(", ?) ").append(compare).append(" ?");
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append("(").property(propName).append(", ?) ").append(compare).append(" ?");
|
||||
}
|
||||
|
||||
protected String functionName(BitwiseOp operator) {
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ final class H2DbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void bitwise(SpiExpressionRequest request, String propName, BitwiseOp operator, long flags, String compare, long match) {
|
||||
String funcName = functionName(operator);
|
||||
request.append(funcName).append("(").append(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)");
|
||||
final String funcName = functionName(operator);
|
||||
request.append(funcName).append("(").property(propName).append(", cast(? as long)) ").append(compare).append(" cast(? as long)");
|
||||
}
|
||||
}
|
||||
|
||||
+3
-5
@@ -16,13 +16,12 @@ final class HanaDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("json_value(").append(propName).append(", '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("cardinality(").append(propName).append(")");
|
||||
request.append("cardinality(").property(propName).append(")");
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
} else {
|
||||
@@ -51,8 +50,7 @@ final class HanaDbExpression extends BaseDbExpression {
|
||||
if (!contains) {
|
||||
request.append(" not ");
|
||||
}
|
||||
request.append(" member of ").append(propName).append(")");
|
||||
|
||||
request.append(" member of ").property(propName).append(")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-2
@@ -10,7 +10,6 @@ final class MariaDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("(").append(propName).append(" ->> '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
request.append("(").property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -10,8 +10,7 @@ final class MySqlDbExpression extends BasicDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
request.append("(").append(propName).append(" ->> '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
request.append("(").property(propName).append(" ->> '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+3
-4
@@ -17,12 +17,11 @@ final class OracleDbExpression extends BaseDbExpression {
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
if (operator == Op.EXISTS) {
|
||||
request.append("json_exists(").append(propName).append(", '$.").append(path).append("')");
|
||||
request.append("json_exists(").property(propName).append(", '$.").append(path).append("')");
|
||||
} else if (operator == Op.NOT_EXISTS) {
|
||||
request.append("not json_exists(").append(propName).append(", '$.").append(path).append("')");
|
||||
request.append("not json_exists(").property(propName).append(", '$.").append(path).append("')");
|
||||
} else {
|
||||
request.append("json_value(").append(propName).append(", '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-15
@@ -15,27 +15,22 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
|
||||
StringBuilder sb = new StringBuilder(50);
|
||||
String[] paths = path.split("\\.");
|
||||
if (paths.length == 1) {
|
||||
// (t0.content ->> 'title') = 'Some value'
|
||||
sb.append("(").append(propName).append(" ->> '").append(path).append("')");
|
||||
|
||||
request.append("(").property(propName).append(" ->> '").append(path).append("')");
|
||||
} else {
|
||||
// (t0.content #>> '{path,inner}') = 'Some value'
|
||||
sb.append("(").append(propName).append(" #>> '{");
|
||||
request.append("(").property(propName).append(" #>> '{");
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
if (i > 0) {
|
||||
sb.append(",");
|
||||
request.append(",");
|
||||
}
|
||||
sb.append(paths[i]);
|
||||
request.append(paths[i]);
|
||||
}
|
||||
sb.append("}')");
|
||||
request.append("}')");
|
||||
}
|
||||
|
||||
request.append(sb.toString());
|
||||
request.append(PostgresCast.cast(value));
|
||||
request.append(operator.bind());
|
||||
request.append(PostgresCast.cast(value)).append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -43,12 +38,11 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
if (!contains) {
|
||||
request.append("not (");
|
||||
}
|
||||
request.append(propName).append(" @> array[?");
|
||||
request.property(propName).append(" @> array[?");
|
||||
for (int i = 1; i < values.length; i++) {
|
||||
request.append(",?");
|
||||
}
|
||||
request.append("]");
|
||||
request.append(PostgresCast.cast(values[0], true));
|
||||
request.append("]").append(PostgresCast.cast(values[0], true));
|
||||
if (!contains) {
|
||||
request.append(")");
|
||||
}
|
||||
@@ -56,7 +50,7 @@ final class PostgresDbExpression extends BaseDbExpression {
|
||||
|
||||
@Override
|
||||
public void arrayIsEmpty(SpiExpressionRequest request, String propName, boolean empty) {
|
||||
request.append("coalesce(cardinality(").append(propName).append("),0)");
|
||||
request.append("coalesce(cardinality(").property(propName).append("),0)");
|
||||
if (empty) {
|
||||
request.append(" = 0");
|
||||
} else {
|
||||
|
||||
+1
-2
@@ -11,8 +11,7 @@ final class SqlServerDbExpression extends BaseDbExpression {
|
||||
@Override
|
||||
public void json(final SpiExpressionRequest request, final String propName,
|
||||
final String path, final Op operator, final Object value) {
|
||||
request.append("json_value(").append(propName).append(", '$.").append(path).append("')");
|
||||
request.append(operator.bind());
|
||||
request.append("json_value(").property(propName).append(", '$.").append(path).append("')").append(operator.bind());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,12 +35,12 @@ abstract class DLoadBaseContext {
|
||||
|
||||
DLoadBaseContext(DLoadContext parent, BeanDescriptor<?> desc, String path, OrmQueryProperties queryProps) {
|
||||
this.parent = parent;
|
||||
this.serverName = parent.getEbeanServer().name();
|
||||
this.serverName = parent.server().name();
|
||||
this.desc = desc;
|
||||
this.queryProps = queryProps;
|
||||
this.fullPath = parent.getFullPath(path);
|
||||
this.fullPath = parent.fullPath(path);
|
||||
this.hitCache = parent.isBeanCacheGet() && desc.isBeanCaching();
|
||||
this.objectGraphNode = parent.getObjectGraphNode(path);
|
||||
this.objectGraphNode = parent.objectGraphNode(path);
|
||||
this.queryFetch = queryProps != null && queryProps.isQueryFetch();
|
||||
this.batchSize = parent.batchSize(queryProps);
|
||||
}
|
||||
@@ -50,14 +50,14 @@ abstract class DLoadBaseContext {
|
||||
* set onto the secondary query.
|
||||
*/
|
||||
void setLabel(SpiQuery<?> query) {
|
||||
String label = parent.getPlanLabel();
|
||||
String label = parent.planLabel();
|
||||
if (label != null) {
|
||||
query.setProfilePath(label, fullPath, parent.getProfileLocation());
|
||||
query.setProfilePath(label, fullPath, parent.profileLocation());
|
||||
}
|
||||
}
|
||||
|
||||
PersistenceContext getPersistenceContext() {
|
||||
return parent.getPersistenceContext();
|
||||
PersistenceContext persistenceContext() {
|
||||
return parent.persistenceContext();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
if (currentBuffer.isFull()) {
|
||||
currentBuffer = createBuffer(batchSize);
|
||||
}
|
||||
ebi.setBeanLoader(currentBuffer, getPersistenceContext());
|
||||
ebi.setBeanLoader(currentBuffer, persistenceContext());
|
||||
currentBuffer.add(ebi);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
if (bufferList != null) {
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (!loadBuffer.batch.isEmpty()) {
|
||||
parent.getEbeanServer().loadBean(new LoadBeanRequest(loadBuffer, parentRequest));
|
||||
parent.server().loadBean(new LoadBeanRequest(loadBuffer, parentRequest));
|
||||
}
|
||||
if (forEach) {
|
||||
clear();
|
||||
@@ -165,7 +165,7 @@ final class DLoadBeanContext extends DLoadBaseContext implements LoadBeanContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return context.serverName;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,24 +2,11 @@ package io.ebeaninternal.server.loadcontext;
|
||||
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.ProfileLocation;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.CallOrigin;
|
||||
import io.ebean.bean.EntityBeanIntercept;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.ObjectGraphOrigin;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebeaninternal.api.LoadContext;
|
||||
import io.ebeaninternal.api.LoadSecondaryQuery;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.api.SpiQuerySecondary;
|
||||
import io.ebean.bean.*;
|
||||
import io.ebeaninternal.api.*;
|
||||
import io.ebeaninternal.server.autotune.ProfilingListener;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssoc;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import io.ebeaninternal.server.deploy.*;
|
||||
import io.ebeaninternal.server.el.ElPropertyValue;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
|
||||
@@ -127,14 +114,14 @@ public final class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Return the query plan label of the origin query.
|
||||
*/
|
||||
String getPlanLabel() {
|
||||
String planLabel() {
|
||||
return planLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the profile location of the origin query.
|
||||
*/
|
||||
public ProfileLocation getProfileLocation() {
|
||||
public ProfileLocation profileLocation() {
|
||||
return profileLocation;
|
||||
}
|
||||
|
||||
@@ -179,7 +166,7 @@ public final class DLoadContext implements LoadContext {
|
||||
* Return the minimum batch size when using QueryIterator with query joins.
|
||||
*/
|
||||
@Override
|
||||
public int getSecondaryQueriesMinBatchSize() {
|
||||
public int secondaryQueriesMinBatchSize() {
|
||||
if (secQuery == null) {
|
||||
return -1;
|
||||
}
|
||||
@@ -201,7 +188,7 @@ public final class DLoadContext implements LoadContext {
|
||||
public void executeSecondaryQueries(OrmQueryRequest<?> parentRequest, boolean forEach) {
|
||||
if (secQuery != null) {
|
||||
for (OrmQueryProperties aSecQuery : secQuery) {
|
||||
LoadSecondaryQuery load = getLoadSecondaryQuery(aSecQuery.getPath());
|
||||
LoadSecondaryQuery load = loadSecondaryQuery(aSecQuery.getPath());
|
||||
load.loadSecondaryQuery(parentRequest, forEach);
|
||||
}
|
||||
}
|
||||
@@ -210,13 +197,13 @@ public final class DLoadContext implements LoadContext {
|
||||
/**
|
||||
* Return the LoadBeanContext or LoadManyContext for the given path.
|
||||
*/
|
||||
private LoadSecondaryQuery getLoadSecondaryQuery(String path) {
|
||||
private LoadSecondaryQuery loadSecondaryQuery(String path) {
|
||||
LoadSecondaryQuery beanLoad = beanMap.get(path);
|
||||
return beanLoad == null ? manyMap.get(path) : beanLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getObjectGraphNode(String path) {
|
||||
public ObjectGraphNode objectGraphNode(String path) {
|
||||
return nodePathMap.computeIfAbsent(path, this::createObjectGraphNode);
|
||||
}
|
||||
|
||||
@@ -231,7 +218,7 @@ public final class DLoadContext implements LoadContext {
|
||||
return new ObjectGraphNode(origin, path);
|
||||
}
|
||||
|
||||
String getFullPath(String path) {
|
||||
String fullPath(String path) {
|
||||
if (relativePath == null) {
|
||||
return path;
|
||||
} else {
|
||||
@@ -239,7 +226,7 @@ public final class DLoadContext implements LoadContext {
|
||||
}
|
||||
}
|
||||
|
||||
SpiEbeanServer getEbeanServer() {
|
||||
SpiEbeanServer server() {
|
||||
return ebeanServer;
|
||||
}
|
||||
|
||||
@@ -252,23 +239,23 @@ public final class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String path, EntityBeanIntercept ebi) {
|
||||
getBeanContext(path).register(ebi);
|
||||
beanContext(path).register(ebi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String path, EntityBeanIntercept ebi, BeanPropertyAssocOne<?> property) {
|
||||
getBeanContextWithInherit(path, property).register(ebi);
|
||||
beanContextWithInherit(path, property).register(ebi);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void register(String path, BeanPropertyAssocMany<?> many, BeanCollection<?> bc) {
|
||||
getManyContext(path, many).register(bc);
|
||||
manyContext(path, many).register(bc);
|
||||
}
|
||||
|
||||
int batchSize(OrmQueryProperties props) {
|
||||
@@ -279,14 +266,14 @@ public final class DLoadContext implements LoadContext {
|
||||
return batchSize == 0 ? defaultBatchSize : batchSize;
|
||||
}
|
||||
|
||||
DLoadBeanContext getBeanContext(String path) {
|
||||
DLoadBeanContext beanContext(String path) {
|
||||
if (path == null) {
|
||||
return rootBeanContext;
|
||||
}
|
||||
return beanMap.computeIfAbsent(path, p -> createBeanContext(p, null));
|
||||
}
|
||||
|
||||
DLoadBeanContext getBeanContextWithInherit(String path, BeanPropertyAssocOne<?> property) {
|
||||
DLoadBeanContext beanContextWithInherit(String path, BeanPropertyAssocOne<?> property) {
|
||||
String key = path + ":" + property.targetDescriptor().name();
|
||||
return beanMap.computeIfAbsent(key, p -> createBeanContext(property, path));
|
||||
}
|
||||
@@ -300,7 +287,7 @@ public final class DLoadContext implements LoadContext {
|
||||
}
|
||||
}
|
||||
|
||||
DLoadManyContext getManyContext(String path, BeanPropertyAssocMany<?> many) {
|
||||
DLoadManyContext manyContext(String path, BeanPropertyAssocMany<?> many) {
|
||||
return manyMap.computeIfAbsent(path, p -> createManyContext(p, many));
|
||||
}
|
||||
|
||||
@@ -309,12 +296,12 @@ public final class DLoadContext implements LoadContext {
|
||||
}
|
||||
|
||||
private DLoadManyContext createManyContext(String path, OrmQueryProperties queryProps) {
|
||||
BeanPropertyAssocMany<?> p = (BeanPropertyAssocMany<?>) getBeanProperty(rootDescriptor, path);
|
||||
BeanPropertyAssocMany<?> p = (BeanPropertyAssocMany<?>) beanProperty(rootDescriptor, path);
|
||||
return new DLoadManyContext(this, p, path, queryProps);
|
||||
}
|
||||
|
||||
private DLoadBeanContext createBeanContext(String path, OrmQueryProperties queryProps) {
|
||||
BeanPropertyAssoc<?> p = (BeanPropertyAssoc<?>) getBeanProperty(rootDescriptor, path);
|
||||
BeanPropertyAssoc<?> p = (BeanPropertyAssoc<?>) beanProperty(rootDescriptor, path);
|
||||
return new DLoadBeanContext(this, p.targetDescriptor(), path, queryProps);
|
||||
}
|
||||
|
||||
@@ -322,7 +309,7 @@ public final class DLoadContext implements LoadContext {
|
||||
return new DLoadBeanContext(this, property.targetDescriptor(), path, null);
|
||||
}
|
||||
|
||||
private BeanProperty getBeanProperty(BeanDescriptor<?> desc, String path) {
|
||||
private BeanProperty beanProperty(BeanDescriptor<?> desc, String path) {
|
||||
return desc.findPropertyFromPath(path);
|
||||
}
|
||||
|
||||
|
||||
+11
-15
@@ -1,10 +1,6 @@
|
||||
package io.ebeaninternal.server.loadcontext;
|
||||
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.bean.BeanCollectionLoader;
|
||||
import io.ebean.bean.EntityBean;
|
||||
import io.ebean.bean.ObjectGraphNode;
|
||||
import io.ebean.bean.PersistenceContext;
|
||||
import io.ebean.bean.*;
|
||||
import io.ebeaninternal.api.LoadManyBuffer;
|
||||
import io.ebeaninternal.api.LoadManyContext;
|
||||
import io.ebeaninternal.api.LoadManyRequest;
|
||||
@@ -77,7 +73,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
|
||||
|
||||
public String getName() {
|
||||
return parent.getEbeanServer().name();
|
||||
return parent.server().name();
|
||||
}
|
||||
|
||||
public void register(BeanCollection<?> bc) {
|
||||
@@ -99,7 +95,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
for (LoadBuffer loadBuffer : bufferList) {
|
||||
if (loadBuffer.size() > 0) {
|
||||
LoadManyRequest req = new LoadManyRequest(loadBuffer, parentRequest);
|
||||
parent.getEbeanServer().loadMany(req);
|
||||
parent.server().loadMany(req);
|
||||
}
|
||||
}
|
||||
if (forEach) {
|
||||
@@ -129,7 +125,7 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
this.context = context;
|
||||
// set the persistence context as at this moment in
|
||||
// case it changes as part of a findIterate etc
|
||||
this.persistenceContext = context.getPersistenceContext();
|
||||
this.persistenceContext = context.persistenceContext();
|
||||
this.batchSize = batchSize;
|
||||
}
|
||||
|
||||
@@ -158,12 +154,12 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
abstract void clear();
|
||||
|
||||
@Override
|
||||
public BeanPropertyAssocMany<?> getBeanProperty() {
|
||||
public BeanPropertyAssocMany<?> beanProperty() {
|
||||
return context.property;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectGraphNode getObjectGraphNode() {
|
||||
public ObjectGraphNode objectGraphNode() {
|
||||
return context.objectGraphNode;
|
||||
}
|
||||
|
||||
@@ -178,17 +174,17 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
public BeanDescriptor<?> descriptor() {
|
||||
return context.desc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PersistenceContext getPersistenceContext() {
|
||||
public PersistenceContext persistenceContext() {
|
||||
return persistenceContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFullPath() {
|
||||
public String fullPath() {
|
||||
return context.fullPath;
|
||||
}
|
||||
|
||||
@@ -205,14 +201,14 @@ final class DLoadManyContext extends DLoadBaseContext implements LoadManyContext
|
||||
if (parentDesc.cacheManyPropLoad(context.property, bc, parentKey, context.parent.isReadOnly())) {
|
||||
// we loaded the bean collection from cache so remove it from the buffer
|
||||
if (removeFromBuffer(bc)) {
|
||||
bc.setLoader(context.parent.getEbeanServer());
|
||||
bc.setLoader(context.parent.server());
|
||||
}
|
||||
// find it using instance equality - avoiding equals() and potential deadlock issue
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
context.parent.getEbeanServer().loadMany(new LoadManyRequest(this, onlyIds, useCache, bc));
|
||||
context.parent.server().loadMany(new LoadManyRequest(this, onlyIds, useCache, bc));
|
||||
// clear the buffer as all entries have been loaded
|
||||
clear();
|
||||
} finally {
|
||||
|
||||
@@ -661,7 +661,7 @@ public final class CQuery<T> implements DbReadContext, CancelableQuery, SpiProfi
|
||||
|
||||
@Override
|
||||
public void profileBean(EntityBeanIntercept ebi, String prefix) {
|
||||
ObjectGraphNode node = request.loadContext().getObjectGraphNode(prefix);
|
||||
ObjectGraphNode node = request.loadContext().objectGraphNode(prefix);
|
||||
ebi.setNodeUsageCollector(new NodeUsageCollector(node, profilingListener));
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebeaninternal.api.BindParams;
|
||||
import io.ebeaninternal.api.CoreLog;
|
||||
import io.ebeaninternal.api.SpiExpressionList;
|
||||
import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
@@ -14,7 +15,6 @@ import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import io.ebeaninternal.server.querydefn.OrmUpdateProperties;
|
||||
import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
import io.ebeaninternal.server.bind.DataBind;
|
||||
import io.ebeaninternal.server.util.BindParamsParser;
|
||||
|
||||
import java.sql.Connection;
|
||||
@@ -47,26 +47,14 @@ public final class CQueryPredicates {
|
||||
private final Object idValue;
|
||||
private final BindParams bindParams;
|
||||
private DefaultExpressionRequest filterMany;
|
||||
/**
|
||||
* SQL generated from the where expressions.
|
||||
*/
|
||||
private String filterManyExprSql;
|
||||
/**
|
||||
* Bind values from the where expressions.
|
||||
*/
|
||||
private DefaultExpressionRequest where;
|
||||
/**
|
||||
* SQL generated from the where expressions.
|
||||
*/
|
||||
private String whereExprSql;
|
||||
/**
|
||||
* Bind values for having expression.
|
||||
*/
|
||||
private DefaultExpressionRequest having;
|
||||
/**
|
||||
* SQL generated from the having expression.
|
||||
*/
|
||||
private String havingExprSql;
|
||||
private String dbHaving;
|
||||
/**
|
||||
* logicalWhere with property names converted to db columns.
|
||||
@@ -190,70 +178,46 @@ public final class CQueryPredicates {
|
||||
buildUpdateClause(buildSql, deployParser);
|
||||
buildBindWhereRawSql(buildSql);
|
||||
|
||||
BeanPropertyAssocMany<?> manyProperty = request.determineMany();
|
||||
if (buildSql) {
|
||||
String logicalOrderBy = deriveOrderByWithMany(request.manyPropertyForOrderBy());
|
||||
if (logicalOrderBy != null) {
|
||||
dbOrderBy = deployParser.parse(logicalOrderBy);
|
||||
}
|
||||
// create a copy of the includes required to support the orderBy
|
||||
orderByIncludes = new HashSet<>(deployParser.includes());
|
||||
}
|
||||
SpiExpressionList<?> whereExp = query.getWhereExpressions();
|
||||
if (whereExp != null) {
|
||||
this.where = new DefaultExpressionRequest(request, deployParser, binder, whereExp);
|
||||
if (buildSql) {
|
||||
whereExprSql = where.buildSql();
|
||||
dbWhere = where.buildSql();
|
||||
}
|
||||
}
|
||||
BeanPropertyAssocMany<?> manyProperty = request.determineMany();
|
||||
if (manyProperty != null) {
|
||||
OrmQueryProperties chunk = query.getDetail().getChunk(manyProperty.name(), false);
|
||||
SpiExpressionList<?> filterManyExpr = chunk.getFilterMany();
|
||||
if (filterManyExpr != null) {
|
||||
this.filterMany = new DefaultExpressionRequest(request, deployParser, binder, filterManyExpr);
|
||||
if (buildSql) {
|
||||
filterManyExprSql = filterMany.buildSql();
|
||||
dbFilterMany = filterMany.buildSql();
|
||||
}
|
||||
}
|
||||
}
|
||||
// having expression
|
||||
SpiExpressionList<?> havingExpr = query.getHavingExpressions();
|
||||
if (havingExpr != null) {
|
||||
this.having = new DefaultExpressionRequest(request, deployParser, binder, havingExpr);
|
||||
if (buildSql) {
|
||||
havingExprSql = having.buildSql();
|
||||
dbHaving = having.buildSql();
|
||||
}
|
||||
}
|
||||
if (buildSql) {
|
||||
parsePropertiesToDbColumns(deployParser);
|
||||
predicateIncludes = deployParser.includes();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse/Convert property names to database columns in the where and order by
|
||||
* clauses etc.
|
||||
*/
|
||||
private void parsePropertiesToDbColumns(DeployParser deployParser) {
|
||||
// order by is dependent on the manyProperty (if there is one)
|
||||
String logicalOrderBy = deriveOrderByWithMany(request.manyPropertyForOrderBy());
|
||||
if (logicalOrderBy != null) {
|
||||
dbOrderBy = deployParser.parse(logicalOrderBy);
|
||||
}
|
||||
// create a copy of the includes required to support the orderBy
|
||||
orderByIncludes = new HashSet<>(deployParser.getIncludes());
|
||||
dbWhere = deriveWhere(deployParser);
|
||||
dbFilterMany = deriveFilterMany(deployParser);
|
||||
dbHaving = deriveHaving(deployParser);
|
||||
// all includes, including ones for manyWhere clause
|
||||
predicateIncludes = deployParser.getIncludes();
|
||||
}
|
||||
|
||||
private String deriveFilterMany(DeployParser deployParser) {
|
||||
if (isEmpty(filterManyExprSql)) {
|
||||
return null;
|
||||
} else {
|
||||
return deployParser.parse(filterManyExprSql);
|
||||
}
|
||||
}
|
||||
|
||||
private String deriveWhere(DeployParser deployParser) {
|
||||
return parse(whereExprSql, deployParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the table alias place holders.
|
||||
* Replace the table alias place-holders.
|
||||
*/
|
||||
void parseTableAlias(SqlTreeAlias alias) {
|
||||
if (dbWhere != null) {
|
||||
@@ -272,20 +236,6 @@ public final class CQueryPredicates {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
private String parse(String expr, DeployParser deployParser) {
|
||||
if (expr == null) return "";
|
||||
if (expr.isEmpty()) return expr;
|
||||
return deployParser.parse(expr);
|
||||
}
|
||||
|
||||
private String deriveHaving(DeployParser deployParser) {
|
||||
return parse(havingExprSql, deployParser);
|
||||
}
|
||||
|
||||
private String parseOrderBy() {
|
||||
OrderBy<?> orderBy = query.getOrderBy();
|
||||
if (orderBy == null) {
|
||||
@@ -353,7 +303,7 @@ public final class CQueryPredicates {
|
||||
* Return the bind values for the where expression.
|
||||
*/
|
||||
public List<Object> whereExprBindValues() {
|
||||
return where == null ? Collections.emptyList() : where.getBindValues();
|
||||
return where == null ? Collections.emptyList() : where.bindValues();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,11 +26,13 @@ public class DeployPropertyParserTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void depth1_path() {
|
||||
Assertions.assertThat(parser().property("billingAddress.city")).isEqualTo("${billingAddress}city");
|
||||
Assertions.assertThat(parser().parse("billingAddress.city")).isEqualTo("${billingAddress}city");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void depth2_path() {
|
||||
Assertions.assertThat(parser().property("max(billingAddress.country.name)")).isEqualTo("max(${billingAddress.country}name)");
|
||||
Assertions.assertThat(parser().parse("max(billingAddress.country.name)")).isEqualTo("max(${billingAddress.country}name)");
|
||||
}
|
||||
|
||||
@@ -69,6 +71,7 @@ public class DeployPropertyParserTest extends BaseTest {
|
||||
|
||||
@Test
|
||||
public void unknown_path() {
|
||||
Assertions.assertThat(parser().property(" foo ")).isEqualTo(" foo ");
|
||||
Assertions.assertThat(parser().parse(" foo ")).isEqualTo(" foo ");
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class BetweenExpressionTest extends BaseExpressionTest {
|
||||
BetweenExpression exp = new BetweenExpression("startDate", 1, 2);
|
||||
exp.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("startDate between ? and ?");
|
||||
assertThat(expReq.sql()).isEqualTo("startDate between ? and ?");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class BetweenPropertyExpressionTest extends BaseExpressionTest {
|
||||
public void sqlExpression() {
|
||||
TDSpiExpressionRequest request = new TDSpiExpressionRequest(null);
|
||||
exp("a", "b", 10).addSql(request);
|
||||
Assertions.assertThat(request.getSql()).isEqualTo(" ? between a and b");
|
||||
Assertions.assertThat(request.sql()).isEqualTo(" ? between a and b");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+2
-2
@@ -13,14 +13,14 @@ import static org.mockito.Mockito.verify;
|
||||
public class InQueryExpressionTest extends BaseExpressionTest {
|
||||
|
||||
private SubQueryExpression exp(String propertyName, boolean not, String sql, Object... bindValues) {
|
||||
var op = not ? SubQueryExpression.SQOp.NOTIN : SubQueryExpression.SQOp.IN;
|
||||
var op = not ? SubQueryOp.NOTIN : SubQueryOp.IN;
|
||||
return new SubQueryExpression(op, propertyName, sql, Arrays.asList(bindValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
void copy_subQuery_expectNewInstance() {
|
||||
SpiQuery<?> subQuery = mock(SpiQuery.class);
|
||||
var orig = new SubQueryExpression(SubQueryExpression.SQOp.IN, "name", subQuery);
|
||||
var orig = new SubQueryExpression(SubQueryOp.IN, "name", subQuery);
|
||||
SpiExpression copy = orig.copy();
|
||||
assertThat(copy).isNotSameAs(orig);
|
||||
verify(subQuery).copy();
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class InRangeExpressionTest extends BaseExpressionTest {
|
||||
InRangeExpression exp = new InRangeExpression("startDate", 1, 2);
|
||||
exp.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("(startDate >= ? and startDate < ?)");
|
||||
assertThat(expReq.sql()).isEqualTo("(startDate >= ? and startDate < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public class LogicExpressionTest extends BaseExpressionTest {
|
||||
LogicExpression and = and(eq("a", 10), eq("b", 10));
|
||||
and.addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("(a = ? and b = ?)");
|
||||
assertThat(expReq.sql()).isEqualTo("(a = ? and b = ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,7 +22,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("id", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is not null");
|
||||
assertThat(expReq.sql()).isEqualTo("id is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -32,7 +32,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("id", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("id is null");
|
||||
assertThat(expReq.sql()).isEqualTo("id is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -42,7 +42,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("customer", true).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is not null");
|
||||
assertThat(expReq.sql()).isEqualTo("customer.id is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -52,7 +52,7 @@ public class NullExpressionTest extends BaseExpressionTest {
|
||||
|
||||
nullExp("customer", false).addSql(expReq);
|
||||
|
||||
assertThat(expReq.getSql()).isEqualTo("customer.id is null");
|
||||
assertThat(expReq.sql()).isEqualTo("customer.id is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+19
-7
@@ -24,7 +24,7 @@ public class TDSpiExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DbExpressionHandler getDbPlatformHandler() {
|
||||
public DbExpressionHandler platformHandler() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -34,18 +34,30 @@ public class TDSpiExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BeanDescriptor<?> getBeanDescriptor() {
|
||||
public BeanDescriptor<?> descriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiOrmQueryRequest<?> getQueryRequest() {
|
||||
public SpiOrmQueryRequest<?> queryRequest() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionRequest append(String sqlExpression) {
|
||||
sql.append(sqlExpression);
|
||||
public SpiExpressionRequest append(String expression) {
|
||||
sql.append(expression);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionRequest property(String expression) {
|
||||
sql.append(expression);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpressionRequest parse(String expression) {
|
||||
sql.append(expression);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -60,12 +72,12 @@ public class TDSpiExpressionRequest implements SpiExpressionRequest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSql() {
|
||||
public String sql() {
|
||||
return sql.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<Object> getBindValues() {
|
||||
public ArrayList<Object> bindValues() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -15,7 +15,7 @@ public class HanaDbExpressionTest {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.arrayContains(request, "arrayproperty", true, "v1", "v2", "v3");
|
||||
assertEquals("(? member of arrayproperty) and (? member of arrayproperty) and (? member of arrayproperty)",
|
||||
request.getSql());
|
||||
request.sql());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -24,28 +24,28 @@ public class HanaDbExpressionTest {
|
||||
expression.arrayContains(request, "arrayproperty", false, "v1", "v2", "v3");
|
||||
assertEquals(
|
||||
"(? not member of arrayproperty) and (? not member of arrayproperty) and (? not member of arrayproperty)",
|
||||
request.getSql());
|
||||
request.sql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayContainsEmpty() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.arrayContains(request, "arrayproperty", true);
|
||||
assertEquals("", request.getSql());
|
||||
assertEquals("", request.sql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayIsEmpty() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.arrayIsEmpty(request, "arrayproperty", true);
|
||||
assertEquals("cardinality(arrayproperty) = 0", request.getSql());
|
||||
assertEquals("cardinality(arrayproperty) = 0", request.sql());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArrayIsNotEmpty() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.arrayIsEmpty(request, "arrayproperty", false);
|
||||
assertEquals("cardinality(arrayproperty) <> 0", request.getSql());
|
||||
assertEquals("cardinality(arrayproperty) <> 0", request.sql());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -64,6 +64,6 @@ public class HanaDbExpressionTest {
|
||||
public void testJson() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.json(request, "jsonproperty", "path", Op.EQ, "val");
|
||||
assertEquals("json_value(jsonproperty, '$.path') = ?", request.getSql());
|
||||
assertEquals("json_value(jsonproperty, '$.path') = ?", request.sql());
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -15,6 +15,6 @@ public class MySqlDbExpressionTest {
|
||||
public void testJson() {
|
||||
SpiExpressionRequest request = new DefaultExpressionRequest(null);
|
||||
expression.json(request, "jsonproperty", "path", Op.EQ, "val");
|
||||
assertEquals("(jsonproperty ->> '$.path') = ?", request.getSql());
|
||||
assertEquals("(jsonproperty ->> '$.path') = ?", request.sql());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -413,4 +413,48 @@ public abstract class PBaseComparable<R, T> extends PBaseValueEqual<R, T> {
|
||||
expr().gt(_name, subQuery);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R leSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().leSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Less Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R ltSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().ltSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than or Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R geSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().geSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Greater Than a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R gtSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().gtSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,6 +301,50 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R, T> {
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R inSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().inSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not IN a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R notInSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().notInSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R eqSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().eqSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not Equal To a raw SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R neSubQuery(String sqlSubQuery, Object... bindValues) {
|
||||
expr().neSubQuery(_name, sqlSubQuery, bindValues);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Property is equal to the result of a sub-query.
|
||||
*
|
||||
|
||||
@@ -733,6 +733,28 @@ public abstract class TQRootBean<T, R> {
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* EXISTS using a SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R exists(String sqlSubQuery, Object... bindValues) {
|
||||
query().where().exists(sqlSubQuery, bindValues);
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not EXISTS using a SQL SubQuery.
|
||||
*
|
||||
* @param sqlSubQuery The SQL SubQuery
|
||||
* @param bindValues Optional bind values if the SubQuery uses {@code ? } bind values.
|
||||
*/
|
||||
public final R notExists(String sqlSubQuery, Object... bindValues) {
|
||||
query().where().notExists(sqlSubQuery, bindValues);
|
||||
return root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute using "for update" clause which results in the DB locking the record.
|
||||
*/
|
||||
|
||||
@@ -268,6 +268,84 @@ public class QOrderTest {
|
||||
assertThat(sql).isEqualTo("select t0.id, t0.status from o_order t0 join be_customer t1 on t1.id = t0.customer_id where (coalesce(t1.version,0) > ? or t0.id < ?)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void geSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.geSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered >= (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void gtSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.gtSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered > (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void leSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.leSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <= (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void ltSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.ltSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered < (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void eqSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.eqSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered = (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void neSqlSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
|
||||
var query = new QCustomer()
|
||||
.select(c.id)
|
||||
.registered.neSubQuery("select max(o.order_date) as foo from o_order o")
|
||||
.query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).contains("select t0.id from be_customer t0 where t0.registered <> (select max(o.order_date) as foo from o_order o)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void geSubQuery() {
|
||||
var c = QCustomer.alias();
|
||||
@@ -394,6 +472,30 @@ public class QOrderTest {
|
||||
assertThat(sql).contains(" exists (select 1 from o_order_detail od where od.order_qty > ? and od.id = t1.id)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void sqlSubQueryExists() {
|
||||
Query<Order> query = new QOrder()
|
||||
.exists("select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id", 10)
|
||||
.orderBy("orderDate").query();
|
||||
|
||||
query.findList();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
assertThat(sql).contains(" exists (select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id) order by t0.order_date");
|
||||
}
|
||||
|
||||
@Test
|
||||
void sqlSubQueryNotExists() {
|
||||
Query<Order> query = new QOrder()
|
||||
.notExists("select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id", 10)
|
||||
.orderBy("orderDate").query();
|
||||
|
||||
query.findList();
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
assertThat(sql).contains(" not exists (select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id) order by t0.order_date");
|
||||
}
|
||||
|
||||
@Test
|
||||
void subQueryNotExists() {
|
||||
Query<OrderDetail> subQuery = new QOrderDetail()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package org.tests.query;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.Expr;
|
||||
import io.ebean.Query;
|
||||
import io.ebean.xtest.ForPlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.ForPlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
@@ -187,4 +187,93 @@ public class TestWhereRawClause extends BaseTestCase {
|
||||
.findList();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSqlSubQueryExists() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSql.start();
|
||||
DB.find(Order.class)
|
||||
.select("id")
|
||||
.where()
|
||||
.exists("select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id", 10)
|
||||
.findList();
|
||||
|
||||
DB.find(Order.class)
|
||||
.select("id")
|
||||
.where()
|
||||
.notExists("select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id", 10)
|
||||
.findList();
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id from o_order t0 where exists (select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id)");
|
||||
assertThat(sql.get(1)).contains("select t0.id from o_order t0 where not exists (select 1 from o_order_detail od where od.order_qty > ? and od.order_id = t0.id)");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSqlSubQueryExpressions() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
LoggedSql.start();
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.inSubQuery("id", "select c.id as id from o_customer c")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.notInSubQuery("id", "select c.id as id from o_customer c")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.eqSubQuery("id", "select c.id as id from o_customer c where c.name = ?", "Rob")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.neSubQuery("id", "select c.id as id from o_customer c where c.name = ?", "Rob")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.gtSubQuery("id", "select c.id as id from o_customer c where c.name = ?", "Rob")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.geSubQuery("id", "select c.id as id from o_customer c where c.name = ?", "Rob")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.ltSubQuery("id", "select c.id as id from o_customer c where c.name = ?", "Rob")
|
||||
.findList();
|
||||
|
||||
DB.find(Customer.class)
|
||||
.select("name")
|
||||
.where()
|
||||
.leSubQuery("id", "select c.id as id from o_customer c where c.name = ? and 1 = ?", "Rob", 1)
|
||||
.like("name", "R%")
|
||||
.findList();
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(8);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.name from o_customer t0 where t0.id in (select c.id as id from o_customer c)");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.name from o_customer t0 where t0.id not in (select c.id as id from o_customer c)");
|
||||
assertThat(sql.get(2)).contains("select t0.id, t0.name from o_customer t0 where t0.id = (select c.id as id from o_customer c where c.name = ?)");
|
||||
assertThat(sql.get(3)).contains("select t0.id, t0.name from o_customer t0 where t0.id <> (select c.id as id from o_customer c where c.name = ?)");
|
||||
assertThat(sql.get(4)).contains("select t0.id, t0.name from o_customer t0 where t0.id > (select c.id as id from o_customer c where c.name = ?)");
|
||||
assertThat(sql.get(5)).contains("select t0.id, t0.name from o_customer t0 where t0.id >= (select c.id as id from o_customer c where c.name = ?)");
|
||||
assertThat(sql.get(6)).contains("select t0.id, t0.name from o_customer t0 where t0.id < (select c.id as id from o_customer c where c.name = ?)");
|
||||
assertThat(sql.get(7)).contains("select t0.id, t0.name from o_customer t0 where t0.id <= (select c.id as id from o_customer c where c.name = ? and 1 = ?)");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user