mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Compare commits
35
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3490e90f03 | ||
|
|
d89817a5c5 | ||
|
|
db1ba5f20e | ||
|
|
4f9a9a5094 | ||
|
|
1c6ac1289d | ||
|
|
b96be84106 | ||
|
|
3c40293183 | ||
|
|
a9a6031986 | ||
|
|
b82085da42 | ||
|
|
9a17a7752c | ||
|
|
92474c2b24 | ||
|
|
9a00b9df0e | ||
|
|
697f67c14a | ||
|
|
2c34bc1636 | ||
|
|
1f9ccf1c8b | ||
|
|
a1f10b8704 | ||
|
|
3c21950b91 | ||
|
|
3b45308ac7 | ||
|
|
00e69e1b5d | ||
|
|
11b3f7a813 | ||
|
|
2185c8a886 | ||
|
|
f8bda05b37 | ||
|
|
0a3b819991 | ||
|
|
5c8b1eb3bb | ||
|
|
824f6dcc7e | ||
|
|
06e23b85ad | ||
|
|
09219c759b | ||
|
|
b861038568 | ||
|
|
bfd8445bcd | ||
|
|
c30e3bf78c | ||
|
|
c793d6652f | ||
|
|
d12e55c20b | ||
|
|
3477f590dd | ||
|
|
6bbf93aba8 | ||
|
|
42d02cc521 |
@@ -9,7 +9,7 @@
|
||||
|
||||
<groupId>org.avaje.ebeanorm</groupId>
|
||||
<artifactId>avaje-ebeanorm</artifactId>
|
||||
<version>7.14.1</version>
|
||||
<version>7.16.3</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>avaje-ebeanorm</name>
|
||||
@@ -37,7 +37,7 @@
|
||||
|
||||
<scm>
|
||||
<developerConnection>scm:git:https://github.com/ebean-orm/avaje-ebeanorm.git</developerConnection>
|
||||
<tag>avaje-ebeanorm-7.14.1</tag>
|
||||
<tag>avaje-ebeanorm-7.16.3</tag>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -49,7 +49,7 @@ final class DRawSqlColumnsParser {
|
||||
if (split.length > 1) {
|
||||
ArrayList<String> tmp = new ArrayList<String>(split.length);
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
if (split[i].trim().length() > 0) {
|
||||
if (!split[i].trim().isEmpty()) {
|
||||
tmp.add(split[i].trim());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public final class Ebean {
|
||||
// look to see if there is a default server defined
|
||||
String defaultName = PrimaryServer.getDefaultServerName();
|
||||
logger.debug("defaultName:" + defaultName);
|
||||
if (defaultName != null && defaultName.trim().length() > 0) {
|
||||
if (defaultName != null && !defaultName.trim().isEmpty()) {
|
||||
defaultServer = getWithCreate(defaultName.trim());
|
||||
}
|
||||
}
|
||||
@@ -182,7 +182,7 @@ public final class Ebean {
|
||||
}
|
||||
|
||||
private EbeanServer get(String name) {
|
||||
if (name == null || name.length() == 0) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
return defaultServer;
|
||||
}
|
||||
// non-synchronized read
|
||||
|
||||
@@ -400,6 +400,6 @@ public final class OrderBy<T> implements Serializable {
|
||||
}
|
||||
|
||||
private boolean isEmptyString(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,6 @@ class PrimaryServer {
|
||||
* Return true if the string is null or empty.
|
||||
*/
|
||||
private static boolean isEmpty(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ package com.avaje.ebean;
|
||||
*
|
||||
* int modifiedCount = Ebean.execute(update);
|
||||
*
|
||||
* String msg = "There where " + modifiedCount + "rows updated"
|
||||
* String msg = "There were " + modifiedCount + " rows updated"
|
||||
* </pre>
|
||||
*
|
||||
* @see Update
|
||||
@@ -143,4 +143,4 @@ public interface SqlUpdate {
|
||||
*/
|
||||
SqlUpdate setNullParameter(String name, int jdbcType);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import java.util.ArrayList;
|
||||
* This object is used internally with the enhancement of a method with
|
||||
* Transactional annotation.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @see TxCallable
|
||||
* @see TxRunnable
|
||||
* @see Ebean#execute(TxScope, TxCallable)
|
||||
@@ -44,27 +44,6 @@ public final class TxScope {
|
||||
|
||||
ArrayList<Class<? extends Throwable>> noRollbackFor;
|
||||
|
||||
/**
|
||||
* Return true if PersistBatch has been set.
|
||||
*/
|
||||
public boolean isBatchSet() {
|
||||
return batch != null && batch != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch on cascade has been set.
|
||||
*/
|
||||
public boolean isBatchOnCascadeSet() {
|
||||
return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch size has been set.
|
||||
*/
|
||||
public boolean isBatchSizeSet() {
|
||||
return batchSize > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to create a TxScope with REQUIRES.
|
||||
*/
|
||||
@@ -130,6 +109,44 @@ public final class TxScope {
|
||||
+ "] rollbackFor[" + rollbackFor + "] noRollbackFor[" + noRollbackFor + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if PersistBatch has been set.
|
||||
*/
|
||||
public boolean isBatchSet() {
|
||||
return batch != null && batch != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch on cascade has been set.
|
||||
*/
|
||||
public boolean isBatchOnCascadeSet() {
|
||||
return batchOnCascade != null && batchOnCascade != PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if batch size has been set.
|
||||
*/
|
||||
public boolean isBatchSizeSet() {
|
||||
return batchSize > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for batchSize being set without batch mode and use this to imply PersistBatch.ALL.
|
||||
*/
|
||||
public void checkBatchMode() {
|
||||
if (batchSize > 0 && notSet(batch) && notSet(batchOnCascade)) {
|
||||
// Use setting the batchSize as implying PersistBatch.ALL for @Transactional
|
||||
batch = PersistBatch.ALL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the mode is considered not set.
|
||||
*/
|
||||
private boolean notSet(PersistBatch batchMode) {
|
||||
return batchMode == null || batchMode == PersistBatch.INHERIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the transaction type.
|
||||
*/
|
||||
|
||||
@@ -274,7 +274,7 @@ public abstract class AbstractNamingConvention implements NamingConvention {
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
protected boolean isEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -163,6 +163,17 @@ public class ServerConfig {
|
||||
*/
|
||||
private int databaseSequenceBatchSize = 20;
|
||||
|
||||
/**
|
||||
* JDBC fetchSize hint when using findList. Defaults to 0 leaving it up to the JDBC driver.
|
||||
*/
|
||||
private int jdbcFetchSizeFindList;
|
||||
|
||||
/**
|
||||
* JDBC fetchSize hint when using findEach/findEachWhile. Defaults to 100. Note that this does
|
||||
* not apply to MySql as that gets special treatment (forward only etc).
|
||||
*/
|
||||
private int jdbcFetchSizeFindEach = 100;
|
||||
|
||||
/**
|
||||
* Suffix appended to the base table to derive the view that contains the union
|
||||
* of the base table and the history table in order to support asOf queries.
|
||||
@@ -719,6 +730,34 @@ public class ServerConfig {
|
||||
this.databaseSequenceBatchSize = databaseSequenceBatchSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default JDBC fetchSize hint for findList queries.
|
||||
*/
|
||||
public int getJdbcFetchSizeFindList() {
|
||||
return jdbcFetchSizeFindList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default JDBC fetchSize hint for findList queries.
|
||||
*/
|
||||
public void setJdbcFetchSizeFindList(int jdbcFetchSizeFindList) {
|
||||
this.jdbcFetchSizeFindList = jdbcFetchSizeFindList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default JDBC fetchSize hint for findEach/findEachWhile queries.
|
||||
*/
|
||||
public int getJdbcFetchSizeFindEach() {
|
||||
return jdbcFetchSizeFindEach;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default JDBC fetchSize hint for findEach/findEachWhile queries.
|
||||
*/
|
||||
public void setJdbcFetchSizeFindEach(int jdbcFetchSizeFindEach) {
|
||||
this.jdbcFetchSizeFindEach = jdbcFetchSizeFindEach;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the ChangeLogPrepare.
|
||||
* <p>
|
||||
@@ -2405,6 +2444,8 @@ public class ServerConfig {
|
||||
asOfSysPeriod = p.get("asOfSysPeriod", asOfSysPeriod);
|
||||
historyTableSuffix = p.get("historyTableSuffix", historyTableSuffix);
|
||||
dataSourceJndiName = p.get("dataSourceJndiName", dataSourceJndiName);
|
||||
jdbcFetchSizeFindEach = p.getInt("jdbcFetchSizeFindEach", jdbcFetchSizeFindEach);
|
||||
jdbcFetchSizeFindList = p.getInt("jdbcFetchSizeFindList", jdbcFetchSizeFindList);
|
||||
databaseSequenceBatchSize = p.getInt("databaseSequenceBatchSize", databaseSequenceBatchSize);
|
||||
databaseBooleanTrue = p.get("databaseBooleanTrue", databaseBooleanTrue);
|
||||
databaseBooleanFalse = p.get("databaseBooleanFalse", databaseBooleanFalse);
|
||||
@@ -2460,7 +2501,7 @@ public class ServerConfig {
|
||||
String[] split = classNames.split("[ ,;]");
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
String cn = split[i].trim();
|
||||
if (cn.length() > 0 && !"class".equalsIgnoreCase(cn)) {
|
||||
if (!cn.isEmpty() && !"class".equalsIgnoreCase(cn)) {
|
||||
try {
|
||||
classes.add(Class.forName(cn));
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
||||
@@ -146,6 +146,6 @@ public final class TableName {
|
||||
* @return true, if is valid
|
||||
*/
|
||||
public boolean isValid() {
|
||||
return name != null && name.length() > 0;
|
||||
return name != null && !name.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -492,7 +492,7 @@ public class DatabasePlatform {
|
||||
*/
|
||||
public String convertQuotedIdentifiers(String dbName) {
|
||||
// Ignore null values e.g. schema name or catalog
|
||||
if (dbName != null && dbName.length() > 0) {
|
||||
if (dbName != null && !dbName.isEmpty()) {
|
||||
if (dbName.charAt(0) == BACK_TICK) {
|
||||
if (dbName.charAt(dbName.length() - 1) == BACK_TICK) {
|
||||
|
||||
|
||||
@@ -6,11 +6,13 @@ package com.avaje.ebean.config.dbplatform;
|
||||
public interface DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return true if the 'As of' predicate is part of the from clause
|
||||
* (more standard sql2011). So true for Oracle total recall and false
|
||||
* for Postgres and MySql (where we use views and history tables).
|
||||
* Return true if the implementation is SQL2011 standards based.
|
||||
* <p>
|
||||
* Non standards based means we need to add additional predicates into the
|
||||
* JOIN ON clause and add an additional predicate for the base table.
|
||||
* </p>
|
||||
*/
|
||||
boolean isBindWithFromClause();
|
||||
boolean isStandardsBased();
|
||||
|
||||
/**
|
||||
* Return the number of columns bound in a 'As Of' predicate.
|
||||
|
||||
@@ -5,11 +5,8 @@ package com.avaje.ebean.config.dbplatform;
|
||||
*/
|
||||
public abstract class DbStandardHistorySupport implements DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return true as with sql2011 the 'as of timestamp' clause included in from or join clause.
|
||||
*/
|
||||
@Override
|
||||
public boolean isBindWithFromClause() {
|
||||
public boolean isStandardsBased() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,11 +9,8 @@ package com.avaje.ebean.config.dbplatform;
|
||||
*/
|
||||
public abstract class DbViewHistorySupport implements DbHistorySupport {
|
||||
|
||||
/**
|
||||
* Return false for view based implementations where we append extra 'as of' predicates to the end.
|
||||
*/
|
||||
@Override
|
||||
public boolean isBindWithFromClause() {
|
||||
public boolean isStandardsBased() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,7 +104,7 @@ public class MTable {
|
||||
/**
|
||||
* Compound unique constraints.
|
||||
*/
|
||||
private List<MCompoundUniqueConstraint> compoundUniqueConstraints = new ArrayList<MCompoundUniqueConstraint>();
|
||||
private List<MCompoundUniqueConstraint> uniqueConstraints = new ArrayList<MCompoundUniqueConstraint>();
|
||||
|
||||
/**
|
||||
* Compound foreign keys.
|
||||
@@ -216,7 +216,7 @@ public class MTable {
|
||||
createTable.getForeignKey().add(compoundKey.createForeignKey());
|
||||
}
|
||||
|
||||
for (MCompoundUniqueConstraint constraint : compoundUniqueConstraints) {
|
||||
for (MCompoundUniqueConstraint constraint : uniqueConstraints) {
|
||||
UniqueConstraint uq = new UniqueConstraint();
|
||||
uq.setName(constraint.getName());
|
||||
String[] columns = constraint.getColumns();
|
||||
@@ -404,8 +404,8 @@ public class MTable {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public List<MCompoundUniqueConstraint> getCompoundUniqueConstraints() {
|
||||
return compoundUniqueConstraints;
|
||||
public List<MCompoundUniqueConstraint> getUniqueConstraints() {
|
||||
return uniqueConstraints;
|
||||
}
|
||||
|
||||
public List<MCompoundForeignKey> getCompoundKeys() {
|
||||
@@ -476,21 +476,21 @@ public class MTable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
* Add a unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(String[] columns, boolean oneToOne, String constraintName) {
|
||||
compoundUniqueConstraints.add(new MCompoundUniqueConstraint(columns, oneToOne, constraintName));
|
||||
public void addUniqueConstraint(String[] columns, boolean oneToOne, String constraintName) {
|
||||
uniqueConstraints.add(new MCompoundUniqueConstraint(columns, oneToOne, constraintName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
* Add a unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(List<MColumn> columns, boolean oneToOne, String constraintName) {
|
||||
public void addUniqueConstraint(List<MColumn> columns, boolean oneToOne, String constraintName) {
|
||||
String[] cols = new String[columns.size()];
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
cols[i] = columns.get(i).getName();
|
||||
}
|
||||
addCompoundUniqueConstraint(cols, oneToOne, constraintName);
|
||||
addUniqueConstraint(cols, oneToOne, constraintName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -85,6 +85,11 @@ public class ModelBuildIntersectionTable {
|
||||
|
||||
String tableName = intersectionTableJoin.getTable();
|
||||
MTable table = new MTable(tableName);
|
||||
if (!manyProp.isExcludedFromHistory()) {
|
||||
if (localDesc.isHistorySupport()) {
|
||||
table.setWithHistory(true);
|
||||
}
|
||||
}
|
||||
table.setPkName(ctx.primaryKeyName(tableName));
|
||||
|
||||
TableJoinColumn[] columns = intersectionTableJoin.columns();
|
||||
|
||||
+12
-21
@@ -10,7 +10,7 @@ import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyCompound;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.TableJoinColumn;
|
||||
import com.avaje.ebeaninternal.server.deploy.id.ImportedId;
|
||||
@@ -45,30 +45,30 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
this.ctx = ctx;
|
||||
this.table = table;
|
||||
this.beanDescriptor = beanDescriptor;
|
||||
addCompoundUniqueConstraint(beanDescriptor.getCompoundUniqueConstraints());
|
||||
addIndexes(beanDescriptor.getIndexDefinitions());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add unique constraints defined via JPA UniqueConstraint annotations.
|
||||
*/
|
||||
private void addCompoundUniqueConstraint(CompoundUniqueConstraint[] constraints) {
|
||||
private void addIndexes(IndexDefinition[] indexes) {
|
||||
|
||||
if (constraints != null) {
|
||||
for (int i = 0; i < constraints.length; i++) {
|
||||
CompoundUniqueConstraint constraint = constraints[i];
|
||||
String[] columns = constraint.getColumns();
|
||||
if (indexes != null) {
|
||||
for (int i = 0; i < indexes.length; i++) {
|
||||
IndexDefinition index = indexes[i];
|
||||
String[] columns = index.getColumns();
|
||||
indexSet.add(columns);
|
||||
|
||||
if (constraint.isUnique()) {
|
||||
String uqName = constraint.getName();
|
||||
if (index.isUnique()) {
|
||||
String uqName = index.getName();
|
||||
if (uqName == null || uqName.trim().isEmpty()) {
|
||||
uqName = determineUniqueConstraintName(columns);
|
||||
}
|
||||
table.addCompoundUniqueConstraint(columns, false, uqName);
|
||||
table.addUniqueConstraint(columns, false, uqName);
|
||||
|
||||
} else {
|
||||
// 'just' an index (not a unique constraint)
|
||||
String idxName = constraint.getName();
|
||||
String idxName = index.getName();
|
||||
if (idxName == null || idxName.trim().isEmpty()) {
|
||||
idxName = determineIndexName(columns);
|
||||
}
|
||||
@@ -216,7 +216,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
|
||||
} else {
|
||||
String uqName = determineUniqueConstraintName(p.getName());
|
||||
table.addCompoundUniqueConstraint(modelColumns, true, uqName);
|
||||
table.addUniqueConstraint(modelColumns, true, uqName);
|
||||
indexSetAdd(modelColumns);
|
||||
}
|
||||
}
|
||||
@@ -260,15 +260,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor {
|
||||
col.setCheckConstraintName(determineCheckConstraintName(col.getName()));
|
||||
}
|
||||
|
||||
String indexName = p.getIndexName();
|
||||
if (indexName != null) {
|
||||
// single column non-unique index
|
||||
if (indexName.trim().isEmpty()) {
|
||||
indexName = determineIndexName(col.getName());
|
||||
}
|
||||
ctx.addIndex(indexName, table.getName(), p.getDbColumn());
|
||||
}
|
||||
|
||||
lastColumn = col;
|
||||
table.addColumn(col);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ public class PathProperties implements FetchPath {
|
||||
String path = entry.getKey();
|
||||
String props = entry.getValue().getPropertiesAsString();
|
||||
|
||||
if (path == null || path.length() == 0) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
query.select(props);
|
||||
} else {
|
||||
query.fetch(path, props);
|
||||
|
||||
@@ -108,7 +108,7 @@ class PathPropertiesParser {
|
||||
|
||||
private void addCurrentProperty() {
|
||||
String w = currentWord();
|
||||
if (w.length() > 0) {
|
||||
if (!w.isEmpty()) {
|
||||
currentPathProps.addProperty(w);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ public final class TimeStringParser implements StringParser {
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public Object parse(String value) {
|
||||
if (value == null || value.trim().length() == 0) {
|
||||
if (value == null || value.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ public class StringHelper {
|
||||
String listDelimiter, String nameValueSeparator) {
|
||||
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.length() == 0)) {
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
@@ -155,7 +155,7 @@ public class StringHelper {
|
||||
* Return true if the value is null or an empty string.
|
||||
*/
|
||||
public static boolean isNull(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +189,7 @@ public class StringHelper {
|
||||
// there is a key without a value?
|
||||
String key = allNameValuePairs.substring(pos, delimPos);
|
||||
key = key.trim();
|
||||
if (key.length() > 0) {
|
||||
if (!key.isEmpty()) {
|
||||
map.put(key, null);
|
||||
}
|
||||
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
|
||||
@@ -251,7 +251,7 @@ public class StringHelper {
|
||||
if (endPos == -1) {
|
||||
if (startPos <= str.length()) {
|
||||
String lastValue = str.substring(startPos, str.length());
|
||||
if (keepEmpties || lastValue.length() != 0) {
|
||||
if (keepEmpties || !lastValue.isEmpty()) {
|
||||
list.add(lastValue);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +260,7 @@ public class StringHelper {
|
||||
} else {
|
||||
// get the delimited value... add it..
|
||||
String value = str.substring(startPos, endPos);
|
||||
if (keepEmpties || value.length() != 0) {
|
||||
if (keepEmpties || !value.isEmpty()) {
|
||||
list.add(value);
|
||||
}
|
||||
// recursively search as we are not at the end yet...
|
||||
|
||||
@@ -18,8 +18,13 @@ public interface SpiExpression extends Expression {
|
||||
*/
|
||||
void writeDocQuery(DocQueryContext context) throws IOException;
|
||||
|
||||
/**
|
||||
* Process "Many" properties populating ManyWhereJoins.
|
||||
/**
|
||||
* Return the nested path for this expression.
|
||||
*/
|
||||
String nestedPath(BeanDescriptor<?> desc);
|
||||
|
||||
/**
|
||||
* Process "Many" properties populating ManyWhereJoins.
|
||||
* <p>
|
||||
* Predicates on Many properties require an extra independent join clause.
|
||||
* </p>
|
||||
@@ -89,4 +94,8 @@ public interface SpiExpression extends Expression {
|
||||
*/
|
||||
SpiExpression copyForPlanKey();
|
||||
|
||||
/**
|
||||
* Return the bind Id value if this is a "equal to" expression for the id property.
|
||||
*/
|
||||
Object getIdEqualTo(String idName);
|
||||
}
|
||||
|
||||
@@ -133,6 +133,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a single "equal to" expression for the Id.
|
||||
*/
|
||||
void checkIdEqualTo();
|
||||
|
||||
/**
|
||||
* Return true if AutoTune should be attempted on this query.
|
||||
*/
|
||||
@@ -218,14 +223,14 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
Timestamp getAsOf();
|
||||
|
||||
/**
|
||||
* Add a table alias for a @History entity involved in a 'As Of' query.
|
||||
* Increment the counter of tables used in 'As Of' query.
|
||||
*/
|
||||
void addAsOfTableAlias(String tableAlias);
|
||||
void incrementAsOfTableCount();
|
||||
|
||||
/**
|
||||
* Return the list of table alias involved in a 'As Of' query that have @History support.
|
||||
* Return the table alias used for the base table.
|
||||
*/
|
||||
List<String> getAsOfTableAlias();
|
||||
int getAsOfTableCount();
|
||||
|
||||
void addSoftDeletePredicate(String softDeletePredicate);
|
||||
|
||||
@@ -301,6 +306,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
NaturalKeyBindParam getNaturalKeyBindParam();
|
||||
|
||||
/**
|
||||
* Prepare the query for docstore execution with nested paths.
|
||||
*/
|
||||
void prepareDocNested();
|
||||
|
||||
/**
|
||||
* Set the query to be a delete query.
|
||||
*/
|
||||
@@ -615,6 +625,11 @@ public interface SpiQuery<T> extends Query<T> {
|
||||
*/
|
||||
void setGeneratedSql(String generatedSql);
|
||||
|
||||
/**
|
||||
* Set the JDBC fetchSize buffer hint if not explicitly set.
|
||||
*/
|
||||
void setDefaultFetchBuffer(int fetchSize);
|
||||
|
||||
/**
|
||||
* Return the hint for Statement.setFetchSize().
|
||||
*/
|
||||
|
||||
@@ -40,7 +40,7 @@ public class ExtraDdlXmlReader {
|
||||
* @param platforms The platforms (comma delimited) this script should run for
|
||||
*/
|
||||
public static boolean matchPlatform(String platformName, String platforms) {
|
||||
if (platforms == null || platforms.trim().length() == 0) {
|
||||
if (platforms == null || platforms.trim().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
String[] names = platforms.split("[,;]");
|
||||
|
||||
@@ -683,6 +683,9 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
if (txScope == null) {
|
||||
// create a TxScope with default settings
|
||||
txScope = new TxScope();
|
||||
} else {
|
||||
// check for implied batch mode via setting batchSize
|
||||
txScope.checkBatchMode();
|
||||
}
|
||||
|
||||
SpiTransaction suspended = null;
|
||||
@@ -1043,21 +1046,20 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
public <T> T findUnique(Query<T> query, Transaction transaction) {
|
||||
|
||||
Object id = query.getId();
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
spiQuery.checkIdEqualTo();
|
||||
Object id = spiQuery.getId();
|
||||
if (id != null) {
|
||||
// actually a find by Id query
|
||||
return findId(query, transaction);
|
||||
}
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) query;
|
||||
BeanDescriptor<T> desc = spiQuery.getBeanDescriptor();
|
||||
|
||||
SpiTransaction t = (SpiTransaction) transaction;
|
||||
if (t == null) {
|
||||
t = getCurrentServerTransaction();
|
||||
}
|
||||
if (t == null || !t.isSkipCache()) {
|
||||
id = desc.cacheNaturalKeyIdLookup(spiQuery);
|
||||
id = spiQuery.getBeanDescriptor().cacheNaturalKeyIdLookup(spiQuery);
|
||||
if (id != null) {
|
||||
T bean = findIdCheckPersistenceContextAndCache(t, spiQuery, id);
|
||||
if (bean != null) {
|
||||
|
||||
@@ -137,7 +137,7 @@ public class InternalConfiguration {
|
||||
|
||||
this.dataTimeZone = initDataTimeZone();
|
||||
this.binder = getBinder(typeManager, databasePlatform, dataTimeZone);
|
||||
this.cQueryEngine = new CQueryEngine(databasePlatform, binder, asOfTableMapping, serverConfig.getAsOfSysPeriod(), draftTableMap);
|
||||
this.cQueryEngine = new CQueryEngine(serverConfig, databasePlatform, binder, asOfTableMapping, draftTableMap);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,7 +235,7 @@ public class InternalConfiguration {
|
||||
if (historySupport == null) {
|
||||
return new Binder(typeManager, 0, false, jsonHandler, dataTimeZone);
|
||||
}
|
||||
return new Binder(typeManager, historySupport.getBindCount(), historySupport.isBindWithFromClause(), jsonHandler, dataTimeZone);
|
||||
return new Binder(typeManager, historySupport.getBindCount(), historySupport.isStandardsBased(), jsonHandler, dataTimeZone);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -513,4 +513,18 @@ public final class OrmQueryRequest<T> extends BeanRequest implements BeanQueryRe
|
||||
public boolean isAuditReads() {
|
||||
return !query.isDisableReadAudit() && beanDescriptor.isReadAuditing();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base table alias for this query.
|
||||
*/
|
||||
public String getBaseTableAlias() {
|
||||
return query.getAlias() == null ? beanDescriptor.getBaseTableAlias() : query.getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC buffer fetchSize hint if not set explicitly.
|
||||
*/
|
||||
public void setDefaultFetchBuffer(int fetchSize) {
|
||||
query.setDefaultFetchBuffer(fetchSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public final class RelationalQueryRequest {
|
||||
int maxRows = query.getMaxRows();
|
||||
if (firstRow > 0 || maxRows > 0) {
|
||||
return ebeanServer.getDatabasePlatform().getBasicSqlLimiter()
|
||||
.limit(query.getQuery(), firstRow, maxRows);
|
||||
.limit(sql, firstRow, maxRows);
|
||||
}
|
||||
return sql;
|
||||
}
|
||||
|
||||
@@ -176,7 +176,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
*/
|
||||
private final ConcurrencyMode concurrencyMode;
|
||||
|
||||
private final CompoundUniqueConstraint[] compoundUniqueConstraints;
|
||||
private final IndexDefinition[] indexDefinitions;
|
||||
|
||||
private final String[] dependentTables;
|
||||
|
||||
@@ -431,7 +431,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
this.selectLastInsertedId = deploy.getSelectLastInsertedId();
|
||||
this.concurrencyMode = deploy.getConcurrencyMode();
|
||||
this.updateChangesOnly = deploy.isUpdateChangesOnly();
|
||||
this.compoundUniqueConstraints = deploy.getCompoundUniqueConstraints();
|
||||
this.indexDefinitions = deploy.getIndexDefinitions();
|
||||
|
||||
this.readAuditing = deploy.isReadAuditing();
|
||||
this.draftable = deploy.isDraftable();
|
||||
@@ -1768,6 +1768,13 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
pc.deleted(rootBeanType, idValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Id property name or null if no Id property exists.
|
||||
*/
|
||||
public String getIdName() {
|
||||
return (idProperty == null) ? null : idProperty.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return the unique property. If only one property makes up
|
||||
* the unique id then it's value is returned. If there is a concatenated
|
||||
@@ -2168,8 +2175,8 @@ public class BeanDescriptor<T> implements MetaBeanInfo, BeanType<T> {
|
||||
/**
|
||||
* Return the compound unique constraints.
|
||||
*/
|
||||
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
|
||||
return compoundUniqueConstraints;
|
||||
public IndexDefinition[] getIndexDefinitions() {
|
||||
return indexDefinitions;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1141,7 +1141,7 @@ public class BeanDescriptorManager implements BeanDescriptorMap {
|
||||
// already assigned (So custom or UUID)
|
||||
return;
|
||||
}
|
||||
if (desc.propertiesId().size() == 0) {
|
||||
if (desc.propertiesId().isEmpty()) {
|
||||
// bean doesn't have an Id property
|
||||
if (desc.isBaseTableType() && desc.getBeanFinder() == null) {
|
||||
// expecting an id property
|
||||
|
||||
@@ -255,10 +255,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
|
||||
final String softDeleteDbPredicate;
|
||||
|
||||
final boolean indexed;
|
||||
|
||||
final String indexName;
|
||||
|
||||
public BeanProperty(DeployBeanProperty deploy) {
|
||||
this(null, deploy);
|
||||
}
|
||||
@@ -268,8 +264,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
this.descriptor = descriptor;
|
||||
this.name = InternString.intern(deploy.getName());
|
||||
this.propertyIndex = deploy.getPropertyIndex();
|
||||
this.indexed = deploy.isIndexed();
|
||||
this.indexName = deploy.getIndexName();
|
||||
this.unidirectionalShadow = deploy.isUndirectionalShadow();
|
||||
this.discriminator = deploy.isDiscriminator();
|
||||
this.localEncrypted = deploy.isLocalEncrypted();
|
||||
@@ -370,9 +364,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
this.descriptor = source.descriptor;
|
||||
this.name = InternString.intern(source.getName());
|
||||
this.propertyIndex = source.propertyIndex;
|
||||
|
||||
this.indexed = source.isIndexed();
|
||||
this.indexName = source.getIndexName();
|
||||
this.dbColumn = InternString.intern(override.getDbColumn());
|
||||
// override with sqlFormula not currently supported
|
||||
this.sqlFormulaJoin = null;
|
||||
@@ -631,14 +622,6 @@ public class BeanProperty implements ElPropertyValue, Property {
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this object is part of an inheritance hierarchy.
|
||||
*/
|
||||
|
||||
+12
-3
@@ -3,7 +3,7 @@ package com.avaje.ebeaninternal.server.deploy;
|
||||
/**
|
||||
* Holds multiple column unique constraints defined for an entity.
|
||||
*/
|
||||
public class CompoundUniqueConstraint {
|
||||
public class IndexDefinition {
|
||||
|
||||
private final String[] columns;
|
||||
|
||||
@@ -11,7 +11,16 @@ public class CompoundUniqueConstraint {
|
||||
|
||||
private final boolean unique;
|
||||
|
||||
public CompoundUniqueConstraint(String[] columns, String name, boolean unique) {
|
||||
/**
|
||||
* A single column index.
|
||||
*/
|
||||
public IndexDefinition(String column, String name, boolean unique) {
|
||||
this.columns = new String[]{column};
|
||||
this.unique = unique;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public IndexDefinition(String[] columns, String name, boolean unique) {
|
||||
this.columns = columns;
|
||||
this.unique = unique;
|
||||
this.name = name;
|
||||
@@ -20,7 +29,7 @@ public class CompoundUniqueConstraint {
|
||||
/**
|
||||
* Create a unique constraint given the column names.
|
||||
*/
|
||||
public CompoundUniqueConstraint(String[] columns) {
|
||||
public IndexDefinition(String[] columns) {
|
||||
this.columns = columns;
|
||||
this.unique = true;
|
||||
this.name = null;
|
||||
+13
-13
@@ -23,7 +23,7 @@ import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistController;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPersistListener;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanPostLoad;
|
||||
import com.avaje.ebeaninternal.server.deploy.ChainedBeanQueryAdapter;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.InheritInfo;
|
||||
import com.avaje.ebeaninternal.server.deploy.parse.DeployBeanInfo;
|
||||
import com.avaje.ebeaninternal.server.idgen.UuidIdGenerator;
|
||||
@@ -108,7 +108,7 @@ public class DeployBeanDescriptor<T> {
|
||||
|
||||
private boolean updateChangesOnly;
|
||||
|
||||
private List<CompoundUniqueConstraint> compoundUniqueConstraints;
|
||||
private List<IndexDefinition> indexDefinitions;
|
||||
|
||||
/**
|
||||
* The base database table.
|
||||
@@ -283,7 +283,7 @@ public class DeployBeanDescriptor<T> {
|
||||
docStoreUpdate = docStore.update();
|
||||
docStoreDelete = docStore.delete();
|
||||
String doc = docStore.doc();
|
||||
if (doc.length() > 0) {
|
||||
if (!doc.isEmpty()) {
|
||||
docStorePathProperties = PathProperties.parse(doc);
|
||||
}
|
||||
}
|
||||
@@ -388,7 +388,7 @@ public class DeployBeanDescriptor<T> {
|
||||
public void setCache(Cache cache) {
|
||||
|
||||
String naturalKey = null;
|
||||
if (cache.naturalKey().length() > 0) {
|
||||
if (!cache.naturalKey().isEmpty()) {
|
||||
// find the property and mark as natural key property
|
||||
String propName = cache.naturalKey().trim();
|
||||
DeployBeanProperty beanProperty = getBeanProperty(propName);
|
||||
@@ -440,21 +440,21 @@ public class DeployBeanDescriptor<T> {
|
||||
/**
|
||||
* Add a compound unique constraint.
|
||||
*/
|
||||
public void addCompoundUniqueConstraint(CompoundUniqueConstraint c) {
|
||||
if (compoundUniqueConstraints == null) {
|
||||
compoundUniqueConstraints = new ArrayList<CompoundUniqueConstraint>();
|
||||
public void addIndex(IndexDefinition c) {
|
||||
if (indexDefinitions == null) {
|
||||
indexDefinitions = new ArrayList<IndexDefinition>();
|
||||
}
|
||||
compoundUniqueConstraints.add(c);
|
||||
indexDefinitions.add(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the compound unique constraints (can be null).
|
||||
*/
|
||||
public CompoundUniqueConstraint[] getCompoundUniqueConstraints() {
|
||||
if (compoundUniqueConstraints == null) {
|
||||
public IndexDefinition[] getIndexDefinitions() {
|
||||
if (indexDefinitions == null) {
|
||||
return null;
|
||||
} else {
|
||||
return compoundUniqueConstraints.toArray(new CompoundUniqueConstraint[compoundUniqueConstraints.size()]);
|
||||
return indexDefinitions.toArray(new IndexDefinition[indexDefinitions.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -583,7 +583,7 @@ public class DeployBeanDescriptor<T> {
|
||||
*/
|
||||
public void setView(String viewName, String[] dependentTables) {
|
||||
this.entityType = EntityType.VIEW;
|
||||
this.dependentTables = this.dependentTables;
|
||||
this.dependentTables = dependentTables;
|
||||
setBaseTable(new TableName(viewName), "", "");
|
||||
}
|
||||
|
||||
@@ -835,7 +835,7 @@ public class DeployBeanDescriptor<T> {
|
||||
return null;
|
||||
}
|
||||
String selectClause = sb.toString();
|
||||
if (selectClause.length() == 0) {
|
||||
if (selectClause.isEmpty()) {
|
||||
throw new IllegalStateException("Bean " + getFullName() + " has no properties?");
|
||||
}
|
||||
return selectClause.substring(0, selectClause.length() - 1);
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertyGetter;
|
||||
import com.avaje.ebeaninternal.server.properties.BeanPropertySetter;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarType;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeEnum;
|
||||
import com.avaje.ebeaninternal.server.type.ScalarTypeWrapper;
|
||||
import com.avaje.ebeanservice.docstore.api.mapping.DocPropertyOptions;
|
||||
|
||||
@@ -192,9 +191,6 @@ public class DeployBeanProperty {
|
||||
|
||||
private int sortOrder;
|
||||
|
||||
private boolean indexed;
|
||||
private String indexName;
|
||||
|
||||
private boolean excludedFromHistory;
|
||||
|
||||
private boolean draft;
|
||||
@@ -386,7 +382,7 @@ public class DeployBeanProperty {
|
||||
* Set a specific DB column definition.
|
||||
*/
|
||||
public void setDbColumnDefn(String dbColumnDefn) {
|
||||
if (dbColumnDefn == null || dbColumnDefn.trim().length() == 0) {
|
||||
if (dbColumnDefn == null || dbColumnDefn.trim().isEmpty()) {
|
||||
this.dbColumnDefn = null;
|
||||
} else {
|
||||
this.dbColumnDefn = InternString.intern(dbColumnDefn);
|
||||
@@ -849,22 +845,6 @@ public class DeployBeanProperty {
|
||||
return desc.getFullName() + "." + name;
|
||||
}
|
||||
|
||||
public boolean isIndexed() {
|
||||
return indexed;
|
||||
}
|
||||
|
||||
public void setIndexed() {
|
||||
this.indexed = true;
|
||||
}
|
||||
|
||||
public String getIndexName() {
|
||||
return indexName;
|
||||
}
|
||||
|
||||
public void setIndexName(String indexName) {
|
||||
this.indexName = indexName;
|
||||
}
|
||||
|
||||
public boolean isExcludedFromHistory() {
|
||||
return excludedFromHistory;
|
||||
}
|
||||
|
||||
+2
-2
@@ -178,7 +178,7 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
|
||||
* Set the default mapKey to use when returning a Map.
|
||||
*/
|
||||
public void setMapKey(String mapKey) {
|
||||
if (mapKey != null && mapKey.length() > 0) {
|
||||
if (mapKey != null && !mapKey.isEmpty()) {
|
||||
this.mapKey = mapKey;
|
||||
}
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class DeployBeanPropertyAssocMany<T> extends DeployBeanPropertyAssoc<T> {
|
||||
* list, set or map.
|
||||
*/
|
||||
public void setFetchOrderBy(String orderBy) {
|
||||
if (orderBy != null && orderBy.length() > 0) {
|
||||
if (orderBy != null && !orderBy.isEmpty()) {
|
||||
fetchOrderBy = orderBy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public abstract class AnnotationBase {
|
||||
* Checks string is null or empty .
|
||||
*/
|
||||
protected boolean isEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
return s == null || s.trim().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebean.annotation.UpdateMode;
|
||||
import com.avaje.ebean.annotation.View;
|
||||
import com.avaje.ebean.config.TableName;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor.EntityType;
|
||||
import com.avaje.ebeaninternal.server.deploy.CompoundUniqueConstraint;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -120,12 +120,12 @@ public class AnnotationClass extends AnnotationParser {
|
||||
|
||||
Index index = cls.getAnnotation(Index.class);
|
||||
if (index != null) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(index.columnNames(), index.name(), index.unique()));
|
||||
descriptor.addIndex(new IndexDefinition(index.columnNames(), index.name(), index.unique()));
|
||||
}
|
||||
|
||||
UniqueConstraint uc = cls.getAnnotation(UniqueConstraint.class);
|
||||
if (uc != null) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(uc.columnNames()));
|
||||
descriptor.addIndex(new IndexDefinition(uc.columnNames()));
|
||||
}
|
||||
|
||||
View view = cls.getAnnotation(View.class);
|
||||
@@ -136,7 +136,7 @@ public class AnnotationClass extends AnnotationParser {
|
||||
if (table != null) {
|
||||
UniqueConstraint[] uniqueConstraints = table.uniqueConstraints();
|
||||
for (UniqueConstraint c : uniqueConstraints) {
|
||||
descriptor.addCompoundUniqueConstraint(new CompoundUniqueConstraint(c.columnNames()));
|
||||
descriptor.addIndex(new IndexDefinition(c.columnNames()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import com.avaje.ebean.config.dbplatform.DbEncrypt;
|
||||
import com.avaje.ebean.config.dbplatform.DbEncryptFunction;
|
||||
import com.avaje.ebean.config.dbplatform.IdType;
|
||||
import com.avaje.ebean.config.dbplatform.PlatformIdGenerator;
|
||||
import com.avaje.ebeaninternal.server.deploy.IndexDefinition;
|
||||
import com.avaje.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
|
||||
@@ -314,8 +315,7 @@ public class AnnotationFields extends AnnotationParser {
|
||||
if (hasRelationshipItem(prop)) {
|
||||
throw new RuntimeException("Can't use Index on foreign key relationships.");
|
||||
}
|
||||
prop.setIndexed();
|
||||
prop.setIndexName(index.name());
|
||||
descriptor.addIndex(new IndexDefinition(prop.getDbColumn(), index.name(), index.unique()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ public class DeployInheritInfo {
|
||||
public void setDiscriminatorValue(String value) {
|
||||
if (value != null) {
|
||||
value = value.trim();
|
||||
if (value.length() != 0) {
|
||||
if (!value.isEmpty()) {
|
||||
discriminatorStringValue = value;
|
||||
// convert the value if desired
|
||||
if (discriminatorType == Types.INTEGER) {
|
||||
|
||||
@@ -70,7 +70,7 @@ public class SqlReservedWords {
|
||||
public static synchronized void addKeyword(String keyword){
|
||||
if (keyword != null){
|
||||
keyword = keyword.trim().toUpperCase();
|
||||
if (keyword.length() > 0){
|
||||
if (!keyword.isEmpty()){
|
||||
keywords.add(keyword);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyValue;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
|
||||
/**
|
||||
* Base class for simple expressions.
|
||||
@@ -20,11 +21,32 @@ public abstract class AbstractExpression implements SpiExpression {
|
||||
this.propName = propName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// override on SimpleExpression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return propertyNestedPath(propName, desc);
|
||||
}
|
||||
|
||||
protected String propertyNestedPath(String propertyName, BeanDescriptor<?> desc) {
|
||||
if (propertyName != null) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(propertyName);
|
||||
if (elProp != null && elProp.containsMany()) {
|
||||
return SplitName.begin(propName);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ public abstract class AbstractTextExpression extends AbstractExpression {
|
||||
super(propName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
// do nothing, only execute against document store
|
||||
|
||||
@@ -30,6 +30,11 @@ class AllEqualsExpression extends NonPrepareExpression {
|
||||
context.writeAllEquals(propMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
if (propMap != null) {
|
||||
|
||||
+11
@@ -7,6 +7,7 @@ import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -39,6 +40,16 @@ class BetweenPropertyExpression extends NonPrepareExpression {
|
||||
context.endBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
ElPropertyDeploy elProp = desc.getElPropertyDeploy(name(lowProperty));
|
||||
if (elProp != null && elProp.containsMany()) {
|
||||
// assumes highProperty is also nested property which seems reasonable
|
||||
return SplitName.begin(lowProperty);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
|
||||
+31
-25
@@ -1,8 +1,5 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.avaje.ebean.ExampleExpression;
|
||||
import com.avaje.ebean.LikeType;
|
||||
import com.avaje.ebean.bean.EntityBean;
|
||||
@@ -12,33 +9,34 @@ import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanProperty;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
import com.avaje.ebeaninternal.server.query.SplitName;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* A "Query By Example" type of expression.
|
||||
* <p>
|
||||
* Pass in an example entity and for each non-null scalar properties an
|
||||
* expression is added.
|
||||
* </p>
|
||||
*
|
||||
* <pre class="code">
|
||||
* <p>
|
||||
* <pre>{@code
|
||||
* // create an example bean and set the properties
|
||||
* // with the query parameters you want
|
||||
* Customer example = new Customer();
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class).where()
|
||||
* // pass the bean into the where() clause
|
||||
* .exampleLike(example)
|
||||
* // you can add other expressions to the same query
|
||||
* .gt("id", 2).findList();
|
||||
*
|
||||
* </pre>
|
||||
* example.setName("Rob%");
|
||||
* example.setNotes("%something%");
|
||||
*
|
||||
* List<Customer> list = Ebean.find(Customer.class)
|
||||
* .where()
|
||||
* .exampleLike(example)
|
||||
* .findList();
|
||||
*
|
||||
* }</pre>
|
||||
*/
|
||||
public class DefaultExampleExpression implements SpiExpression, ExampleExpression {
|
||||
|
||||
@@ -71,13 +69,10 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
|
||||
/**
|
||||
* Construct the query by example expression.
|
||||
*
|
||||
* @param entity
|
||||
* the example entity with non null property values
|
||||
* @param caseInsensitive
|
||||
* if true use case insensitive expressions
|
||||
* @param likeType
|
||||
* the type of Like wild card used
|
||||
*
|
||||
* @param entity the example entity with non null property values
|
||||
* @param caseInsensitive if true use case insensitive expressions
|
||||
* @param likeType the type of Like wild card used
|
||||
*/
|
||||
public DefaultExampleExpression(EntityBean entity, boolean caseInsensitive, LikeType likeType) {
|
||||
this.entity = entity;
|
||||
@@ -104,11 +99,22 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new DefaultExampleExpression(list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
list = buildExpressions(desc);
|
||||
@@ -290,9 +296,9 @@ public class DefaultExampleExpression implements SpiExpression, ExampleExpressio
|
||||
}
|
||||
|
||||
} else if ((beanProperty instanceof BeanPropertyAssocOne) && (value instanceof EntityBean)) {
|
||||
BeanPropertyAssocOne assocOne = (BeanPropertyAssocOne)beanProperty;
|
||||
BeanPropertyAssocOne assocOne = (BeanPropertyAssocOne) beanProperty;
|
||||
BeanDescriptor targetDescriptor = assocOne.getTargetDescriptor();
|
||||
addExpressions(list, targetDescriptor, (EntityBean)value, propName);
|
||||
addExpressions(list, targetDescriptor, (EntityBean) value, propName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+68
-11
@@ -29,7 +29,9 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
protected final List<SpiExpression> list;
|
||||
private static final String AND = " and ";
|
||||
|
||||
protected List<SpiExpression> list;
|
||||
|
||||
protected final Query<T> query;
|
||||
|
||||
@@ -37,9 +39,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
|
||||
protected transient ExpressionFactory expr;
|
||||
|
||||
private final String listAndStart;
|
||||
private final String listAndEnd;
|
||||
private final String listAndJoin;
|
||||
protected String allDocNestedPath;
|
||||
|
||||
/**
|
||||
* Set to true for the "Text" root expression list.
|
||||
@@ -71,16 +71,32 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
this.query = query;
|
||||
this.expr = expr;
|
||||
this.parentExprList = parentExprList;
|
||||
|
||||
this.listAndStart = "";
|
||||
this.listAndEnd = "";
|
||||
this.listAndJoin = " and ";
|
||||
}
|
||||
|
||||
private DefaultExpressionList() {
|
||||
this(null, null, null, new ArrayList<SpiExpression>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the expression list as a Junction or top level DefaultExpressionList.
|
||||
*
|
||||
* @param list The list of expressions grouped by nested path
|
||||
* @param nestedPath The doc store nested path
|
||||
* @param type The junction type (or null for top level expression list).
|
||||
* @return A single SpiExpression that has the nestedPath set
|
||||
*/
|
||||
SpiExpression wrap(List<SpiExpression> list, String nestedPath, Junction.Type type) {
|
||||
|
||||
DefaultExpressionList<T> wrapper = new DefaultExpressionList<T>(query, expr, null, list, false);
|
||||
wrapper.setAllDocNested(nestedPath);
|
||||
|
||||
if (type != null) {
|
||||
return new JunctionExpression<T>(type, wrapper);
|
||||
} else {
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Write being aware if it is the Top level "text" expressions.
|
||||
* <p>
|
||||
@@ -100,6 +116,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
// this is a Top level "text" expressions so we may need to wrap in Bool SHOULD etc.
|
||||
if (list.isEmpty()) throw new IllegalStateException("empty expression list?");
|
||||
|
||||
if (allDocNestedPath!=null) context.startNested(allDocNestedPath);
|
||||
int size = list.size();
|
||||
|
||||
SpiExpression first = list.get(0);
|
||||
@@ -130,11 +147,13 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
if (implicitBool || explicitBool) {
|
||||
context.endBoolGroup();
|
||||
}
|
||||
if (allDocNestedPath!=null) context.endNested();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeDocQuery(DocQueryContext context, SpiExpression idEquals) throws IOException {
|
||||
|
||||
if (allDocNestedPath!=null) context.startNested(allDocNestedPath);
|
||||
int size = list.size();
|
||||
if (size == 1 && idEquals == null) {
|
||||
// only 1 expression - skip bool
|
||||
@@ -153,6 +172,7 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
}
|
||||
context.endBool();
|
||||
}
|
||||
if (allDocNestedPath!=null) context.endNested();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -184,6 +204,12 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return copy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if one of the expressions is related to a Many property.
|
||||
*/
|
||||
@@ -433,15 +459,13 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
|
||||
request.append(listAndStart);
|
||||
for (int i = 0, size = list.size(); i < size; i++) {
|
||||
SpiExpression expression = list.get(i);
|
||||
if (i > 0) {
|
||||
request.append(listAndJoin);
|
||||
request.append(AND);
|
||||
}
|
||||
expression.addSql(request);
|
||||
}
|
||||
request.append(listAndEnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -983,4 +1007,37 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return junction(Junction.Type.MUST_NOT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
// effectively handled by JunctionExpression
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the nested path that all contained expressions share.
|
||||
*/
|
||||
public void setAllDocNested(String allDocNestedPath) {
|
||||
this.allDocNestedPath = allDocNestedPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the underlying expression list with one organised by nested path.
|
||||
*/
|
||||
public void setUnderlying(List<SpiExpression> groupedByNesting) {
|
||||
this.list = groupedByNesting;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare expressions for document store nested path handling.
|
||||
*/
|
||||
public void prepareDocNested(BeanDescriptor<T> beanDescriptor) {
|
||||
PrepareDocNested.prepare(this, beanDescriptor);
|
||||
}
|
||||
|
||||
public Object idEqualTo(String idName) {
|
||||
if (list.size() == 1) {
|
||||
return list.get(0).getIdEqualTo(idName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,4 +147,24 @@ public interface DocQueryContext {
|
||||
* Return the expression path for the given property path.
|
||||
*/
|
||||
ExpressionPath getExpressionPath(String propName);
|
||||
|
||||
/**
|
||||
* Start nested path expressions.
|
||||
*/
|
||||
void startNested(String nestedPath) throws IOException;
|
||||
|
||||
/**
|
||||
* End nested path expressions.
|
||||
*/
|
||||
void endNested() throws IOException;
|
||||
|
||||
/**
|
||||
* Start a not wrapping an expression.
|
||||
*/
|
||||
void startNot() throws IOException;
|
||||
|
||||
/**
|
||||
* End a not wrapper.
|
||||
*/
|
||||
void endNot() throws IOException;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,12 @@ class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreExpress
|
||||
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) {
|
||||
|
||||
@@ -118,6 +124,11 @@ class ExistsQueryExpression implements SpiExpression, UnsupportedDocStoreExpress
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
// Nothing to do for exists expression
|
||||
|
||||
@@ -25,6 +25,11 @@ class IdExpression extends NonPrepareExpression implements SpiExpression {
|
||||
context.writeId(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns false.
|
||||
*/
|
||||
|
||||
@@ -22,6 +22,11 @@ public class IdInExpression extends NonPrepareExpression {
|
||||
this.idList = idList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
}
|
||||
|
||||
@@ -16,15 +16,38 @@ class IsEmptyExpression extends AbstractExpression {
|
||||
|
||||
private final String propertyPath;
|
||||
|
||||
private String nestedPath;
|
||||
|
||||
IsEmptyExpression(String propertyName, boolean empty) {
|
||||
super(propertyName);
|
||||
this.empty = empty;
|
||||
this.propertyPath = SplitName.split(propertyName)[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
if (empty) {
|
||||
// capture the nestedPath as we want to put wrap
|
||||
// a NOT around the outer of the nested path exists
|
||||
this.nestedPath = propertyNestedPath(propName, desc);
|
||||
return null;
|
||||
} else {
|
||||
return super.nestedPath(desc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.writeExists(!empty, propName);
|
||||
if (nestedPath == null) {
|
||||
context.writeExists(!empty, propName);
|
||||
} else {
|
||||
// wrap NOT around the outside of nested path exists expression
|
||||
context.startNot();
|
||||
context.startNested(nestedPath);
|
||||
context.writeExists(empty, propName);
|
||||
context.endNested();
|
||||
context.endNot();
|
||||
}
|
||||
}
|
||||
|
||||
public final String getPropName() {
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.Set;
|
||||
*/
|
||||
class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, ExpressionList<T> {
|
||||
|
||||
private final DefaultExpressionList<T> exprList;
|
||||
protected final DefaultExpressionList<T> exprList;
|
||||
|
||||
protected final Junction.Type type;
|
||||
|
||||
@@ -80,6 +80,12 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
context.endBoolGroupList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
@@ -790,4 +796,17 @@ class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expression
|
||||
public ExpressionList<T> endNot() {
|
||||
return endJunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
|
||||
PrepareDocNested.prepare(exprList, desc, type);
|
||||
String nestedPath = exprList.allDocNestedPath;
|
||||
if (nestedPath != null) {
|
||||
// push the nestedPath up to parent
|
||||
exprList.setAllDocNested(null);
|
||||
return nestedPath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,9 @@ abstract class LogicExpression implements SpiExpression {
|
||||
}
|
||||
}
|
||||
|
||||
protected final SpiExpression expOne;
|
||||
protected SpiExpression expOne;
|
||||
|
||||
protected final SpiExpression expTwo;
|
||||
protected SpiExpression expTwo;
|
||||
|
||||
private final String joinType;
|
||||
|
||||
@@ -67,6 +67,33 @@ abstract class LogicExpression implements SpiExpression {
|
||||
context.endBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
|
||||
String pathOne = expOne.nestedPath(desc);
|
||||
String pathTwo = expTwo.nestedPath(desc);
|
||||
|
||||
if (pathOne == null && pathTwo == null) {
|
||||
return null;
|
||||
}
|
||||
if (pathOne != null && pathOne.equals(pathTwo)) {
|
||||
return pathOne;
|
||||
}
|
||||
if (pathOne != null) {
|
||||
expOne = new NestedPathWrapperExpression(pathOne, expOne);
|
||||
}
|
||||
if (pathTwo != null) {
|
||||
expTwo = new NestedPathWrapperExpression(pathTwo, expTwo);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
expOne.containsMany(desc, manyWhereJoin);
|
||||
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.event.BeanQueryRequest;
|
||||
import com.avaje.ebeaninternal.api.HashQueryPlanBuilder;
|
||||
import com.avaje.ebeaninternal.api.ManyWhereJoins;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionRequest;
|
||||
import com.avaje.ebeaninternal.api.SpiExpressionValidation;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Wraps a single expression with nestedPath for document queries.
|
||||
*/
|
||||
class NestedPathWrapperExpression implements SpiExpression {
|
||||
|
||||
protected final String nestedPath;
|
||||
|
||||
protected final SpiExpression delegate;
|
||||
|
||||
NestedPathWrapperExpression(String nestedPath, SpiExpression delegate) {
|
||||
this.nestedPath = nestedPath;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
context.startNested(nestedPath);
|
||||
delegate.writeDocQuery(context);
|
||||
context.endNested();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return nestedPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
delegate.containsMany(desc, whereManyJoins);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareExpression(BeanQueryRequest<?> request) {
|
||||
delegate.prepareExpression(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void queryPlanHash(HashQueryPlanBuilder builder) {
|
||||
delegate.queryPlanHash(builder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryBindHash() {
|
||||
return delegate.queryBindHash();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByPlan(SpiExpression other) {
|
||||
if (other instanceof NestedPathWrapperExpression) {
|
||||
NestedPathWrapperExpression that = (NestedPathWrapperExpression)other;
|
||||
return nestedPath.equals(that.nestedPath)
|
||||
&& delegate.isSameByPlan(that.delegate);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSameByBind(SpiExpression other) {
|
||||
return delegate.isSameByBind(other);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSql(SpiExpressionRequest request) {
|
||||
delegate.addSql(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBindValues(SpiExpressionRequest request) {
|
||||
delegate.addBindValues(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(SpiExpressionValidation validation) {
|
||||
delegate.validate(validation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new NestedPathWrapperExpression(nestedPath, delegate.copyForPlanKey());
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,12 @@ abstract class NonPrepareExpression implements SpiExpression {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always null in this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return this;
|
||||
|
||||
@@ -26,6 +26,17 @@ class NoopExpression implements SpiExpression {
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins whereManyJoins) {
|
||||
// nothing to do
|
||||
|
||||
@@ -29,11 +29,22 @@ final class NotExpression implements SpiExpression {
|
||||
context.endBool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
// always return null for this expression
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpiExpression copyForPlanKey() {
|
||||
return new NotExpression(exp.copyForPlanKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return exp.nestedPath(desc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
exp.containsMany(desc, manyWhereJoin);
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Junction;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Prepare nested path expressions for
|
||||
*/
|
||||
class PrepareDocNested {
|
||||
|
||||
/**
|
||||
* Prepare the top level expressions for nested path handling.
|
||||
*/
|
||||
static void prepare(DefaultExpressionList<?> expressions, BeanDescriptor<?> beanDescriptor) {
|
||||
new PrepareDocNested(expressions, beanDescriptor, null).process();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the Junction expressions for nested path handling.
|
||||
*/
|
||||
static void prepare(DefaultExpressionList<?> expressions, BeanDescriptor<?> beanDescriptor, Junction.Type type) {
|
||||
new PrepareDocNested(expressions, beanDescriptor, type).process();
|
||||
}
|
||||
|
||||
enum Mode {
|
||||
NONE,
|
||||
SINGLE,
|
||||
MIXED
|
||||
}
|
||||
|
||||
private final Junction.Type type;
|
||||
private final DefaultExpressionList<?> original;
|
||||
private final BeanDescriptor<?> beanDescriptor;
|
||||
private final List<SpiExpression> origUnderlying;
|
||||
private final int origSize;
|
||||
|
||||
private boolean hasNesting;
|
||||
private boolean hasMixedNesting;
|
||||
private String firstNestedPath;
|
||||
|
||||
|
||||
PrepareDocNested(DefaultExpressionList<?> original, BeanDescriptor<?> beanDescriptor, Junction.Type type) {
|
||||
this.type = type;
|
||||
this.beanDescriptor = beanDescriptor;
|
||||
this.original = original;
|
||||
this.origUnderlying = original.getUnderlyingList();
|
||||
this.origSize = origUnderlying.size();
|
||||
}
|
||||
|
||||
void process() {
|
||||
|
||||
PrepareDocNested.Mode mode = determineMode();
|
||||
if (mode == PrepareDocNested.Mode.SINGLE) {
|
||||
original.setAllDocNested(firstNestedPath);
|
||||
|
||||
} else if (mode == PrepareDocNested.Mode.MIXED) {
|
||||
original.setUnderlying(group());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reorganise the flat list of expressions into a tree grouping expressions by nested path.
|
||||
*
|
||||
* Returns the new top level list of expressions.
|
||||
*/
|
||||
private List<SpiExpression> group() {
|
||||
|
||||
Map<String,Group> groups = new LinkedHashMap<String,Group>();
|
||||
|
||||
// organise expressions by nestedPath
|
||||
for (int i = 0; i < origSize; i++) {
|
||||
SpiExpression expr = origUnderlying.get(i);
|
||||
String nestedPath = expr.nestedPath(beanDescriptor);
|
||||
Group group = groups.get(nestedPath);
|
||||
if (group == null) {
|
||||
group = new Group(nestedPath);
|
||||
groups.put(nestedPath, group);
|
||||
}
|
||||
group.list.add(expr);
|
||||
}
|
||||
|
||||
List<SpiExpression> newList = new ArrayList<SpiExpression>();
|
||||
Collection<Group> values = groups.values();
|
||||
for (Group group : values) {
|
||||
group.addTo(newList);
|
||||
}
|
||||
return newList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determined the nested path mode.
|
||||
*/
|
||||
private Mode determineMode() {
|
||||
|
||||
if (!hasNesting()) {
|
||||
// no nested paths at all
|
||||
return Mode.NONE;
|
||||
}
|
||||
if (!hasMixedNesting) {
|
||||
// single nested path for all expressions
|
||||
return Mode.SINGLE;
|
||||
}
|
||||
// mixed nested paths to underlying expression list needs re-organising by nested path
|
||||
return Mode.MIXED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the expressions have nested paths.
|
||||
*/
|
||||
private boolean hasNesting() {
|
||||
|
||||
for (int i = 0; i < origSize; i++) {
|
||||
SpiExpression expr = origUnderlying.get(i);
|
||||
String nestedPath = expr.nestedPath(beanDescriptor);
|
||||
if (nestedPath == null) {
|
||||
hasMixedNesting = true;
|
||||
|
||||
} if (nestedPath != null) {
|
||||
hasNesting = true;
|
||||
if (firstNestedPath == null) {
|
||||
firstNestedPath = nestedPath;
|
||||
} else if (hasMixedNesting || !firstNestedPath.equals(nestedPath)) {
|
||||
hasMixedNesting = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasNesting;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List of SpiExpression grouped by nested path.
|
||||
*/
|
||||
class Group {
|
||||
|
||||
final String nestedPath;
|
||||
|
||||
final List<SpiExpression> list = new ArrayList<SpiExpression>();
|
||||
|
||||
Group(String nestedPath) {
|
||||
this.nestedPath = nestedPath;
|
||||
}
|
||||
|
||||
void addTo(List<SpiExpression> newList) {
|
||||
if (nestedPath == null) {
|
||||
newList.addAll(list);
|
||||
} else {
|
||||
newList.add(original.wrap(list, nestedPath, type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -25,6 +25,11 @@ class RawExpression extends NonPrepareExpression {
|
||||
context.writeRaw(sql, values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String nestedPath(BeanDescriptor<?> desc) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void containsMany(BeanDescriptor<?> desc, ManyWhereJoins manyWhereJoin) {
|
||||
|
||||
|
||||
@@ -21,6 +21,14 @@ public class SimpleExpression extends AbstractExpression {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getIdEqualTo(String idName) {
|
||||
if (type == Op.EQ && idName.equals(propName)) {
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeDocQuery(DocQueryContext context) throws IOException {
|
||||
if (type == Op.BETWEEN) {
|
||||
|
||||
@@ -24,7 +24,7 @@ public class StringHelper {
|
||||
String listDelimiter, String nameValueSeparator) {
|
||||
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.length() == 0)) {
|
||||
if ((allNameValuePairs == null) || (allNameValuePairs.isEmpty())) {
|
||||
return params;
|
||||
}
|
||||
// trim off any leading listDelimiter...
|
||||
@@ -56,7 +56,7 @@ public class StringHelper {
|
||||
* Return true if the value is null or an empty string.
|
||||
*/
|
||||
public static boolean isNull(String value) {
|
||||
return value == null || value.trim().length() == 0;
|
||||
return value == null || value.trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +90,7 @@ public class StringHelper {
|
||||
// there is a key without a value?
|
||||
String key = allNameValuePairs.substring(pos, delimPos);
|
||||
key = key.trim();
|
||||
if (key.length() > 0) {
|
||||
if (!key.isEmpty()) {
|
||||
map.put(key, null);
|
||||
}
|
||||
return getKeyValue(map, delimPos + 1, allNameValuePairs, listDelimiter,
|
||||
|
||||
@@ -33,7 +33,7 @@ public class Binder {
|
||||
|
||||
private final int asOfBindCount;
|
||||
|
||||
private final boolean bindAsOfWithFromClause;
|
||||
private final boolean asOfStandardsBased;
|
||||
|
||||
private final DbExpressionHandler dbExpressionHandler;
|
||||
|
||||
@@ -42,12 +42,12 @@ public class Binder {
|
||||
/**
|
||||
* Set the PreparedStatement with which to bind variables to.
|
||||
*/
|
||||
public Binder(TypeManager typeManager, int asOfBindCount, boolean bindAsOfWithFromClause,
|
||||
public Binder(TypeManager typeManager, int asOfBindCount, boolean asOfStandardsBased,
|
||||
DbExpressionHandler dbExpressionHandler, DataTimeZone dataTimeZone) {
|
||||
|
||||
this.typeManager = typeManager;
|
||||
this.asOfBindCount = asOfBindCount;
|
||||
this.bindAsOfWithFromClause = bindAsOfWithFromClause;
|
||||
this.asOfStandardsBased = asOfStandardsBased;
|
||||
this.dbExpressionHandler = dbExpressionHandler;
|
||||
this.dataTimeZone = dataTimeZone;
|
||||
}
|
||||
@@ -60,12 +60,10 @@ public class Binder {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the 'as of' predicates are in the from/join clause in which case the timestamp is
|
||||
* bound early (before all the other predicates ala Oracle). Return false if the 'as of' predicates are
|
||||
* appended to the end of the predicates and the timestamp is bound last (Postgres, MySql).
|
||||
* Return true if the 'as of' history support is SQL2011 standards based.
|
||||
*/
|
||||
public boolean isBindAsOfWithFromClause() {
|
||||
return bindAsOfWithFromClause;
|
||||
public boolean isAsOfStandardsBased() {
|
||||
return asOfStandardsBased;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -839,16 +839,6 @@ public final class DefaultPersister implements Persister {
|
||||
this.publish = request.isPublish();
|
||||
}
|
||||
|
||||
private SaveManyPropRequest(BeanPropertyAssocMany<?> many, EntityBean parentBean, SpiTransaction t) {
|
||||
this.insertedParent = false;
|
||||
this.many = many;
|
||||
this.parentBean = parentBean;
|
||||
this.transaction = t;
|
||||
this.cascade = true;
|
||||
this.deleteMissingChildren = false;
|
||||
this.publish = false;
|
||||
}
|
||||
|
||||
public boolean isSaveIntersection() {
|
||||
return transaction.isSaveAssocManyIntersection(many.getIntersectionTableJoin().getTable(), many.getBeanDescriptor().getName());
|
||||
}
|
||||
|
||||
@@ -466,18 +466,20 @@ public class CQueryBuilder {
|
||||
String inheritanceWhere = select.getInheritanceWhereSql();
|
||||
|
||||
boolean hasWhere = false;
|
||||
if (inheritanceWhere.length() > 0) {
|
||||
if (!inheritanceWhere.isEmpty()) {
|
||||
sb.append(" where");
|
||||
sb.append(inheritanceWhere);
|
||||
hasWhere = true;
|
||||
}
|
||||
|
||||
int asOfCount = query.getAsOfTableCount();
|
||||
if (asOfCount > 0 && !historySupport.isStandardsBased()) {
|
||||
hasWhere = appendWhere(hasWhere, sb);
|
||||
sb.append(historySupport.getAsOfPredicate(request.getBaseTableAlias()));
|
||||
}
|
||||
|
||||
if (request.isFindById() || query.getId() != null) {
|
||||
if (hasWhere) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" where ");
|
||||
}
|
||||
appendWhere(hasWhere, sb);
|
||||
|
||||
BeanDescriptor<?> desc = request.getBeanDescriptor();
|
||||
String idSql = desc.getIdBinderIdSql();
|
||||
@@ -515,24 +517,6 @@ public class CQueryBuilder {
|
||||
sb.append(dbFilterMany);
|
||||
}
|
||||
|
||||
List<String> asOfTableAlias = query.getAsOfTableAlias();
|
||||
if (asOfTableAlias != null && !historySupport.isBindAtFromClause()) {
|
||||
// append the effective date predicates for each table alias
|
||||
// that maps to a @History entity involved in this query
|
||||
// Do this when history using separate tables/views (PG, MySql etc)
|
||||
if (!hasWhere) {
|
||||
sb.append(" where ");
|
||||
} else {
|
||||
sb.append("and ");
|
||||
}
|
||||
for (int i = 0; i < asOfTableAlias.size(); i++) {
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
sb.append(historySupport.getAsOfPredicate(asOfTableAlias.get(i)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!query.isIncludeSoftDeletes()) {
|
||||
List<String> softDeletePredicates = query.getSoftDeletePredicates();
|
||||
if (softDeletePredicates != null) {
|
||||
@@ -565,6 +549,18 @@ public class CQueryBuilder {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Append where or and based on the hasWhere flag.
|
||||
*/
|
||||
private boolean appendWhere(boolean hasWhere, StringBuilder sb) {
|
||||
if (hasWhere) {
|
||||
sb.append(" and ");
|
||||
} else {
|
||||
sb.append(" where ");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the dbOrderBy clause to be safe for adding to select. This is done when 'distinct' is
|
||||
* used.
|
||||
@@ -575,7 +571,7 @@ public class CQueryBuilder {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public class CQueryBuilderRawSql {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
private String getOrderBy(CQueryPredicates predicates, RawSql.Sql sql) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebean.config.ServerConfig;
|
||||
import com.avaje.ebeaninternal.server.core.QueryIterator;
|
||||
import com.avaje.ebean.ValuePair;
|
||||
import com.avaje.ebean.Version;
|
||||
@@ -19,6 +20,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -34,15 +36,22 @@ public class CQueryEngine {
|
||||
|
||||
private static final String T0 = "t0";
|
||||
|
||||
private final int defaultFetchSizeFindList;
|
||||
|
||||
private final int defaultFetchSizeFindEach;
|
||||
|
||||
private final boolean forwardOnlyHintOnFindIterate;
|
||||
|
||||
private final CQueryBuilder queryBuilder;
|
||||
|
||||
private final CQueryHistorySupport historySupport;
|
||||
|
||||
public CQueryEngine(DatabasePlatform dbPlatform, Binder binder, Map<String, String> asOfTableMapping, String asOfSysPeriod, Map<String, String> draftTableMap) {
|
||||
public CQueryEngine(ServerConfig serverConfig, DatabasePlatform dbPlatform, Binder binder, Map<String, String> asOfTableMapping, Map<String, String> draftTableMap) {
|
||||
this.defaultFetchSizeFindEach = serverConfig.getJdbcFetchSizeFindEach();
|
||||
this.defaultFetchSizeFindList = serverConfig.getJdbcFetchSizeFindList();
|
||||
this.forwardOnlyHintOnFindIterate = dbPlatform.isForwardOnlyHintOnFindIterate();
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, asOfSysPeriod);
|
||||
|
||||
this.historySupport = new CQueryHistorySupport(dbPlatform.getHistorySupport(), asOfTableMapping, serverConfig.getAsOfSysPeriod());
|
||||
this.queryBuilder = new CQueryBuilder(dbPlatform, binder, historySupport, new CQueryDraftSupport(draftTableMap));
|
||||
}
|
||||
|
||||
@@ -90,11 +99,7 @@ public class CQueryEngine {
|
||||
BeanIdList list = rcQuery.findIds();
|
||||
|
||||
if (request.isLogSql()) {
|
||||
String logSql = rcQuery.getGeneratedSql();
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
|
||||
}
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -114,6 +119,14 @@ public class CQueryEngine {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> void logGeneratedSql(OrmQueryRequest<T> request, String sql, String bindLog) {
|
||||
String logSql = sql;
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", bindLog, ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and execute the row count query.
|
||||
*/
|
||||
@@ -125,11 +138,7 @@ public class CQueryEngine {
|
||||
int rowCount = rcQuery.findRowCount();
|
||||
|
||||
if (request.isLogSql()) {
|
||||
String logSql = rcQuery.getGeneratedSql();
|
||||
if (TransactionManager.SQL_LOGGER.isTraceEnabled()) {
|
||||
logSql = Str.add(logSql, "; --bind(", rcQuery.getBindLog(), ")");
|
||||
}
|
||||
request.logSql(logSql);
|
||||
logGeneratedSql(request, rcQuery.getGeneratedSql(), rcQuery.getBindLog());
|
||||
}
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -137,7 +146,6 @@ public class CQueryEngine {
|
||||
}
|
||||
|
||||
if (request.getQuery().isFutureFetch()) {
|
||||
logger.debug("Future findRowCount completed!");
|
||||
request.getTransaction().end();
|
||||
}
|
||||
|
||||
@@ -158,7 +166,9 @@ public class CQueryEngine {
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
try {
|
||||
|
||||
if (defaultFetchSizeFindEach > 0) {
|
||||
request.setDefaultFetchBuffer(defaultFetchSizeFindEach);
|
||||
}
|
||||
if (!cquery.prepareBindExecuteQueryForwardOnly(forwardOnlyHintOnFindIterate)) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
@@ -204,15 +214,16 @@ public class CQueryEngine {
|
||||
|
||||
SpiQuery<T> query = request.getQuery();
|
||||
|
||||
if (query.isVersionsBetween() && !historySupport.isBindAtFromClause()) {
|
||||
String sysPeriodLower = getSysPeriodLower(query);
|
||||
if (query.isVersionsBetween() && !historySupport.isStandardsBased()) {
|
||||
// just add as normal predicates using the lower bound
|
||||
query.where().gt(getSysPeriodLower(query), query.getVersionStart());
|
||||
query.where().lt(getSysPeriodLower(query), query.getVersionEnd());
|
||||
query.where().gt(sysPeriodLower, query.getVersionStart());
|
||||
query.where().lt(sysPeriodLower, query.getVersionEnd());
|
||||
}
|
||||
|
||||
// order by id asc, lower sys period desc
|
||||
query.orderBy().asc(request.getBeanDescriptor().getIdProperty().getName());
|
||||
query.orderBy().desc(getSysPeriodLower(query));
|
||||
query.orderBy().desc(sysPeriodLower);
|
||||
|
||||
CQuery<T> cquery = queryBuilder.buildQuery(request);
|
||||
try {
|
||||
@@ -222,6 +233,9 @@ public class CQueryEngine {
|
||||
}
|
||||
|
||||
List<Version<T>> versions = cquery.readVersions();
|
||||
// just order in memory rather than use NULLS LAST as that
|
||||
// is not universally supported, not expect huge list here
|
||||
Collections.sort(versions, OrderVersionDesc.INSTANCE);
|
||||
deriveVersionDiffs(versions, request);
|
||||
|
||||
if (request.isLogSummary()) {
|
||||
@@ -296,6 +310,9 @@ public class CQueryEngine {
|
||||
request.setCancelableQuery(cquery);
|
||||
|
||||
try {
|
||||
if (defaultFetchSizeFindList > 0) {
|
||||
request.setDefaultFetchBuffer(defaultFetchSizeFindList);
|
||||
}
|
||||
if (!cquery.prepareBindExecuteQuery()) {
|
||||
// query has been cancelled already
|
||||
logger.trace("Future fetch already cancelled");
|
||||
|
||||
@@ -31,11 +31,10 @@ public class CQueryHistorySupport {
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the bind of 'as of' timestamp occurs with the from clause
|
||||
* rather than at the end.
|
||||
* Return true if the underlying history support is standards based.
|
||||
*/
|
||||
public boolean isBindAtFromClause() {
|
||||
return dbHistorySupport.isBindWithFromClause();
|
||||
public boolean isStandardsBased() {
|
||||
return dbHistorySupport.isStandardsBased();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -70,6 +70,8 @@ public class CQueryPlan {
|
||||
|
||||
protected final DataTimeZone dataTimeZone;
|
||||
|
||||
private final int asOfTableCount;
|
||||
|
||||
/**
|
||||
* Key used to identify the query plan in audit logging.
|
||||
*/
|
||||
@@ -86,6 +88,7 @@ public class CQueryPlan {
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.planKey = request.getQueryPlanKey();
|
||||
this.autoTuned = request.getQuery().isAutoTuned();
|
||||
this.asOfTableCount = request.getQuery().getAsOfTableCount();
|
||||
if (sqlRes != null) {
|
||||
this.sql = sqlRes.getSql();
|
||||
this.rowNumberIncluded = sqlRes.isIncludesRowNumberColumn();
|
||||
@@ -111,6 +114,7 @@ public class CQueryPlan {
|
||||
this.stats = new CQueryPlanStats(this, server.isCollectQueryOrigins());
|
||||
this.planKey = buildPlanKey(sql, rawSql, rowNumberIncluded, logWhereSql);
|
||||
this.autoTuned = false;
|
||||
this.asOfTableCount = 0;
|
||||
this.sql = sql;
|
||||
this.sqlTree = sqlTree;
|
||||
this.rawSql = rawSql;
|
||||
@@ -151,6 +155,10 @@ public class CQueryPlan {
|
||||
return dataBind;
|
||||
}
|
||||
|
||||
public int getAsOfTableCount() {
|
||||
return asOfTableCount;
|
||||
}
|
||||
|
||||
public boolean isAutoTuned() {
|
||||
return autoTuned;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ public class CQueryPredicates {
|
||||
updateProperties.bind(binder, dataBind);
|
||||
}
|
||||
|
||||
if (query.isVersionsBetween() && binder.isBindAsOfWithFromClause()) {
|
||||
if (query.isVersionsBetween() && binder.isAsOfStandardsBased()) {
|
||||
// sql2011 based versions between timestamp syntax
|
||||
Timestamp start = query.getVersionStart();
|
||||
Timestamp end = query.getVersionEnd();
|
||||
@@ -136,13 +136,13 @@ public class CQueryPredicates {
|
||||
dataBind.append(", ");
|
||||
}
|
||||
|
||||
List<String> historyTableAlias = query.getAsOfTableAlias();
|
||||
if (historyTableAlias != null && binder.isBindAsOfWithFromClause()) {
|
||||
int asOfTableCount = request.getQueryPlan().getAsOfTableCount();
|
||||
if (asOfTableCount > 0) {
|
||||
// bind the asOf value for each table alias as part of the from/join clauses
|
||||
// there is one effective date predicate per table alias
|
||||
Timestamp asOf = query.getAsOf();
|
||||
dataBind.append("asOf ").append(asOf);
|
||||
for (int i = 0; i < historyTableAlias.size() * binder.getAsOfBindCount(); i++) {
|
||||
for (int i = 0; i < asOfTableCount * binder.getAsOfBindCount(); i++) {
|
||||
binder.bindObject(dataBind, asOf);
|
||||
}
|
||||
dataBind.append(", ");
|
||||
@@ -167,16 +167,6 @@ public class CQueryPredicates {
|
||||
filterMany.bind(dataBind);
|
||||
}
|
||||
|
||||
if (historyTableAlias != null && !binder.isBindAsOfWithFromClause()) {
|
||||
// bind the asOf value for each table alias after all the normal predicates
|
||||
// there is one effective date predicate per table alias
|
||||
Timestamp asOf = query.getAsOf();
|
||||
dataBind.append(" asOf ").append(asOf);
|
||||
for (int i = 0; i < historyTableAlias.size() * binder.getAsOfBindCount(); i++) {
|
||||
binder.bindObject(dataBind, asOf);
|
||||
}
|
||||
}
|
||||
|
||||
if (having != null) {
|
||||
having.bind(dataBind);
|
||||
}
|
||||
@@ -305,7 +295,7 @@ public class CQueryPredicates {
|
||||
}
|
||||
|
||||
private boolean isEmpty(String s) {
|
||||
return s == null || s.length() == 0;
|
||||
return s == null || s.isEmpty();
|
||||
}
|
||||
|
||||
private String parse(String expr, DeployParser deployParser) {
|
||||
|
||||
@@ -106,8 +106,8 @@ public class DefaultDbSqlContext implements DbSqlContext {
|
||||
|
||||
tableJoins.add(joinKey);
|
||||
|
||||
sb.append(" ");
|
||||
sb.append(type);
|
||||
sb.append(" ").append(type);
|
||||
boolean addAsOfOnClause = false;
|
||||
if (draftSupport != null) {
|
||||
appendTable(table, draftSupport.getDraftTable(table));
|
||||
|
||||
@@ -117,32 +117,32 @@ public class DefaultDbSqlContext implements DbSqlContext {
|
||||
} else {
|
||||
// check if there is an associated history table and if so
|
||||
// use the unionAll view - we expect an additional predicate to match
|
||||
appendTable(table, historySupport.getAsOfView(table));
|
||||
String asOfView = historySupport.getAsOfView(table);
|
||||
appendTable(table, asOfView);
|
||||
if (asOfView != null) {
|
||||
addAsOfOnClause = !historySupport.isStandardsBased();
|
||||
}
|
||||
}
|
||||
|
||||
sb.append(a2);
|
||||
sb.append(" on ");
|
||||
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
TableJoinColumn pair = cols[i];
|
||||
if (i > 0) {
|
||||
sb.append(" and ");
|
||||
}
|
||||
|
||||
sb.append(a2);
|
||||
sb.append(".").append(pair.getForeignDbColumn());
|
||||
sb.append(a2).append(".").append(pair.getForeignDbColumn());
|
||||
sb.append(" = ");
|
||||
sb.append(a1);
|
||||
sb.append(".").append(pair.getLocalDbColumn());
|
||||
sb.append(a1).append(".").append(pair.getLocalDbColumn());
|
||||
}
|
||||
|
||||
|
||||
// add on any inheritance where clause
|
||||
if (inheritance != null && inheritance.length() > 0) {
|
||||
sb.append(" and ");
|
||||
sb.append(a2);
|
||||
sb.append(".");
|
||||
sb.append(inheritance);
|
||||
if (inheritance != null && !inheritance.isEmpty()) {
|
||||
sb.append(" and ").append(a2).append(".").append(inheritance);
|
||||
}
|
||||
|
||||
if (addAsOfOnClause) {
|
||||
sb.append(" and ").append(historySupport.getAsOfPredicate(a2));
|
||||
}
|
||||
|
||||
sb.append(" ");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebean.Version;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Compare Version beans in descending order with nulls last.
|
||||
*/
|
||||
class OrderVersionDesc implements Comparator<Version<?>> {
|
||||
|
||||
static final OrderVersionDesc INSTANCE = new OrderVersionDesc();
|
||||
|
||||
@Override
|
||||
public int compare(Version<?> o1, Version<?> o2) {
|
||||
|
||||
Timestamp v1 = o1.getStart();
|
||||
if (v1 == null) {
|
||||
return 1;
|
||||
}
|
||||
Timestamp v2 = o2.getStart();
|
||||
if (v2 == null) {
|
||||
return -1;
|
||||
}
|
||||
return v1.compareTo(v2) * -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,9 +1,15 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
/**
|
||||
* Helper for dot notation property paths.
|
||||
*/
|
||||
public class SplitName {
|
||||
|
||||
private static final char PERIOD = '.';
|
||||
|
||||
/**
|
||||
* Add the two name sections together in dot notation.
|
||||
*/
|
||||
public static String add(String prefix, String name) {
|
||||
if (prefix != null) {
|
||||
return prefix + "." + name;
|
||||
@@ -38,10 +44,20 @@ public class SplitName {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name split by last.
|
||||
*/
|
||||
public static String[] split(String name) {
|
||||
return split(name, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first part of the name.
|
||||
*/
|
||||
public static String begin(String name) {
|
||||
return splitBegin(name)[0];
|
||||
}
|
||||
|
||||
public static String[] splitBegin(String name) {
|
||||
return split(name, false);
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ public class SqlTreeBuilder {
|
||||
this.queryDetail = query.getDetail();
|
||||
|
||||
this.predicates = predicates;
|
||||
this.alias = new SqlTreeAlias(request.getQuery().getAlias() == null ? request.getBeanDescriptor().getBaseTableAlias() : request.getQuery().getAlias());
|
||||
this.alias = new SqlTreeAlias(request.getBaseTableAlias());
|
||||
this.ctx = new DefaultDbSqlContext(alias, tableAliasPlaceHolder, columnAliasPrefix, !subQuery, historySupport, draftSupport);
|
||||
}
|
||||
|
||||
@@ -417,7 +417,7 @@ public class SqlTreeBuilder {
|
||||
// This makes sense for transient properties used to
|
||||
// hold sum() count() type values (with SqlSelect)
|
||||
for (String propName : queryProps.getSelectProperties()) {
|
||||
if (propName.length() > 0) {
|
||||
if (!propName.isEmpty()) {
|
||||
addProperty(selectProps, desc, queryProps, propName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
* Table alias set if this bean node includes a join to a intersection
|
||||
* table and that table has history support.
|
||||
*/
|
||||
protected String intersectionAsOfTableAlias;
|
||||
private boolean intersectionAsOfTableAlias;
|
||||
|
||||
/**
|
||||
* Construct for Raw SQL.
|
||||
@@ -501,11 +501,10 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
// if history on this bean type add it's alias
|
||||
// for each alias we add an effect date predicate
|
||||
if (desc.isHistorySupport()) {
|
||||
query.addAsOfTableAlias(baseTableAlias);
|
||||
query.incrementAsOfTableCount();
|
||||
}
|
||||
if (intersectionAsOfTableAlias != null) {
|
||||
// adds the 'as of' predicate for this intersection table
|
||||
query.addAsOfTableAlias(intersectionAsOfTableAlias);
|
||||
if (intersectionAsOfTableAlias) {
|
||||
query.incrementAsOfTableCount();
|
||||
}
|
||||
for (int i = 0; i < children.length; i++) {
|
||||
children[i].addAsOfTableAlias(query);
|
||||
@@ -531,7 +530,7 @@ public class SqlTreeNodeBean implements SqlTreeNode {
|
||||
TableJoin manyToManyJoin = manyProp.getIntersectionTableJoin();
|
||||
manyToManyJoin.addJoin(joinType, parentAlias, alias2, ctx);
|
||||
if (!manyProp.isExcludedFromHistory()) {
|
||||
intersectionAsOfTableAlias = alias2;
|
||||
intersectionAsOfTableAlias = true;
|
||||
}
|
||||
|
||||
return nodeBeanProp.addJoin(joinType, alias2, alias, ctx);
|
||||
|
||||
@@ -144,10 +144,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
private DefaultExpressionList<T> havingExpressions;
|
||||
|
||||
/**
|
||||
* The list of table alias associated with @History entity beans.
|
||||
*/
|
||||
private List<String> asOfTableAlias;
|
||||
private int asOfTableCount;
|
||||
|
||||
/**
|
||||
* Set for flashback style 'as of' query.
|
||||
@@ -236,6 +233,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return beanDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkIdEqualTo() {
|
||||
if (id == null && whereExpressions != null) {
|
||||
id = whereExpressions.idEqualTo(beanDescriptor.getIdName());
|
||||
if (id != null) {
|
||||
whereExpressions = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoTunable() {
|
||||
return beanDescriptor.isAutoTunable();
|
||||
@@ -271,21 +278,14 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
return softDeletePredicates;
|
||||
}
|
||||
|
||||
/**
|
||||
* This table alias is for a @History entity involved in the query and as
|
||||
* such we need to add a 'as of predicate' to the query using this alias.
|
||||
*/
|
||||
@Override
|
||||
public void addAsOfTableAlias(String tableAlias) {
|
||||
if (asOfTableAlias == null) {
|
||||
asOfTableAlias = new ArrayList<String>();
|
||||
}
|
||||
asOfTableAlias.add(tableAlias);
|
||||
public void incrementAsOfTableCount() {
|
||||
asOfTableCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getAsOfTableAlias() {
|
||||
return asOfTableAlias;
|
||||
public int getAsOfTableCount() {
|
||||
return asOfTableCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -484,6 +484,16 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareDocNested() {
|
||||
if (textExpressions != null) {
|
||||
textExpressions.prepareDocNested(beanDescriptor);
|
||||
}
|
||||
if (whereExpressions != null) {
|
||||
whereExpressions.prepareDocNested(beanDescriptor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to be a delete query.
|
||||
*/
|
||||
@@ -1151,7 +1161,7 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public DefaultOrmQuery<T> order(String orderByClause) {
|
||||
if (orderByClause == null || orderByClause.trim().length() == 0) {
|
||||
if (orderByClause == null || orderByClause.trim().isEmpty()) {
|
||||
this.orderBy = null;
|
||||
} else {
|
||||
this.orderBy = new OrderBy<T>(this, orderByClause);
|
||||
@@ -1356,6 +1366,13 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
this.generatedSql = generatedSql;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultFetchBuffer(int fetchSize) {
|
||||
if (bufferFetchSizeHint == 0) {
|
||||
bufferFetchSizeHint = fetchSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Query<T> setBufferFetchSizeHint(int bufferFetchSizeHint) {
|
||||
this.bufferFetchSizeHint = bufferFetchSizeHint;
|
||||
|
||||
@@ -134,7 +134,7 @@ public class OrmQueryDetailParser {
|
||||
}
|
||||
}
|
||||
String whereClause = sb.toString().trim();
|
||||
if (whereClause.length() > 0) {
|
||||
if (!whereClause.isEmpty()) {
|
||||
rawWhereClause = whereClause;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ public class OrmQueryProperties implements Serializable {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void configureBeanQuery(SpiQuery<?> query) {
|
||||
|
||||
if (trimmedProperties != null && trimmedProperties.length() > 0) {
|
||||
if (trimmedProperties != null && !trimmedProperties.isEmpty()) {
|
||||
query.select(trimmedProperties);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -122,7 +122,7 @@ public class OrmQueryPropertiesParser {
|
||||
String temp;
|
||||
for (int i = 0; i < res.length; i++) {
|
||||
temp = res[i].trim();
|
||||
if (temp.length() > 0) {
|
||||
if (!temp.isEmpty()) {
|
||||
if (count > 0) {
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ public class OrmUpdateProperties {
|
||||
@Override
|
||||
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
||||
binder.bindObject(dataBind, value);
|
||||
dataBind.append(value).append(",");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +106,7 @@ public class OrmUpdateProperties {
|
||||
public void bind(Binder binder, DataBind dataBind) throws SQLException {
|
||||
for (Object val : bindValues) {
|
||||
binder.bindObject(dataBind, val);
|
||||
dataBind.append(val).append(",");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,7 +268,7 @@ public class TCsvReader<T> implements CsvReader<T> {
|
||||
|
||||
strValue = strValue.trim();
|
||||
|
||||
if (strValue.length() == 0) {
|
||||
if (strValue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -402,12 +402,7 @@ public class TransactionManager {
|
||||
public void notifyOfCommit(SpiTransaction transaction) {
|
||||
|
||||
try {
|
||||
|
||||
if (transaction.isExplicit()) {
|
||||
if (TXN_LOGGER.isInfoEnabled()) {
|
||||
TXN_LOGGER.info(transaction.getLogPrefix() + "Commit");
|
||||
}
|
||||
} else if (TXN_LOGGER.isDebugEnabled()) {
|
||||
if (TXN_LOGGER.isDebugEnabled()) {
|
||||
TXN_LOGGER.debug(transaction.getLogPrefix() + "Commit");
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public class ScalarTypeChar extends ScalarTypeBaseVarchar<Character> {
|
||||
|
||||
public Character read(DataReader dataReader) throws SQLException {
|
||||
String string = dataReader.getString();
|
||||
if (string == null || string.length() == 0) {
|
||||
if (string == null || string.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
return string.charAt(0);
|
||||
|
||||
@@ -86,7 +86,7 @@ public class BindParamsParser {
|
||||
|
||||
if (params.isSameBindHash()) {
|
||||
String preparedSql = params.getPreparedSql();
|
||||
if (preparedSql != null && preparedSql.length() > 0) {
|
||||
if (preparedSql != null && !preparedSql.isEmpty()) {
|
||||
// the sql has already been parsed and positionedParameters are set in order
|
||||
return preparedSql;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public final class SortByClauseParser {
|
||||
}
|
||||
|
||||
private Property parseSection(String section) {
|
||||
if (section.length() == 0) {
|
||||
if (section.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String[] words = section.split(" ");
|
||||
|
||||
+1
-1
@@ -321,7 +321,7 @@ public abstract class DocStoreBeanBaseAdapter<T> implements DocStoreBeanAdapter<
|
||||
* Return the supplied value or default to the bean name lower case.
|
||||
*/
|
||||
protected String derive(BeanType<?> desc, String suppliedValue) {
|
||||
return (suppliedValue != null && suppliedValue.length() > 0) ? suppliedValue : desc.getName().toLowerCase();
|
||||
return (suppliedValue != null && !suppliedValue.isEmpty()) ? suppliedValue : desc.getName().toLowerCase();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,6 +30,6 @@ public class PrimaryServerTest {
|
||||
public void testLoadProperties() throws Exception {
|
||||
|
||||
Properties properties = PrimaryServer.getProperties();
|
||||
assertTrue(properties.size() > 0);
|
||||
assertTrue(!properties.isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.avaje.ebean;
|
||||
|
||||
import com.avaje.ebean.config.PersistBatch;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TxScopeTest {
|
||||
|
||||
@Test
|
||||
public void checkBatchMode_when_bothNull() throws Exception {
|
||||
|
||||
TxScope scope = new TxScope();
|
||||
scope.setBatchSize(100);
|
||||
|
||||
assertNull(scope.getBatch());
|
||||
assertNull(scope.getBatchOnCascade());
|
||||
|
||||
scope.checkBatchMode();
|
||||
assertEquals(scope.getBatch(), PersistBatch.ALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBatchMode_when_bothInherit() throws Exception {
|
||||
|
||||
TxScope scope = new TxScope();
|
||||
scope.setBatchSize(100);
|
||||
scope.setBatch(PersistBatch.INHERIT);
|
||||
scope.setBatchOnCascade(PersistBatch.INHERIT);
|
||||
|
||||
scope.checkBatchMode();
|
||||
assertEquals(scope.getBatch(), PersistBatch.ALL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBatchMode_when_batchSizeZero_and_onCascadeInherit() throws Exception {
|
||||
|
||||
TxScope scope = new TxScope();
|
||||
scope.setBatchOnCascade(PersistBatch.INHERIT);
|
||||
|
||||
scope.checkBatchMode();
|
||||
assertNull(scope.getBatch());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBatchMode_when_batchSizeZero_and_bothInherit() throws Exception {
|
||||
|
||||
TxScope scope = new TxScope();
|
||||
scope.setBatch(PersistBatch.INHERIT);
|
||||
scope.setBatchOnCascade(PersistBatch.INHERIT);
|
||||
|
||||
scope.checkBatchMode();
|
||||
assertEquals(scope.getBatch(), PersistBatch.INHERIT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkBatchMode_when_onCascadeSet() throws Exception {
|
||||
|
||||
TxScope scope = new TxScope();
|
||||
scope.setBatchSize(100);
|
||||
scope.setBatchOnCascade(PersistBatch.INSERT);
|
||||
|
||||
scope.checkBatchMode();
|
||||
assertNull(scope.getBatch());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,12 +32,16 @@ public class ServerConfigTest {
|
||||
props.setProperty("persistBatch", "INSERT");
|
||||
props.setProperty("persistBatchOnCascade", "INSERT");
|
||||
props.setProperty("dbuuid","binary");
|
||||
props.setProperty("jdbcFetchSizeFindEach", "42");
|
||||
props.setProperty("jdbcFetchSizeFindList", "43");
|
||||
|
||||
serverConfig.loadFromProperties(props);
|
||||
|
||||
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatch());
|
||||
assertEquals(PersistBatch.INSERT, serverConfig.getPersistBatchOnCascade());
|
||||
assertEquals(ServerConfig.DbUuid.BINARY, serverConfig.getDbUuid());
|
||||
assertEquals(42, serverConfig.getJdbcFetchSizeFindEach());
|
||||
assertEquals(43, serverConfig.getJdbcFetchSizeFindList());
|
||||
|
||||
serverConfig.setPersistBatch(PersistBatch.NONE);
|
||||
serverConfig.setPersistBatchOnCascade(PersistBatch.NONE);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class MySqlHistorySupportTest {
|
||||
|
||||
private MySqlHistorySupport support = new MySqlHistorySupport();
|
||||
|
||||
@Test
|
||||
public void getAsOfPredicate() {
|
||||
|
||||
String asOfPredicate = support.getAsOfPredicate("t0", "sys_period");
|
||||
assertEquals(asOfPredicate, "(t0.sys_period_start <= ? and (t0.sys_period_end is null or t0.sys_period_end > ?))");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLower() throws Exception {
|
||||
|
||||
String lower = support.getSysPeriodLower("t0", "sys_period");
|
||||
assertEquals(lower, "t0.sys_period_start");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getUpper() throws Exception {
|
||||
|
||||
String upper = support.getSysPeriodUpper("t0", "sys_period");
|
||||
assertEquals(upper, "t0.sys_period_end");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.avaje.ebean.config.dbplatform;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class PostgresHistorySupportTest {
|
||||
|
||||
private PostgresHistorySupport support = new PostgresHistorySupport();
|
||||
|
||||
@Test
|
||||
public void getBindCount() throws Exception {
|
||||
|
||||
assertEquals(support.getBindCount(), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAsOfPredicate() throws Exception {
|
||||
|
||||
String asOfPredicate = support.getAsOfPredicate("t0", "sys_period");
|
||||
assertEquals(asOfPredicate, "t0.sys_period @> ?::timestamptz");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSysPeriodLower() throws Exception {
|
||||
|
||||
String lower = support.getSysPeriodLower("t0", "sys_period");
|
||||
assertEquals(lower, "lower(t0.sys_period)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSysPeriodUpper() throws Exception {
|
||||
|
||||
String upper = support.getSysPeriodUpper("t0", "sys_period");
|
||||
assertEquals(upper, "upper(t0.sys_period)");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.Expr;
|
||||
import com.avaje.ebean.Expression;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -75,4 +76,54 @@ public class LogicExpressionTest extends BaseExpressionTest {
|
||||
assertThat(and(eq("a", 10), eq("b", 10))
|
||||
.isSameByBind(and(eq("a", 10), eq("c", 20)))).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedPath_when_notNested() {
|
||||
|
||||
LogicExpression and = and(eq("orderDate", 10), eq("shipDate", 10));
|
||||
|
||||
and.nestedPath(getBeanDescriptor(Order.class));
|
||||
|
||||
assertThat(and.expOne).isInstanceOf(SimpleExpression.class);
|
||||
assertThat(and.expTwo).isInstanceOf(SimpleExpression.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedPath_when_nestedSame() {
|
||||
|
||||
LogicExpression and = and(eq("details.orderQty", 10), eq("details.unitPrice", 10));
|
||||
|
||||
String path = and.nestedPath(getBeanDescriptor(Order.class));
|
||||
|
||||
assertThat(path).isEqualTo("details");
|
||||
assertThat(and.expOne).isInstanceOf(SimpleExpression.class);
|
||||
assertThat(and.expTwo).isInstanceOf(SimpleExpression.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedPath_when_nestedDifferent() {
|
||||
|
||||
LogicExpression and = and(eq("details.orderQty", 10), eq("shipments.shipTime", 10));
|
||||
|
||||
String path = and.nestedPath(getBeanDescriptor(Order.class));
|
||||
|
||||
assertThat(path).isNull();
|
||||
assertThat(and.expOne).isInstanceOf(NestedPathWrapperExpression.class);
|
||||
assertThat(((NestedPathWrapperExpression)and.expOne).nestedPath).isEqualTo("details");
|
||||
assertThat(and.expTwo).isInstanceOf(NestedPathWrapperExpression.class);
|
||||
assertThat(((NestedPathWrapperExpression)and.expTwo).nestedPath).isEqualTo("shipments");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedPath_when_oneNested() {
|
||||
|
||||
LogicExpression and = and(eq("details.orderQty", 10), eq("orderDate", 10));
|
||||
|
||||
String path = and.nestedPath(getBeanDescriptor(Order.class));
|
||||
|
||||
assertThat(path).isNull();
|
||||
assertThat(and.expOne).isInstanceOf(NestedPathWrapperExpression.class);
|
||||
assertThat(((NestedPathWrapperExpression)and.expOne).nestedPath).isEqualTo("details");
|
||||
assertThat(and.expTwo).isInstanceOf(SimpleExpression.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package com.avaje.ebeaninternal.server.expression;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.ExpressionList;
|
||||
import com.avaje.ebeaninternal.api.SpiExpression;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
public class PrepareDocNestedTest extends BaseTestCase {
|
||||
@Test
|
||||
public void prepare() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.gt("details.orderQty", 1)
|
||||
.query().where();
|
||||
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 1);
|
||||
assertEquals(exp.allDocNestedPath, "details");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prepare_when_multipleOfSamePath() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.gt("details.orderQty", 1)
|
||||
.gt("details.unitPrice", 1)
|
||||
.query().where();
|
||||
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 2);
|
||||
assertEquals(exp.allDocNestedPath, "details");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prepare_when_mixed() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.gt("customer.id", 1)
|
||||
.gt("details.orderQty", 1)
|
||||
.gt("details.unitPrice", 1)
|
||||
.query().where();
|
||||
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 2);
|
||||
assertNull(exp.allDocNestedPath);
|
||||
|
||||
DefaultExpressionList<?> second = (DefaultExpressionList<?>)underlyingList.get(1);
|
||||
assertEquals(second.allDocNestedPath, "details");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prepare_when_nestedJunction() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.not()
|
||||
.gt("customer.id", 1)
|
||||
.gt("details.orderQty", 1)
|
||||
.gt("details.unitPrice", 1)
|
||||
.query().where();
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 1);
|
||||
assertNull(exp.allDocNestedPath);
|
||||
|
||||
JunctionExpression<?> junction = (JunctionExpression<?>)underlyingList.get(0);
|
||||
List<SpiExpression> junctionUnderlying = junction.exprList.getUnderlyingList();
|
||||
JunctionExpression<?> nestedNestedPath = (JunctionExpression)junctionUnderlying.get(1);
|
||||
assertEquals(nestedNestedPath.exprList.allDocNestedPath, "details");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void prepare_when_nestedMultiple() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.isNotNull("shipments.shipTime")
|
||||
.gt("details.orderQty", 1)
|
||||
.gt("details.unitPrice", 1)
|
||||
.query().where();
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 2);
|
||||
assertNull(exp.allDocNestedPath);
|
||||
|
||||
DefaultExpressionList<?> shipExpr = (DefaultExpressionList<?>)underlyingList.get(0);
|
||||
assertEquals(shipExpr.allDocNestedPath, "shipments");
|
||||
|
||||
DefaultExpressionList<?> detailsExpr = (DefaultExpressionList<?>)underlyingList.get(1);
|
||||
assertEquals(detailsExpr.allDocNestedPath, "details");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void prepare_when_manyMixed() throws Exception {
|
||||
|
||||
ExpressionList<Order> where = Ebean.find(Order.class)
|
||||
.where()
|
||||
.gt("customer.id", 1) // 0
|
||||
.isNotNull("shipments.shipTime") // shipments 0
|
||||
.isNotNull("status") // 1
|
||||
.gt("details.orderQty", 1) // details 0
|
||||
.isNotNull("orderDate") // 2
|
||||
.gt("details.unitPrice", 1) // details 1
|
||||
.query().where();
|
||||
|
||||
DefaultExpressionList<?> exp = (DefaultExpressionList<?>)where;
|
||||
PrepareDocNested.prepare(exp, getBeanDescriptor(Order.class));
|
||||
|
||||
List<SpiExpression> underlyingList = exp.getUnderlyingList();
|
||||
assertEquals(underlyingList.size(), 5);
|
||||
assertNull(exp.allDocNestedPath);
|
||||
|
||||
DefaultExpressionList<?> shipExpr = (DefaultExpressionList<?>)underlyingList.get(3);
|
||||
assertEquals(shipExpr.allDocNestedPath, "shipments");
|
||||
|
||||
DefaultExpressionList<?> detailsExpr = (DefaultExpressionList<?>)underlyingList.get(4);
|
||||
assertEquals(detailsExpr.allDocNestedPath, "details");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import com.avaje.ebean.Version;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class OrderVersionDescTest {
|
||||
|
||||
private final long now = System.currentTimeMillis();
|
||||
|
||||
@Test
|
||||
public void sort() {
|
||||
|
||||
Version<?> atNull = atNull();
|
||||
Version<?> at100 = at(100);
|
||||
Version<?> at200 = at(200);
|
||||
Version<?> at300 = at(300);
|
||||
|
||||
List<Version<?>> versions = new ArrayList<Version<?>>();
|
||||
versions.add(at200);
|
||||
versions.add(atNull);
|
||||
versions.add(at300);
|
||||
versions.add(at100);
|
||||
|
||||
Collections.sort(versions, OrderVersionDesc.INSTANCE);
|
||||
|
||||
assertThat(versions.get(0)).isSameAs(at300);
|
||||
assertThat(versions.get(1)).isSameAs(at200);
|
||||
assertThat(versions.get(2)).isSameAs(at100);
|
||||
assertThat(versions.get(3)).isSameAs(atNull);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compare_lt() {
|
||||
|
||||
assertEquals(OrderVersionDesc.INSTANCE.compare(at(0), at(1)), 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compare_gt() {
|
||||
|
||||
assertEquals(OrderVersionDesc.INSTANCE.compare(at(2), at(1)), -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compare_eq() {
|
||||
|
||||
assertEquals(OrderVersionDesc.INSTANCE.compare(at(1), at(1)), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compare_nullFirst() {
|
||||
|
||||
assertEquals(OrderVersionDesc.INSTANCE.compare(atNull(), at(1)), 1);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void compare_nullLast() {
|
||||
|
||||
assertEquals(OrderVersionDesc.INSTANCE.compare(at(0), atNull()), -1);
|
||||
}
|
||||
|
||||
private Version<?> atNull() {
|
||||
return new Version();
|
||||
}
|
||||
|
||||
private Version at(long diff) {
|
||||
Timestamp timestamp = new Timestamp(now + diff);
|
||||
Version ver = new Version();
|
||||
ver.setStart(timestamp);
|
||||
return ver;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.avaje.ebeaninternal.server.query;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class SplitNameTest {
|
||||
|
||||
@Test
|
||||
public void add() throws Exception {
|
||||
|
||||
assertEquals(SplitName.add("a","b"), "a.b");
|
||||
assertEquals(SplitName.add("a","b.c"), "a.b.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void count() throws Exception {
|
||||
|
||||
assertEquals(SplitName.count("a"), 0);
|
||||
assertEquals(SplitName.count("a.b"), 1);
|
||||
assertEquals(SplitName.count("a.b.c"), 2);
|
||||
assertEquals(SplitName.count("a.b.c.foo"), 3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parent() throws Exception {
|
||||
assertNull(SplitName.parent("a"));
|
||||
assertEquals(SplitName.parent("a.b"), "a");
|
||||
assertEquals(SplitName.parent("a.b.c"), "a.b");
|
||||
assertNull(SplitName.parent(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void split() throws Exception {
|
||||
|
||||
String[] split = SplitName.split("a.b.c");
|
||||
assertEquals(split[0], "a.b");
|
||||
assertEquals(split[1], "c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void begin_when_one() throws Exception {
|
||||
|
||||
assertEquals(SplitName.begin("a"), "a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void begin_when_both() throws Exception {
|
||||
|
||||
assertEquals(SplitName.begin("a.b"), "a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void begin_when_multi() throws Exception {
|
||||
|
||||
assertEquals(SplitName.begin("a.b.c"), "a");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitBegin_when_both() throws Exception {
|
||||
|
||||
String[] split = SplitName.splitBegin("a.b");
|
||||
assertEquals(split[0], "a");
|
||||
assertEquals(split[1], "b");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitBegin_when_bothPlus() throws Exception {
|
||||
|
||||
String[] split = SplitName.splitBegin("a.b.c");
|
||||
assertEquals(split[0], "a");
|
||||
assertEquals(split[1], "b.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void splitBegin_when_one() throws Exception {
|
||||
|
||||
String[] split = SplitName.splitBegin("a");
|
||||
assertEquals(split[0], "a");
|
||||
assertNull(split[1]);
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.avaje.ebeaninternal.server.querydefn;
|
||||
|
||||
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.FetchConfig;
|
||||
import com.avaje.tests.model.basic.Order;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -10,6 +9,28 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class DefaultOrmQueryTest {
|
||||
|
||||
@Test
|
||||
public void checkForId_when_eqId_then_translatedTo_setId() {
|
||||
|
||||
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().eq("id", 42).query();
|
||||
assertThat(q1.getWhereExpressions()).isNotNull();
|
||||
assertThat(q1.getId()).isNull();
|
||||
|
||||
q1.checkIdEqualTo();
|
||||
|
||||
assertThat(q1.getId()).isEqualTo(42);
|
||||
assertThat(q1.getWhereExpressions()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkForId_when_idEq_ok() {
|
||||
|
||||
DefaultOrmQuery<Order> q1 = (DefaultOrmQuery<Order>)Ebean.find(Order.class).where().idEq(42).query();
|
||||
assertThat(q1.getId()).isEqualTo(42);
|
||||
q1.checkIdEqualTo();
|
||||
assertThat(q1.getId()).isEqualTo(42);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void when_addWhere_then_planChanges() {
|
||||
|
||||
|
||||
@@ -41,6 +41,6 @@ public class TestFetchId extends BaseTestCase {
|
||||
List<Object> idList = futureIds.get();
|
||||
Assert.assertTrue("same instance", partial == idList);
|
||||
|
||||
Assert.assertTrue("sz > 0", ids.size() > 0);
|
||||
Assert.assertTrue("sz > 0", !ids.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class TestInheritRef extends BaseTestCase {
|
||||
.setAutoTune(false)
|
||||
.findList();
|
||||
|
||||
Assert.assertTrue(list.size() > 0);
|
||||
Assert.assertTrue(!list.isEmpty());
|
||||
|
||||
Truck foundTruck = null;
|
||||
int found = 0;
|
||||
|
||||
@@ -29,7 +29,7 @@ public class TestLazyLoadInCache extends BaseTestCase {
|
||||
.orderBy().asc("id")
|
||||
.findMap();
|
||||
|
||||
assertTrue(map.size() > 0);
|
||||
assertTrue(!map.isEmpty());
|
||||
|
||||
Object id = map.keySet().iterator().next();
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ public class TestLimitQuery extends BaseTestCase {
|
||||
|
||||
List<Order> list = query.findList();
|
||||
|
||||
Assert.assertTrue("sz > 0", list.size() > 0);
|
||||
Assert.assertTrue("sz > 0", !list.isEmpty());
|
||||
|
||||
String sql = query.getGeneratedSql();
|
||||
boolean hasDetailsJoin = sql.contains("join o_order_detail");
|
||||
|
||||
@@ -76,7 +76,7 @@ public class TestM2MVanilla extends BaseTestCase {
|
||||
Query<MUser> rolesQuery = Ebean.find(MUser.class).where().in("roles", roleList).query();
|
||||
|
||||
List<MUser> userInRolesList = rolesQuery.findList();
|
||||
Assert.assertTrue(userInRolesList.size() > 0);
|
||||
Assert.assertTrue(!userInRolesList.isEmpty());
|
||||
|
||||
List<MUser> list = Ebean.find(MUser.class)
|
||||
.where().in("roles", roleList)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user