Merge remote-tracking branch 'ebean/master' into pr/enh/post_process_find_controller

This commit is contained in:
Jonas Pöhler
2021-09-15 16:36:22 +02:00
19 changed files with 153 additions and 60 deletions
+22 -9
View File
@@ -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;
* </p>
* <pre>{@code sql
*
* create index ix_name on table_name ((sku || '-' || code));
* create index ix_name on table_name (sku || '-' || code);
*
* }</pre>
*/
public class Pairs {
public final class Pairs {
private final String property0;
private final String property1;
private final List<Entry> 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);
}
}
}
@@ -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<MetaQueryPlan> plans() {
return plans;
}
/**
* Deprecated migrate to plans().
*/
@Deprecated
public List<MetaQueryPlan> getPlans() {
return plans;
}
@@ -81,6 +81,11 @@ public interface SpiQuery<T> extends Query<T>, SpiQueryFetch, TxnProfileEventCod
*/
ID_LIST(FIND_ID_LIST, "findIds"),
/**
* Find exists.
*/
EXISTS(FIND_EXISTS, "exists"),
/**
* Find single attribute.
*/
@@ -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";
@@ -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());
@@ -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 <T> boolean exists(Query<T> ormQuery, Transaction transaction) {
Query<T> ormQueryCopy = ormQuery.copy().setMaxRows(1);
SpiOrmQueryRequest<?> request = createQueryRequest(Type.ID_LIST, ormQueryCopy, transaction);
SpiOrmQueryRequest<?> request = createQueryRequest(Type.EXISTS, ormQueryCopy, transaction);
List<Object> ids = request.getFromQueryCache();
if (ids != null) {
return !ids.isEmpty();
}
try {
request.initTransIfRequired();
return !request.findIds().isEmpty();
@@ -545,6 +545,13 @@ public class BeanPropertyAssocOne<T> extends BeanPropertyAssoc<T> 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++) {
@@ -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;
}
+1 -1
View File
@@ -23,7 +23,7 @@
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>12.11.0</version>
<version>12.11.1</version>
</dependency>
<dependency>
@@ -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 {
@@ -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<MColumn> 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?");
}
+2 -2
View File
@@ -84,14 +84,14 @@
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsr305</artifactId>
<version>1.0</version>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>12.4.0</version>
<version>12.11.1</version>
<scope>test</scope>
</dependency>
@@ -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<String> messages = new ArrayList<>();
private boolean active;
CaptureLogger(SpiLogger wrapped) {
@@ -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);
}
}
}
@@ -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 <code>io.ebean.SQL</code>.
*/
static SpiLogger register(DSpiLogger logger) {
static SpiLogger register(SpiLogger logger) {
if (sqlLogger == null) {
sqlLogger = new CaptureLogger(logger);
}
@@ -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);
}
@@ -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<String> 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() {
@@ -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);
+1 -1
View File
@@ -42,7 +42,7 @@
<jackson.version>2.12.1</jackson.version>
<ebean-ddl-runner.version>1.2</ebean-ddl-runner.version>
<ebean-migration-auto.version>1.1</ebean-migration-auto.version>
<ebean-migration.version>12.11.0</ebean-migration.version>
<ebean-migration.version>12.11.1</ebean-migration.version>
<ebean-test-docker.version>4.1</ebean-test-docker.version>
<ebean-datasource.version>7.2</ebean-datasource.version>
<ebean-agent.version>12.11.2</ebean-agent.version>