diff --git a/ebean-api/src/main/java/io/ebean/Pairs.java b/ebean-api/src/main/java/io/ebean/Pairs.java index bd5ee5137..a6847bf1e 100644 --- a/ebean-api/src/main/java/io/ebean/Pairs.java +++ b/ebean-api/src/main/java/io/ebean/Pairs.java @@ -3,6 +3,7 @@ package io.ebean; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Objects; /** * Holds a list of value object pairs. @@ -62,15 +63,14 @@ import java.util.List; *

*
{@code sql
  *
- *   create index ix_name on table_name ((sku || '-' || code));
+ *   create index ix_name on table_name (sku || '-' || code);
  *
  * }
*/ -public class Pairs { +public final class Pairs { private final String property0; private final String property1; - private final List entries = new ArrayList<>(); /** @@ -139,11 +139,19 @@ public class Pairs { /** * Set the separator character used with DB varchar concatenation to combine the 2 values. */ - public Pairs setConcatSeparator(String concatSeparator) { + public Pairs concatSeparator(String concatSeparator) { this.concatSeparator = concatSeparator; return this; } + /** + * Deprecated migrate to concatSeparator() + */ + @Deprecated + public Pairs setConcatSeparator(String concatSeparator) { + return concatSeparator(concatSeparator); + } + /** * Return a suffix used with DB varchar concatenation to combine the 2 values. */ @@ -154,11 +162,19 @@ public class Pairs { /** * Add a suffix used with DB varchar concatenation to combine the 2 values. */ - public Pairs setConcatSuffix(String concatSuffix) { + public Pairs concatSuffix(String concatSuffix) { this.concatSuffix = concatSuffix; return this; } + /** + * Deprecated migrate to concatSuffix() + */ + @Deprecated + public Pairs setConcatSuffix(String concatSuffix) { + return concatSuffix(concatSuffix); + } + @Override public String toString() { return "p0:" + property0 + " p1:" + property1 + " entries:" + entries; @@ -208,16 +224,13 @@ public class Pairs { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - Entry that = (Entry) o; return a.equals(that.a) && b.equals(that.b); } @Override public int hashCode() { - int result = a.hashCode(); - result = 92821 * result + b.hashCode(); - return result; + return Objects.hash(a, b); } } } diff --git a/ebean-api/src/main/java/io/ebean/config/QueryPlanCapture.java b/ebean-api/src/main/java/io/ebean/config/QueryPlanCapture.java index 6f34097fe..13f0a1ed2 100644 --- a/ebean-api/src/main/java/io/ebean/config/QueryPlanCapture.java +++ b/ebean-api/src/main/java/io/ebean/config/QueryPlanCapture.java @@ -21,6 +21,14 @@ public class QueryPlanCapture { /** * Return the database the plans were captured for. */ + public Database database() { + return database; + } + + /** + * Deprecated migrate to database(). + */ + @Deprecated public Database getDatabase() { return database; } @@ -28,6 +36,14 @@ public class QueryPlanCapture { /** * Return the captured query plans. */ + public List plans() { + return plans; + } + + /** + * Deprecated migrate to plans(). + */ + @Deprecated public List getPlans() { return plans; } diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java index 5a6ae2217..3f2e97893 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java @@ -81,6 +81,11 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod */ ID_LIST(FIND_ID_LIST, "findIds"), + /** + * Find exists. + */ + EXISTS(FIND_EXISTS, "exists"), + /** * Find single attribute. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java b/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java index 231d38296..c4d1ea0be 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java @@ -26,6 +26,7 @@ public interface TxnProfileEventCodes { String FIND_MANY = "fm"; String FIND_ITERATE = "fe"; String FIND_ID_LIST = "fi"; + String FIND_EXISTS = "ex"; String FIND_ATTRIBUTE = "fa"; String FIND_COUNT = "fc"; String FIND_SUBQUERY = "fs"; diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultQueryPlanListener.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultQueryPlanListener.java index 5a6196230..f748e7f2b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultQueryPlanListener.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultQueryPlanListener.java @@ -15,8 +15,8 @@ final class DefaultQueryPlanListener implements QueryPlanListener { @Override public void process(QueryPlanCapture capture) { // better to log this in JSON form? - String dbName = capture.getDatabase().name(); - for (MetaQueryPlan plan : capture.getPlans()) { + String dbName = capture.database().name(); + for (MetaQueryPlan plan : capture.plans()) { log.info("queryPlan db:{} label:{} queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}", dbName, plan.label(), plan.queryTimeMicros(), plan.profileLocation(), plan.sql(), plan.bind(), plan.plan()); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java index 0e293d37d..439f888a9 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java @@ -388,6 +388,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { if (dbSchema != null) { migrationRunner.setDefaultDbSchema(dbSchema); } + migrationRunner.setName(config.getName()); migrationRunner.setPlatform(config.getDatabasePlatform().getPlatform().base().name().toLowerCase()); migrationRunner.loadProperties(config.getProperties()); migrationRunner.run(config.getDataSource()); @@ -1296,7 +1297,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { @Override public boolean exists(Query ormQuery, Transaction transaction) { Query ormQueryCopy = ormQuery.copy().setMaxRows(1); - SpiOrmQueryRequest request = createQueryRequest(Type.ID_LIST, ormQueryCopy, transaction); + SpiOrmQueryRequest request = createQueryRequest(Type.EXISTS, ormQueryCopy, transaction); + List ids = request.getFromQueryCache(); + if (ids != null) { + return !ids.isEmpty(); + } + try { request.initTransIfRequired(); return !request.findIds().isEmpty(); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocOne.java b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocOne.java index f8f1c73c7..ad28e75bd 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocOne.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/deploy/BeanPropertyAssocOne.java @@ -545,6 +545,13 @@ public class BeanPropertyAssocOne extends BeanPropertyAssoc implements STr return importedId; } + /** + * Find and return a matching imported id property. + */ + public BeanProperty findMatchImport(String dbCol) { + return importedId.findMatchImport(dbCol); + } + private String deriveWhereParentIdSql(boolean inClause) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < exportedProperties.length; i++) { diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/logger/DSpiLogger.java b/ebean-core/src/main/java/io/ebeaninternal/server/logger/DSpiLogger.java index e921d5aa3..7c59031ae 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/logger/DSpiLogger.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/logger/DSpiLogger.java @@ -3,11 +3,11 @@ package io.ebeaninternal.server.logger; import io.ebeaninternal.api.SpiLogger; import org.slf4j.Logger; -public final class DSpiLogger implements SpiLogger { +final class DSpiLogger implements SpiLogger { private final Logger logger; - public DSpiLogger(Logger logger) { + DSpiLogger(Logger logger) { this.logger = logger; } diff --git a/ebean-ddl-generator/pom.xml b/ebean-ddl-generator/pom.xml index b5340367f..212965d45 100644 --- a/ebean-ddl-generator/pom.xml +++ b/ebean-ddl-generator/pom.xml @@ -23,7 +23,7 @@ io.ebean ebean-migration - 12.11.0 + 12.11.1 diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java index 4018b0fab..978aa4320 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/ddlgeneration/platform/SqlServerDdl.java @@ -5,7 +5,6 @@ import io.ebean.config.dbplatform.DatabasePlatform; import io.ebeaninternal.dbmigration.ddlgeneration.DdlBuffer; import io.ebeaninternal.dbmigration.ddlgeneration.DdlWrite; import io.ebeaninternal.dbmigration.migration.AlterColumn; -import io.ebeaninternal.server.persist.platform.MultiValueBind; import java.io.IOException; @@ -211,7 +210,7 @@ public class SqlServerDdl extends PlatformDdl { } /** - * This writes the multi value datatypes needed for {@link MultiValueBind} + * This writes the multi value datatypes needed for MultiValueBind. */ @Override public void generateProlog(DdlWrite write) throws IOException { diff --git a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java index bb188442e..0a9f29eca 100644 --- a/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java +++ b/ebean-ddl-generator/src/main/java/io/ebeaninternal/dbmigration/model/build/ModelBuildPropertyVisitor.java @@ -2,28 +2,11 @@ package io.ebeaninternal.dbmigration.model.build; import io.ebean.annotation.Platform; import io.ebeaninternal.dbmigration.ddlgeneration.platform.util.IndexSet; -import io.ebeaninternal.dbmigration.model.MColumn; -import io.ebeaninternal.dbmigration.model.MCompoundForeignKey; -import io.ebeaninternal.dbmigration.model.MCompoundUniqueConstraint; -import io.ebeaninternal.dbmigration.model.MIndex; -import io.ebeaninternal.dbmigration.model.MTable; +import io.ebeaninternal.dbmigration.model.*; +import io.ebeaninternal.server.deploy.*; import io.ebeaninternal.server.deploy.visitor.BaseTablePropertyVisitor; -import io.ebeaninternal.server.deploy.BeanDescriptor; -import io.ebeaninternal.server.deploy.BeanProperty; -import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; -import io.ebeaninternal.server.deploy.BeanPropertyAssocOne; -import io.ebeaninternal.server.deploy.IndexDefinition; -import io.ebeaninternal.server.deploy.InheritInfo; -import io.ebeaninternal.server.deploy.PropertyForeignKey; -import io.ebeaninternal.server.deploy.TableJoin; -import io.ebeaninternal.server.deploy.TableJoinColumn; -import io.ebeaninternal.server.deploy.id.ImportedId; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.StringJoiner; +import java.util.*; /** * Used as part of ModelBuildBeanVisitor and generally adds the MColumn to the associated @@ -192,8 +175,6 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { throw new RuntimeException("No join columns for " + p.fullName()); } - ImportedId importedId = p.importedId(); - List modelColumns = new ArrayList<>(columns.length); MCompoundForeignKey compoundKey = null; @@ -209,7 +190,7 @@ public class ModelBuildPropertyVisitor extends BaseTablePropertyVisitor { for (TableJoinColumn column : columns) { String dbCol = column.getLocalDbColumn(); - BeanProperty importedProperty = importedId.findMatchImport(dbCol); + BeanProperty importedProperty = p.findMatchImport(dbCol); if (importedProperty == null) { throw new RuntimeException("Imported BeanProperty not found?"); } diff --git a/ebean-test/pom.xml b/ebean-test/pom.xml index ecd8ebdb6..7998369fe 100644 --- a/ebean-test/pom.xml +++ b/ebean-test/pom.xml @@ -84,14 +84,14 @@ io.avaje avaje-jsr305 - 1.0 + 1.1 test io.ebean ebean-migration - 12.4.0 + 12.11.1 test diff --git a/ebean-test/src/main/java/io/ebean/test/CaptureLogger.java b/ebean-test/src/main/java/io/ebean/test/CaptureLogger.java index 1cdad509c..f76368f6c 100644 --- a/ebean-test/src/main/java/io/ebean/test/CaptureLogger.java +++ b/ebean-test/src/main/java/io/ebean/test/CaptureLogger.java @@ -8,12 +8,10 @@ import java.util.List; /** * Capture the log messages (executed SQL) for testing. */ -class CaptureLogger implements SpiLogger { +final class CaptureLogger implements SpiLogger { private final SpiLogger wrapped; - private List messages = new ArrayList<>(); - private boolean active; CaptureLogger(SpiLogger wrapped) { diff --git a/ebean-test/src/main/java/io/ebean/test/CapturingLoggerFactory.java b/ebean-test/src/main/java/io/ebean/test/CapturingLoggerFactory.java index c30e25790..aecc77026 100644 --- a/ebean-test/src/main/java/io/ebean/test/CapturingLoggerFactory.java +++ b/ebean-test/src/main/java/io/ebean/test/CapturingLoggerFactory.java @@ -2,7 +2,7 @@ package io.ebean.test; import io.ebeaninternal.api.SpiLogger; import io.ebeaninternal.api.SpiLoggerFactory; -import io.ebeaninternal.server.logger.DSpiLogger; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** @@ -15,11 +15,39 @@ public class CapturingLoggerFactory implements SpiLoggerFactory { @Override public SpiLogger create(String name) { - - DSpiLogger logger = new DSpiLogger(LoggerFactory.getLogger(name)); + SpiLogger logger = new LogAdapter(LoggerFactory.getLogger(name)); if (name.equals("io.ebean.SQL")) { return LoggedSql.register(logger); } return logger; } + + private static final class LogAdapter implements SpiLogger { + + private final Logger logger; + + LogAdapter(Logger logger) { + this.logger = logger; + } + + @Override + public boolean isDebug() { + return logger.isDebugEnabled(); + } + + @Override + public boolean isTrace() { + return logger.isTraceEnabled(); + } + + @Override + public void debug(String msg) { + logger.debug(msg); + } + + @Override + public void trace(String msg) { + logger.trace(msg); + } + } } diff --git a/ebean-test/src/main/java/io/ebean/test/LoggedSql.java b/ebean-test/src/main/java/io/ebean/test/LoggedSql.java index 624451f12..4c8f017a9 100644 --- a/ebean-test/src/main/java/io/ebean/test/LoggedSql.java +++ b/ebean-test/src/main/java/io/ebean/test/LoggedSql.java @@ -1,7 +1,6 @@ package io.ebean.test; import io.ebeaninternal.api.SpiLogger; -import io.ebeaninternal.server.logger.DSpiLogger; import java.util.List; @@ -44,7 +43,7 @@ public class LoggedSql { /** * Internal use - register the logger for io.ebean.SQL. */ - static SpiLogger register(DSpiLogger logger) { + static SpiLogger register(SpiLogger logger) { if (sqlLogger == null) { sqlLogger = new CaptureLogger(logger); } diff --git a/ebean-test/src/test/java/io/ebeaninternal/server/expression/InPairsExpressionTest.java b/ebean-test/src/test/java/io/ebeaninternal/server/expression/InPairsExpressionTest.java index b5f1254e5..599b5b4e6 100644 --- a/ebean-test/src/test/java/io/ebeaninternal/server/expression/InPairsExpressionTest.java +++ b/ebean-test/src/test/java/io/ebeaninternal/server/expression/InPairsExpressionTest.java @@ -77,7 +77,7 @@ public class InPairsExpressionTest extends BaseExpressionTest { public void diffSeparator_diff() throws Exception { InPairsExpression e0 = new InPairsExpression(pairs(), false); - InPairsExpression e1 = new InPairsExpression(pairs().setConcatSeparator(":"), false); + InPairsExpression e1 = new InPairsExpression(pairs().concatSeparator(":"), false); different(e0, e1); } @@ -85,7 +85,7 @@ public class InPairsExpressionTest extends BaseExpressionTest { public void diffSuffix_diff() throws Exception { InPairsExpression e0 = new InPairsExpression(pairs(), false); - InPairsExpression e1 = new InPairsExpression(pairs().setConcatSuffix(":"), false); + InPairsExpression e1 = new InPairsExpression(pairs().concatSuffix(":"), false); different(e0, e1); } diff --git a/ebean-test/src/test/java/org/tests/cache/TestQueryCache.java b/ebean-test/src/test/java/org/tests/cache/TestQueryCache.java index f70bc44c7..f127101f9 100644 --- a/ebean-test/src/test/java/org/tests/cache/TestQueryCache.java +++ b/ebean-test/src/test/java/org/tests/cache/TestQueryCache.java @@ -16,7 +16,10 @@ import java.util.List; import java.util.function.Consumer; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertTrue; public class TestQueryCache extends BaseTestCase { @@ -126,15 +129,52 @@ public class TestQueryCache extends BaseTestCase { // and now, ensure that we hit the database LoggedSql.start(); int count2 = DB.find(EColAB.class) - .setUseQueryCache(CacheMode.OFF) - .where() - .eq("columnB", "count") - .findCount(); + .setUseQueryCache(CacheMode.OFF) + .where() + .eq("columnB", "count") + .findCount(); assertThat(count2).isEqualTo(count1); sql = LoggedSql.stop(); assertThat(sql).hasSize(1); } + @Test + public void exists() { + + new EColAB("06", "exists").save(); + new EColAB("07", "exists").save(); + + LoggedSql.start(); + + boolean exists0 = DB.find(EColAB.class) + .setUseQueryCache(CacheMode.ON) + .where() + .eq("columnB", "exists") + .exists(); + + boolean exists1 = DB.find(EColAB.class) + .setUseQueryCache(CacheMode.ON) + .where() + .eq("columnB", "exists") + .exists(); + + List sql = LoggedSql.stop(); + + assertThat(exists0).isEqualTo(exists1); + assertThat(sql).hasSize(1); + + // and now, ensure that we hit the database + LoggedSql.start(); + boolean exists2 = DB.find(EColAB.class) + .setUseQueryCache(CacheMode.OFF) + .where() + .eq("columnB", "exists") + .exists(); + assertThat(exists2).isEqualTo(exists1); + sql = LoggedSql.stop(); + assertThat(sql).hasSize(1); + } + @Test public void findCountDifferentQueries() { diff --git a/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java b/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java index 3e058676b..0c84dc11f 100644 --- a/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java +++ b/ebean-test/src/test/java/org/tests/model/basic/cache/TestCacheViaComplexNaturalKey3.java @@ -386,8 +386,8 @@ public class TestCacheViaComplexNaturalKey3 extends BaseTestCase { loadSomeIntoCache(); Pairs pairs = new Pairs("sku", "code") - .setConcatSeparator(":") - .setConcatSuffix("-foo") + .concatSeparator(":") + .concatSuffix("-foo") .add("2", 1000) .add("2", 1001) .add("3", 1000); diff --git a/pom.xml b/pom.xml index d43b3a93f..a78e6a4e0 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ 2.12.1 1.2 1.1 - 12.11.0 + 12.11.1 4.1 7.2 12.11.2