Compare commits

..
Author SHA1 Message Date
rob bygrave 08d241d946 #1966 Remove sequence batching - postgres opps 2020-03-05 00:34:05 +13:00
rob bygrave 1c24ebf6dc Remove Sequence batching in favour of JPA increment 50
Also remove h2sqldb in favour of always using H2
2020-03-05 00:22:20 +13:00
3948 changed files with 24804 additions and 74912 deletions
+6
View File
@@ -1,3 +1,9 @@
GITHUB ISSUES ARE STRICTLY CONTROLLED FOR THIS PROJECT.
Refer to http://ebean-orm.github.io/support for the policies controlling the use of github issues.
Please post issues to the Ebean group https://groups.google.com/forum/#!forum/ebean first.
## Expected behavior
## Actual behavior
+4 -1
View File
@@ -1,4 +1,6 @@
*.autofetch
*create-all.sql
*drop-all.sql
*.orig
.classpath
.project
@@ -10,6 +12,7 @@ ebean-autotune.xml
ebean-profiling*.xml
/db
/mydb.db
!src/test/ddl-review/*.sql
profiling/
# Intellij project files
@@ -17,4 +20,4 @@ profiling/
*.ipr
*.iws
.idea/
*uuid.state
*uuid.state
+1 -8
View File
@@ -7,11 +7,4 @@ do
echo ${file}
cat ${file}
echo
done
for file in ebean-autotune/target/surefire-reports/*.txt
do
echo ${file}
cat ${file}
echo
done
done
+1 -1
View File
@@ -293,6 +293,6 @@ ebean.tenant.schemaProvider
ebean.updateAllPropertiesInBatch
ebean.updateChangesOnly
ebean.updatesDeleteMissingChildren
ebean.useValidationNotNull
ebean.useJavaxValidationNotNull
ebean.useJtaTransactionManager
-124
View File
@@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.11.3</version>
</parent>
<name>ebean api</name>
<description>ebean api</description>
<artifactId>ebean-api</artifactId>
<dependencies>
<!--
Projects are expected to explicit depend on version
of slf4j that they want to use
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-config</artifactId>
<version>1.3</version>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
-->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsr305</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>persistence-api</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-annotation</artifactId>
<version>7.2</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-types</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource-api</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<!-- provided scope for JsonNode support -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
and not require a separate module for it -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,109 +0,0 @@
package io.ebean;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* Background executor service for executing of tasks asynchronously.
* <p>
* This service can be used to execute tasks in the background.
* <p>
* This service is managed by Ebean and will perform a clean shutdown
* waiting for background tasks to complete with a default 30 second
* timeout. Shutdown occurs prior to DataSource shutdown.
* <p>
* This also propagates MDC context from the current thread to the
* background task if defined.
*/
public interface BackgroundExecutor {
/**
* Execute a callable task in the background returning the Future.
*/
<T> Future<T> submit(Callable<T> task);
/**
* Execute a runnable task in the background returning the Future.
*/
Future<?> submit(Runnable task);
/**
* Execute a task in the background. Effectively the same as
* {@link BackgroundExecutor#submit(Runnable)} but returns void.
*/
void execute(Runnable task);
/**
* Deprecated - migrate to scheduleWithFixedDelay().
* Execute a task periodically with a fixed delay between each execution.
* <p>
* For example, execute a runnable every minute.
* <p>
* The delay is the time between executions no matter how long the task took.
* That is, this method has the same behaviour characteristics as
* {@link ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)}
*/
@Deprecated
void executePeriodically(Runnable task, long delay, TimeUnit unit);
/**
* Deprecated - migrate to scheduleWithFixedDelay().
* Execute a task periodically additionally with an initial delay different from delay.
*/
@Deprecated
void executePeriodically(Runnable task, long initialDelay, long delay, TimeUnit unit);
/**
* Execute a task periodically with a given delay.
*
* @param task the task to execute
* @param initialDelay the time to delay first execution
* @param delay the delay between the termination of one
* execution and the commencement of the next
* @param unit the time unit of the initialDelay and delay parameters
* @return a ScheduledFuture representing pending completion of
* the series of repeated tasks. The future's {@link
* Future#get() get()} method will never return normally,
* and will throw an exception upon task cancellation or
* abnormal termination of a task execution.
*/
ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit);
/**
* Execute a task periodically with a given period.
*
* <p>If any execution of this task takes longer than its period, then
* subsequent executions may start late, but will not concurrently
* execute.
*
* @param task the task to execute
* @param initialDelay the time to delay first execution
* @param period the period between successive executions
* @param unit the time unit of the initialDelay and period parameters
* @return a ScheduledFuture representing pending completion of
* the series of repeated tasks. The future's {@link
* Future#get() get()} method will never return normally,
* and will throw an exception upon task cancellation or
* abnormal termination of a task execution.
*/
ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit);
/**
* Schedules a Runnable for one-shot action that becomes enabled after the given delay.
*
* @return a ScheduledFuture representing pending completion of the task and
* whose get() method will return null upon completion
*/
ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit);
/**
* Schedules a Callable for one-shot action that becomes enabled after the given delay.
*
* @return a ScheduledFuture that can be used to extract result or cancel
*/
<V> ScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit);
}
@@ -1,19 +0,0 @@
package io.ebean;
/**
* Defines a cancelable query.
* <p>
* Typically holds a representation of the PreparedStatement to perform the
* actual cancel.
* </p>
*/
public interface CancelableQuery {
/**
* Cancel the query.
* <p>
* For JDBC this translates to calling cancel on the PreparedStatement.
* </p>
*/
void cancel();
}
@@ -1,170 +0,0 @@
package io.ebean;
import io.ebean.config.ContainerConfig;
import io.ebean.config.DatabaseConfig;
import io.ebean.service.SpiContainer;
import io.ebean.service.SpiContainerFactory;
import javax.persistence.PersistenceException;
import java.util.Iterator;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.concurrent.locks.ReentrantLock;
/**
* Creates Database instances.
* <p>
* This uses either DatabaseConfig or properties in the application.properties file to
* configure and create a Database instance.
* <p>
* The Database instance can either be registered with the DB singleton or
* not. The DB singleton effectively holds a map of Database by a name.
* If the Database is registered with the DB singleton you can retrieve it
* later via {@link DB#byName(String)}.
* <p>
* One Database can be nominated as the 'default/primary' Database. Many
* methods on the DB singleton such as {@link DB#find(Class)} are just a
* convenient way of using the 'default/primary' Database.
*/
public class DatabaseFactory {
private static final ReentrantLock lock = new ReentrantLock();
private static SpiContainer container;
private static String defaultServerName;
static {
EbeanVersion.getVersion();
}
/**
* Initialise the container with clustering configuration.
* <p>
* Call this prior to creating any Database instances or alternatively set the
* ContainerConfig on the DatabaseConfig when creating the first Database instance.
*/
public static void initialiseContainer(ContainerConfig containerConfig) {
lock.lock();
try {
container(containerConfig);
} finally {
lock.unlock();
}
}
/**
* Create using properties to configure the database.
*/
public static Database create(String name) {
lock.lock();
try {
return container(null).createServer(name);
} finally {
lock.unlock();
}
}
/**
* Create using the DatabaseConfig object to configure the database.
*
* <pre>{@code
*
* DatabaseConfig config = new DatabaseConfig();
* config.setName("db");
* config.loadProperties();
*
* Database database = DatabaseFactory.create(config);
*
* }</pre>
*/
public static Database create(DatabaseConfig config) {
lock.lock();
try {
if (config.getName() == null) {
throw new PersistenceException("The name is null (it is required)");
}
Database server = createInternal(config);
if (config.isRegister()) {
if (config.isDefaultServer()) {
if (defaultServerName != null && !defaultServerName.equals(config.getName())) {
throw new IllegalStateException("Registering [" + config.getName() + "] as the default server but [" + defaultServerName + "] is already registered as the default");
}
defaultServerName = config.getName();
}
DbPrimary.setSkip(true);
DbContext.getInstance().register(server, config.isDefaultServer());
}
return server;
} finally {
lock.unlock();
}
}
/**
* Create using the DatabaseConfig additionally specifying a classLoader to use as the context class loader.
*/
public static Database createWithContextClassLoader(DatabaseConfig config, ClassLoader classLoader) {
lock.lock();
try {
ClassLoader currentContextLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(classLoader);
try {
return DatabaseFactory.create(config);
} finally {
// set the currentContextLoader back
Thread.currentThread().setContextClassLoader(currentContextLoader);
}
} finally {
lock.unlock();
}
}
/**
* Shutdown gracefully all Database instances cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
*/
public static void shutdown() {
lock.lock();
try {
container.shutdown();
} finally {
lock.unlock();
}
}
private static Database createInternal(DatabaseConfig config) {
return container(config.getContainerConfig()).createServer(config);
}
/**
* Return the SpiContainer initialising it if necessary.
*
* @param containerConfig the configuration controlling clustering communication
*/
private static SpiContainer container(ContainerConfig containerConfig) {
// thread safe in that all calling methods hold lock
if (container != null) {
return container;
}
if (containerConfig == null) {
// effectively load configuration from ebean.properties
Properties properties = DbPrimary.getProperties();
containerConfig = new ContainerConfig();
containerConfig.loadFromProperties(properties);
}
container = createContainer(containerConfig);
return container;
}
/**
* Create the container instance using the configuration.
*/
protected static SpiContainer createContainer(ContainerConfig containerConfig) {
Iterator<SpiContainerFactory> factories = ServiceLoader.load(SpiContainerFactory.class).iterator();
if (factories.hasNext()) {
return factories.next().create(containerConfig);
}
throw new IllegalStateException("Service loader didn't find a SpiContainerFactory?");
}
}
@@ -1,139 +0,0 @@
package io.ebean;
import io.ebean.config.BeanNotEnhancedException;
import io.ebean.datasource.DataSourceConfigurationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
/**
* Holds Database instances.
*/
final class DbContext {
private static final Logger logger = LoggerFactory.getLogger(DbContext.class);
static {
EbeanVersion.getVersion();
}
private static final DbContext INSTANCE = new DbContext();
private final ConcurrentHashMap<String, Database> concMap = new ConcurrentHashMap<>();
private final HashMap<String, Database> syncMap = new HashMap<>();
private final ReentrantLock lock = new ReentrantLock();
/**
* The 'default' Database.
*/
private Database defaultDatabase;
private DbContext() {
try {
if (!DbPrimary.isSkip()) {
// look to see if there is a default server defined
String defaultName = DbPrimary.getDefaultServerName();
logger.debug("defaultName:{}", defaultName);
if (defaultName != null && !defaultName.trim().isEmpty()) {
defaultDatabase = getWithCreate(defaultName.trim());
}
}
} catch (BeanNotEnhancedException e) {
throw e;
} catch (DataSourceConfigurationException e) {
String msg = "Configuration error creating DataSource for the default Database." +
" This typically means a missing application-test.yaml or missing ebean-test dependency." +
" See https://ebean.io/docs/trouble-shooting#datasource";
throw new DataSourceConfigurationException(msg, e);
} catch (Throwable e) {
logger.error("Error trying to create the default Database", e);
throw new RuntimeException(e);
}
}
/**
* Return the shared singleton instance.
*/
static DbContext getInstance() {
return INSTANCE;
}
/**
* Return the default database.
*/
Database getDefault() {
if (defaultDatabase == null) {
String msg = "The default Database has not been defined?";
msg += " This is normally set via the ebean.datasource.default property.";
msg += " Otherwise it should be registered programmatically via registerServer()";
throw new PersistenceException(msg);
}
return defaultDatabase;
}
/**
* Return the database by name.
*/
Database get(String name) {
if (name == null || name.isEmpty()) {
return defaultDatabase;
}
Database server = concMap.get(name);
if (server != null) {
return server;
}
return getWithCreate(name);
}
/**
* Read, create and put of Databases.
*/
private Database getWithCreate(String name) {
lock.lock();
try {
Database server = syncMap.get(name);
if (server == null) {
// register when creating server this way
server = DatabaseFactory.create(name);
register(server, false);
}
return server;
} finally {
lock.unlock();
}
}
/**
* Register a server so we can get it by its name.
*/
void register(Database server, boolean isDefault) {
registerWithName(server.name(), server, isDefault);
}
private void registerWithName(String name, Database server, boolean isDefault) {
lock.lock();
try {
concMap.put(name, server);
syncMap.put(name, server);
if (isDefault) {
defaultDatabase = server;
}
} finally {
lock.unlock();
}
}
Database mock(String name, Database server, boolean defaultServer) {
Database originalPrimaryServer = this.defaultDatabase;
registerWithName(name, server, defaultServer);
return originalPrimaryServer;
}
}
@@ -1,70 +0,0 @@
package io.ebean;
import io.ebean.config.ContainerConfig;
import io.ebean.config.ServerConfig;
/**
* Deprecated - please migrate to DatabaseFactory.
* <p>
* Creates EbeanServer instances.
* <p>
* This uses either a ServerConfig or properties in the ebean.properties file to
* configure and create a EbeanServer instance.
* </p>
* <p>
* The EbeanServer instance can either be registered with the Ebean singleton or
* not. The Ebean singleton effectively holds a map of EbeanServers by a name.
* If the EbeanServer is registered with the Ebean singleton you can retrieve it
* later via {@link Ebean#getServer(String)}.
* </p>
* <p>
* One EbeanServer can be nominated as the 'default/primary' EbeanServer. Many
* methods on the Ebean singleton such as {@link Ebean#find(Class)} are just a
* convenient way of using the 'default/primary' EbeanServer.
* </p>
*/
@Deprecated
public class EbeanServerFactory {
/**
* Initialise the container with clustering configuration.
* <p>
* Call this prior to creating any EbeanServer instances or alternatively set the
* ContainerConfig on the ServerConfig when creating the first EbeanServer instance.
*/
public static void initialiseContainer(ContainerConfig containerConfig) {
DatabaseFactory.initialiseContainer(containerConfig);
}
/**
* Create using ebean.properties to configure the database.
*/
public static EbeanServer create(String name) {
return (EbeanServer)DatabaseFactory.create(name);
}
/**
* Create using the ServerConfig object to configure the database.
*/
public static EbeanServer create(ServerConfig config) {
return (EbeanServer)DatabaseFactory.create(config);
}
/**
* Create using the ServerConfig additionally specifying a classLoader to use as the context class loader.
*/
public static EbeanServer createWithContextClassLoader(ServerConfig config, ClassLoader classLoader) {
return (EbeanServer)DatabaseFactory.createWithContextClassLoader(config, classLoader);
}
/**
* Shutdown gracefully all EbeanServers cleaning up any resources as required.
* <p>
* This is typically invoked via JVM shutdown hook and not explicitly called.
* </p>
*/
public static void shutdown() {
DatabaseFactory.shutdown();
}
}
@@ -1,243 +0,0 @@
package io.ebean;
import java.io.Serializable;
/**
* Defines how a relationship is fetched via either normal SQL join,
* a eager secondary query, via lazy loading or via eagerly hitting L2 cache.
* <p>
* <pre>{@code
* // Normal fetch join results in a single SQL query
* List<Order> list = DB.find(Order.class).fetch("details").findList();
*
* }</pre>
* <p>
* Example: Using a "query join" instead of a "fetch join" we instead use 2 SQL queries
* </p>
* <p>
* <pre>{@code
*
* // This will use 2 SQL queries to build this object graph
* List<Order> list =
* DB.find(Order.class)
* .fetch("details", FetchConfig.ofQuery())
* .findList();
*
* // query 1) find order
* // query 2) find orderDetails where order.id in (?,?...) // first 100 order id's
*
* }</pre>
*
* @author mario
* @author rbygrave
*/
public class FetchConfig implements Serializable {
private static final long serialVersionUID = 1L;
private static final int JOIN_MODE = 0;
private static final int QUERY_MODE = 1;
private static final int LAZY_MODE = 2;
private static final int CACHE_MODE = 3;
private int mode;
private int batchSize;
private int hashCode;
/**
* Deprecated - migrate to one of the static factory methods like {@link FetchConfig#ofQuery()}
* <p>
* Construct using default JOIN mode.
*/
@Deprecated
public FetchConfig() {
//this.mode = JOIN_MODE;
this.batchSize = 100;
this.hashCode = 1000;
}
private FetchConfig(int mode, int batchSize) {
this.mode = mode;
this.batchSize = batchSize;
this.hashCode = mode + 10 * batchSize;
}
/**
* Return FetchConfig to eagerly fetch the relationship using L2 cache.
* <p>
* Any cache misses will be loaded by secondary query to the database.
*/
public static FetchConfig ofCache() {
return new FetchConfig(CACHE_MODE, 100);
}
/**
* Return FetchConfig to eagerly fetch the relationship using a secondary query.
*/
public static FetchConfig ofQuery() {
return new FetchConfig(QUERY_MODE, 100);
}
/**
* Return FetchConfig to eagerly fetch the relationship using a secondary with a given batch size.
*/
public static FetchConfig ofQuery(int batchSize) {
return new FetchConfig(QUERY_MODE, batchSize);
}
/**
* Return FetchConfig to lazily load the relationship.
*/
public static FetchConfig ofLazy() {
return new FetchConfig(LAZY_MODE, 0);
}
/**
* Return FetchConfig to lazily load the relationship specifying the batch size.
*/
public static FetchConfig ofLazy(int batchSize) {
return new FetchConfig(LAZY_MODE, batchSize);
}
/**
* Return FetchConfig to fetch the relationship using SQL join.
*/
public static FetchConfig ofDefault() {
return new FetchConfig(JOIN_MODE, 100);
}
/**
* We want to migrate away from mutating FetchConfig to a fully immutable FetchConfig.
*/
private FetchConfig mutate(int mode, int batchSize) {
if (batchSize < 0) {
throw new IllegalArgumentException("batch size " + batchSize + " must be > 0");
}
this.mode = mode;
this.batchSize = batchSize;
this.hashCode = mode + 10 * batchSize;
return this;
}
/**
* Deprecated - migrate to FetchConfig.ofLazy().
*/
@Deprecated
public FetchConfig lazy() {
return mutate(LAZY_MODE, 0);
}
/**
* Deprecated - migrate to FetchConfig.ofLazy(batchSize).
*/
@Deprecated
public FetchConfig lazy(int batchSize) {
return mutate(LAZY_MODE, batchSize);
}
/**
* Deprecated - migrate to FetchConfig.ofQuery().
* <p>
* Eagerly fetch the beans in this path as a separate query (rather than as
* part of the main query).
* <p>
* This will use the default batch size for separate query which is 100.
*/
@Deprecated
public FetchConfig query() {
return mutate(QUERY_MODE, 100);
}
/**
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
* <p>
* Eagerly fetch the beans in this path as a separate query (rather than as
* part of the main query).
* <p>
* The queryBatchSize is the number of parent id's that this separate query
* will load per batch.
* <p>
* This will load all beans on this path eagerly unless a {@link #lazy(int)}
* is also used.
*
* @param batchSize the batch size used to load beans on this path
*/
@Deprecated
public FetchConfig query(int batchSize) {
return mutate(QUERY_MODE, batchSize);
}
/**
* Deprecated - migrate to FetchConfig.ofQuery(batchSize).
* <p>
* Eagerly fetch the first batch of beans on this path.
* This is similar to {@link #query(int)} but only fetches the first batch.
* <p>
* If there are more parent beans than the batch size then they will not be
* loaded eagerly but instead use lazy loading.
*
* @param batchSize the number of parent beans this path is populated for
*/
@Deprecated
public FetchConfig queryFirst(int batchSize) {
return query(batchSize);
}
/**
* Deprecated - migrate to FetchConfig.ofCache().
* <p>
* Eagerly fetch the beans fetching the beans from the L2 bean cache
* and using the DB for beans not in the cache.
*/
@Deprecated
public FetchConfig cache() {
return mutate(CACHE_MODE, 100);
}
/**
* Return the batch size for fetching.
*/
public int getBatchSize() {
return batchSize;
}
/**
* Return true if the fetch should use the L2 cache.
*/
public boolean isCache() {
return mode == CACHE_MODE;
}
/**
* Return true if the fetch should be a eager secondary query.
*/
public boolean isQuery() {
return mode == QUERY_MODE;
}
/**
* Return true if the fetch should be a lazy query.
*/
public boolean isLazy() {
return mode == LAZY_MODE;
}
/**
* Return true if the fetch should try to use SQL join.
*/
public boolean isJoin() {
return mode == JOIN_MODE;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return (hashCode == ((FetchConfig) o).hashCode);
}
@Override
public int hashCode() {
return hashCode;
}
}
@@ -1,42 +0,0 @@
package io.ebean.bean;
/**
* Holds information on mutable values (like plain beans stored as json).
* <p>
* Used internally in EntityBeanIntercept for dirty detection on mutable values.
* Typically, mutation detection is based on a hash/checksum of json content or the
* original json content itself.
* <p>
* Refer to the mapping options {@code @DbJson(mutationDetection)}.
*/
public interface MutableValueInfo {
/**
* Compares the given json returning null if deemed unchanged or returning
* the MutableValueNext to use if deemed dirty/changed.
* <p>
* Returning MutableValueNext allows an implementation based on hash/checksum
* to only perform that computation once.
*
* @return Null if deemed unchanged or the MutableValueNext if deemed changed.
*/
MutableValueNext nextDirty(String json);
/**
* Compares the given object to an internal value.
* <p>
* This is used to support changelog/beanState. The implementation can serialize the
* object into json form and compare it against the original json.
*/
boolean isEqualToObject(Object obj);
/**
* Creates a new instance from the internal json string.
* <p>
* This is used to provide an original/old value for change logging / persist listeners.
* This is only available for properties that have {@code @DbJson(keepSource=true)}.
*/
default Object get() {
return null;
}
}
@@ -1,17 +0,0 @@
package io.ebean.bean;
/**
* Represents a next value to use for mutable content properties (DbJson with jackson beans).
*/
public interface MutableValueNext {
/**
* Return the next content to use. Provided such that we serialise to json once.
*/
String content();
/**
* Return the next MutableValueInfo to use after an update.
*/
MutableValueInfo info();
}
@@ -1,131 +0,0 @@
package io.ebean.common;
import java.util.*;
/**
* Handles the Entry Set for BeanMap.
*/
class ModifyEntrySet<K, E> implements Set<Map.Entry<K, E>> {
private final BeanMap<K, E> owner;
private final Set<Map.Entry<K, E>> entrySet;
ModifyEntrySet(BeanMap<K, E> owner, Set<Map.Entry<K, E>> entrySet) {
this.owner = owner;
this.entrySet = entrySet;
}
@Override
public int size() {
return entrySet.size();
}
@Override
public boolean isEmpty() {
return entrySet.isEmpty();
}
@Override
public boolean contains(Object o) {
return entrySet.contains(o);
}
@Override
public Object[] toArray() {
return entrySet.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return entrySet.toArray(a);
}
@Override
public boolean containsAll(Collection<?> entries) {
return entrySet.containsAll(entries);
}
@Override
public void clear() {
owner.clear();
}
@Override
public boolean add(Map.Entry<K, E> entry) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends Map.Entry<K, E>> c) {
throw new UnsupportedOperationException();
}
@SuppressWarnings("rawtypes")
@Override
public boolean remove(Object o) {
if (o instanceof Map.Entry) {
Map.Entry entry = (Map.Entry) o;
final E val = owner.get(entry.getKey());
if (Objects.equals(val, entry.getValue())) {
owner.remove(entry.getKey());
return true;
}
}
return false;
}
@Override
public boolean retainAll(Collection<?> entries) {
boolean modified = false;
final Iterator<Map.Entry<K, E>> it = iterator();
while (it.hasNext()) {
if (!entries.contains(it.next())) {
it.remove();
modified = true;
}
}
return modified;
}
@Override
public boolean removeAll(Collection<?> entries) {
boolean modified = false;
for (Object entry : entries) {
modified |= remove(entry);
}
return modified;
}
@Override
public Iterator<Map.Entry<K, E>> iterator() {
return new EntrySetIterator(new ArrayList<>(entrySet).iterator());
}
class EntrySetIterator implements Iterator<Map.Entry<K, E>> {
private final Iterator<Map.Entry<K, E>> iterator;
private Map.Entry<K, E> entry;
EntrySetIterator(Iterator<Map.Entry<K, E>> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public Map.Entry<K, E> next() {
entry = iterator.next();
return entry;
}
@Override
public void remove() {
owner.remove(entry.getKey());
iterator.remove();
}
}
}
@@ -1,126 +0,0 @@
package io.ebean.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
/**
* Handle the Key Set for BeanMap.
*/
class ModifyKeySet<E> implements Set<E> {
private final Set<E> keySet;
private final BeanMap<E, ?> owner;
ModifyKeySet(BeanMap<E, ?> owner, Set<E> keySet) {
this.owner = owner;
this.keySet = keySet;
}
@Override
public int size() {
return keySet.size();
}
@Override
public boolean isEmpty() {
return keySet.isEmpty();
}
@Override
public boolean contains(Object o) {
return keySet.contains(o);
}
@Override
public Object[] toArray() {
return keySet.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return keySet.toArray(a);
}
@Override
public boolean add(E key) {
throw new UnsupportedOperationException();
}
@Override
public boolean addAll(Collection<? extends E> keys) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object o) {
return owner.remove(o) != null;
}
@Override
public boolean containsAll(Collection<?> keys) {
return keySet.containsAll(keys);
}
@Override
public void clear() {
owner.clear();
}
@Override
public Iterator<E> iterator() {
return new KeySetIterator<>(new ArrayList<>(keySet).iterator());
}
@Override
public boolean retainAll(Collection<?> keys) {
return keysMatch(keys, false);
}
@Override
public boolean removeAll(Collection<?> keys) {
return keysMatch(keys, true);
}
private boolean keysMatch(Collection<?> keys, boolean containsMatch) {
boolean changed = false;
final Iterator<E> iterator = iterator();
while (iterator.hasNext()) {
final E key = iterator.next();
if (keys.contains(key) == containsMatch) {
iterator.remove();
changed = true;
}
}
return changed;
}
class KeySetIterator<K> implements Iterator<K> {
private final Iterator<K> iterator;
private K key;
KeySetIterator(Iterator<K> iterator) {
this.iterator = iterator;
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public K next() {
key = iterator.next();
return key;
}
@Override
public void remove() {
owner.remove(key);
iterator.remove();
}
}
}
@@ -1,18 +0,0 @@
package io.ebean.config;
/**
* Used to provide some automatic configuration early in the creation of a Database.
*/
public interface AutoConfigure {
/**
* Perform configuration for the DatabaseConfig prior to properties load.
*/
void preConfigure(DatabaseConfig config);
/**
* Provide some configuration the DatabaseConfig prior to server creation but after properties have been applied.
*/
void postConfigure(DatabaseConfig config);
}
@@ -1,39 +0,0 @@
package io.ebean.config;
/**
* Provides a ServiceLoader based mechanism to configure a DatabaseConfig.
* <p>
* Provide an implementation and register it via the standard Java ServiceLoader mechanism
* via a file at <code>META-INF/services/io.ebean.config.DatabaseConfigProvider</code>.
* </p>
* <p>
* If you are using a DI container like Spring or Guice you are unlikely to use this but instead use a
* spring specific configuration. When we are not using a DI container we may use this mechanism to
* explicitly register the entity beans and avoid classpath scanning.
* </p>
* <pre>{@code
*
* public class EbeanConfigProvider implements DatabaseConfigProvider {
*
* @Override
* public void apply(DatabaseConfig config) {
*
* // register the entity bean classes explicitly
* config.addClass(Customer.class);
* config.addClass(User.class);
* ...
* }
* }
*
* }</pre>
*/
public interface DatabaseConfigProvider {
/**
* Apply the configuration to the DatabaseConfig.
* <p>
* Typically we explicitly register entity bean classes and thus avoid classpath scanning.
* </p>
*/
void apply(DatabaseConfig config);
}
@@ -1,34 +0,0 @@
package io.ebean.config;
import io.ebean.Database;
import io.ebean.meta.MetaQueryPlan;
import java.util.List;
/**
* The captured query plans.
*/
public class QueryPlanCapture {
private final Database database;
private final List<MetaQueryPlan> plans;
public QueryPlanCapture(Database database, List<MetaQueryPlan> plans) {
this.database = database;
this.plans = plans;
}
/**
* Return the database the plans were captured for.
*/
public Database getDatabase() {
return database;
}
/**
* Return the captured query plans.
*/
public List<MetaQueryPlan> getPlans() {
return plans;
}
}
@@ -1,13 +0,0 @@
package io.ebean.config;
/**
* EXPERIMENTAL: Listener for captured query plans.
*/
@FunctionalInterface
public interface QueryPlanListener {
/**
* Process the captured query plans.
*/
void process(QueryPlanCapture capture);
}
@@ -1,57 +0,0 @@
package io.ebean.config.dbplatform;
import io.ebean.BackgroundExecutor;
import javax.sql.DataSource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* Database sequence based IdGenerator using Sequence Step 1 but batch fetch many sequence values.
*/
public abstract class SequenceBatchIdGenerator extends SequenceIdGenerator {
/**
* Construct where batchSize is the sequence step size.
*
*/
public SequenceBatchIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
super(be, ds, seqName, batchSize);
}
/**
* If allocateSize is large load some sequences in a background thread.
* <p>
* For example, when inserting a bean with a cascade on a OneToMany with many
* beans Ebean can call this to ensure .
* </p>
*/
@Override
public void preAllocateIds(int requestSize) {
if (allocationSize > 1 && requestSize > allocationSize) {
// only bother if allocateSize is bigger than
// the normal loading batchSize
if (requestSize > 100) {
// max out at 100 for now
requestSize = 100;
}
loadInBackground(requestSize);
}
}
/**
* Add the next set of Ids as the next value plus all the following numbers up to the step size.
*/
@Override
protected List<Long> readIds(ResultSet resultSet, int loadSize) throws SQLException {
List<Long> newIds = new ArrayList<>(loadSize);
while (resultSet.next()) {
newIds.add(resultSet.getLong(1));
}
return newIds;
}
}
@@ -1,35 +0,0 @@
package io.ebean.config.dbplatform.db2;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* DB2 specific sequence Id Generator.
*/
public class DB2SequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
private final String unionBaseSql;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
super(be, ds, seqName, batchSize);
this.baseSql = "values nextval for " + seqName;
this.unionBaseSql = " union " + baseSql;
}
@Override
public String getSql(int batchSize) {
StringBuilder sb = new StringBuilder();
sb.append(baseSql);
for (int i = 1; i < batchSize; i++) {
sb.append(unionBaseSql);
}
return sb.toString();
}
}
@@ -1,35 +0,0 @@
package io.ebean.config.dbplatform.h2;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* H2 specific sequence Id Generator.
*/
public class H2SequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
private final String unionBaseSql;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
public H2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
super(be, ds, seqName, batchSize);
this.baseSql = "select " + seqName + ".nextval";
this.unionBaseSql = " union " + baseSql;
}
@Override
public String getSql(int batchSize) {
StringBuilder sb = new StringBuilder();
sb.append(baseSql);
for (int i = 1; i < batchSize; i++) {
sb.append(unionBaseSql);
}
return sb.toString();
}
}
@@ -1,38 +0,0 @@
package io.ebean.config.dbplatform.hsqldb;
import io.ebean.BackgroundExecutor;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.DbPlatformType;
import io.ebean.config.dbplatform.DbType;
import io.ebean.config.dbplatform.IdType;
import io.ebean.config.dbplatform.PlatformIdGenerator;
import io.ebean.config.dbplatform.h2.H2DbEncrypt;
import io.ebean.config.dbplatform.h2.H2SequenceIdGenerator;
import javax.sql.DataSource;
/**
* H2 specific platform.
*/
public class HsqldbPlatform extends DatabasePlatform {
public HsqldbPlatform() {
super();
this.platform = Platform.HSQLDB;
this.dbEncrypt = new H2DbEncrypt();
this.truncateTable = "delete from %s";
this.dbIdentity.setIdType(IdType.IDENTITY);
this.dbIdentity.setSupportsGetGeneratedKeys(true);
this.dbIdentity.setSupportsSequence(true);
this.dbIdentity.setSupportsIdentity(true);
dbTypeMap.put(DbType.INTEGER, new DbPlatformType("integer", false));
}
@Override
public PlatformIdGenerator createSequenceIdGenerator(BackgroundExecutor be, DataSource ds, int stepSize, String seqName) {
return new H2SequenceIdGenerator(be, ds, seqName, sequenceBatchSize);
}
}
@@ -1,4 +0,0 @@
/**
* Hsqldb specific support.
*/
package io.ebean.config.dbplatform.hsqldb;
@@ -1,38 +0,0 @@
package io.ebean.config.dbplatform.mariadb;
import io.ebean.config.dbplatform.DbStandardHistorySupport;
/**
* History support for MariaDB.
*/
public class MariaDbHistorySupport extends DbStandardHistorySupport {
/**
* Return the ' as of timestamp ?' clause appended after the table name.
*/
@Override
public String getAsOfViewSuffix(String asOfViewSuffix) {
return " for system_time as of ?";
}
@Override
public String getVersionsBetweenSuffix(String asOfViewSuffix) {
return " for system_time between ? and ?";
}
/**
* Returns the SQL Server specific effective start column.
*/
@Override
public String getSysPeriodLower(String tableAlias, String sysPeriod) {
return tableAlias + ".row_start";
}
/**
* Returns the SQL Server specific effective end column.
*/
@Override
public String getSysPeriodUpper(String tableAlias, String sysPeriod) {
return tableAlias + ".row_end";
}
}
@@ -1,16 +0,0 @@
package io.ebean.config.dbplatform.mariadb;
import io.ebean.annotation.Platform;
import io.ebean.config.dbplatform.mysql.BaseMySqlPlatform;
/**
* MariaDB platform.
*/
public class MariaDbPlatform extends BaseMySqlPlatform {
public MariaDbPlatform() {
super();
this.platform = Platform.MARIADB;
this.historySupport = new MariaDbHistorySupport();
}
}
@@ -1,15 +0,0 @@
package io.ebean.config.dbplatform.mysql;
import io.ebean.annotation.Platform;
/**
* MySQL specific platform.
*/
public class MySqlPlatform extends BaseMySqlPlatform {
public MySqlPlatform() {
super();
this.platform = Platform.MYSQL;
}
}
@@ -1,24 +0,0 @@
package io.ebean.config.dbplatform.nuodb;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
import javax.sql.DataSource;
public class NuoDbSequence extends SequenceStepIdGenerator {
private final String nextSql;
/**
* Construct where batchSize is the sequence step size.
*/
public NuoDbSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
super(be, ds, seqName, stepSize);
this.nextSql = "select next value for " + seqName + " from dual";
}
@Override
public String getSql(int batchSize) {
return nextSql;
}
}
@@ -1,35 +0,0 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.config.dbplatform.BasicSqlLimiter;
/**
* Row limiter for Oracle 9,10,11 using rownum.
*/
public class OracleRownumBasicLimiter implements BasicSqlLimiter {
@Override
public String limit(String dbSql, int firstRow, int maxRows) {
if (firstRow < 1 && maxRows < 1) {
return dbSql;
}
StringBuilder sb = new StringBuilder(60 + dbSql.length());
int lastRow = maxRows;
if (lastRow > 0) {
lastRow += firstRow;
}
sb.append("select * from (select ");
if (maxRows > 0) {
sb.append("/*+ FIRST_ROWS(").append(maxRows).append(") */ ");
}
sb.append("a.*, rownum rn_ from (");
sb.append(dbSql).append(") a ");
if (lastRow > 0) {
sb.append(" where rownum <= ").append(lastRow);
}
sb.append(") ");
if (firstRow > 0) {
sb.append(" where rn_ > ").append(firstRow);
}
return sb.toString();
}
}
@@ -1,27 +0,0 @@
package io.ebean.config.dbplatform.oracle;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* Oracle specific sequence Id Generator.
*/
public class OracleSequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
public OracleSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
super(be, ds, seqName, batchSize);
this.baseSql = "select " + seqName + ".nextval, a from (select level as a FROM dual CONNECT BY level <= ";
}
@Override
public String getSql(int batchSize) {
return baseSql + batchSize + ")";
}
}
@@ -1,27 +0,0 @@
package io.ebean.config.dbplatform.postgres;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceBatchIdGenerator;
import javax.sql.DataSource;
/**
* Postgres specific sequence Id Generator.
*/
public class PostgresSequenceIdGenerator extends SequenceBatchIdGenerator {
private final String baseSql;
/**
* Construct given a dataSource and sql to return the next sequence value.
*/
public PostgresSequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
super(be, ds, seqName, batchSize);
this.baseSql = "select nextval('" + seqName + "'), s.generate_series from (select generate_series from generate_series(1,";
}
@Override
public String getSql(int batchSize) {
return baseSql + batchSize + ") ) as s";
}
}
@@ -1,46 +0,0 @@
package io.ebean.config.dbplatform.sqlserver;
import io.ebean.config.dbplatform.AbstractDbEncrypt;
import io.ebean.config.dbplatform.DbEncryptFunction;
/**
* SQL Server EncryptByPassPhrase DecryptByPassPhrase based encryption support.
*/
public class SqlServerDbEncrypt extends AbstractDbEncrypt {
public SqlServerDbEncrypt() {
this.varcharEncryptFunction = new VarcharFunction();
this.dateEncryptFunction = new DateFunction();
}
@Override
public boolean isBindEncryptDataFirst() {
return false;
}
private static class VarcharFunction implements DbEncryptFunction {
@Override
public String getDecryptSql(String columnWithTableAlias) {
return "convert(nvarchar,DecryptByPassPhrase(?," + columnWithTableAlias + "))";
}
@Override
public String getEncryptBindSql() {
return "EncryptByPassPhrase(?,?)";
}
}
private static class DateFunction implements DbEncryptFunction {
@Override
public String getDecryptSql(String columnWithTableAlias) {
return "cast(convert(nvarchar,DecryptByPassPhrase(?," + columnWithTableAlias + ")) as date)";
}
@Override
public String getEncryptBindSql() {
return "EncryptByPassPhrase(?,format(?,'yyyy-MM-dd'))";
}
}
}
@@ -1,24 +0,0 @@
package io.ebean.config.dbplatform.sqlserver;
import io.ebean.BackgroundExecutor;
import io.ebean.config.dbplatform.SequenceStepIdGenerator;
import javax.sql.DataSource;
public class SqlServerStepSequence extends SequenceStepIdGenerator {
private final String nextSql;
/**
* Construct where batchSize is the sequence step size.
*/
public SqlServerStepSequence(BackgroundExecutor be, DataSource ds, String seqName, int stepSize) {
super(be, ds, seqName, stepSize);
this.nextSql = "select next value for "+seqName;
}
@Override
public String getSql(int batchSize) {
return nextSql;
}
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document Mapping for a bean marker interface.
*/
public interface DocMapping {
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document query request context marker interface.
*/
public interface DocQueryContext<T> {
}
@@ -1,7 +0,0 @@
package io.ebean.docstore;
/**
* Document update context marker interface.
*/
public interface DocUpdateContext {
}
@@ -1,71 +0,0 @@
package io.ebean.event;
import io.ebean.Database;
import io.ebean.EbeanServer;
import io.ebean.Transaction;
/**
* A request to delete a bean by Id value.
*/
public interface BeanDeleteIdRequest {
/**
* Deprecated migrate to database().
*/
@Deprecated
EbeanServer getEbeanServer();
/**
* Deprecated migrate to database().
*/
@Deprecated
default Database getDatabase() {
return getEbeanServer();
}
/**
* Return the DB processing the request.
*/
default Database database() {
return getEbeanServer();
}
/**
* Return the Transaction associated with this request.
*/
Transaction transaction();
/**
* Deprecated migrate to transaction().
*/
@Deprecated
default Transaction getTransaction() {
return transaction();
}
/**
* Returns the bean type of the bean being deleted.
*/
Class<?> beanType();
/**
* Deprecated migrate to beanType().
*/
@Deprecated
default Class<?> getBeanType() {
return beanType();
}
/**
* Returns the Id value of the bean being deleted.
*/
Object id();
/**
* Deprecated migrate to id().
*/
@Deprecated
default Object getId() {
return id();
}
}
@@ -1,52 +0,0 @@
package io.ebean.meta;
/**
* Query execution metrics.
*/
public interface MetaQueryMetric extends MetaTimedMetric {
/**
* The type of entity or DTO bean.
*/
Class<?> type();
/**
* Migrate to type().
*/
@Deprecated
default Class<?> getType() {
return type();
}
/**
* The label for the query (can be null).
*/
String label();
/**
* Migrate to label().
*/
@Deprecated
default String getLabel() {
return label();
}
/**
* The actual SQL of the query.
*/
String sql();
/**
* Migrate to sql().
*/
@Deprecated
default String getSql() {
return sql();
}
/**
* Return the hash of the plan.
*/
String hash();
}
@@ -1,48 +0,0 @@
package io.ebean.meta;
import java.util.List;
/**
* Metrics of the Database instance.
*/
public interface ServerMetrics {
/**
* Return timed metrics for Transactions, labelled SqlQuery, labelled SqlUpdate.
*/
List<MetaTimedMetric> timedMetrics();
/**
* Migrate to timedMetrics().
*/
@Deprecated
default List<MetaTimedMetric> getTimedMetrics() {
return timedMetrics();
}
/**
* Return the query metrics.
*/
List<MetaQueryMetric> queryMetrics();
/**
* Migrate to queryMetrics().
*/
@Deprecated
default List<MetaQueryMetric> getQueryMetrics() {
return queryMetrics();
}
/**
* Return the Counter metrics.
*/
List<MetaCountMetric> countMetrics();
/**
* Migrate to countMetrics().
*/
@Deprecated
default List<MetaCountMetric> getCountMetrics() {
return countMetrics();
}
}
@@ -1,114 +0,0 @@
package io.ebean.plugin;
import io.ebean.Database;
import io.ebean.bean.BeanLoader;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.dbplatform.DatabasePlatform;
import java.util.List;
/**
* Extensions to Database API made available to plugins.
*/
public interface SpiServer extends Database {
/**
* Return the DatabaseConfig.
*/
DatabaseConfig config();
/**
* Migrate to config().
*/
@Deprecated
default DatabaseConfig getServerConfig() {
return config();
}
/**
* Return the DatabasePlatform for this database.
*/
DatabasePlatform databasePlatform();
/**
* Migrate to config().
*/
@Deprecated
default DatabasePlatform getDatabasePlatform() {
return databasePlatform();
}
/**
* Return all the bean types registered on this server instance.
*/
List<? extends BeanType<?>> beanTypes();
/**
* Migrate to beanTypes().
*/
@Deprecated
default List<? extends BeanType<?>> getBeanTypes() {
return beanTypes();
}
/**
* Return the bean type for a given entity bean class.
*/
<T> BeanType<T> beanType(Class<T> beanClass);
/**
* Migrate to beanType().
*/
@Deprecated
default <T> BeanType<T> getBeanType(Class<T> beanClass) {
return beanType(beanClass);
}
/**
* Return the bean types mapped to the given base table.
*/
List<? extends BeanType<?>> beanTypes(String baseTableName);
/**
* Migrate to beanTypes().
*/
@Deprecated
default List<? extends BeanType<?>> getBeanTypes(String baseTableName) {
return beanTypes(baseTableName);
}
/**
* Return the bean type for a given doc store queueId.
*/
BeanType<?> beanTypeForQueueId(String queueId);
/**
* Migrate to beanTypes().
*/
@Deprecated
default BeanType<?> getBeanTypeForQueueId(String queueId) {
return beanTypeForQueueId(queueId);
}
/**
* Return a BeanLoader.
*/
BeanLoader beanLoader();
/**
* Invoke lazy loading on this single bean (reference bean).
*/
void loadBeanRef(EntityBeanIntercept ebi);
/**
* Invoke lazy loading on this single bean (L2 cache bean).
*/
void loadBeanL2(EntityBeanIntercept ebi);
/**
* Invoke lazy loading on this single bean when no BeanLoader is set.
* Typically due to serialisation or multiple stateless updates.
*/
void loadBean(EntityBeanIntercept ebi);
}
@@ -1,98 +0,0 @@
package io.ebean.util;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* Annotation utility methods to find annotations.
*/
public class AnnotationUtil {
/**
* Determine if the supplied {@link Annotation} is defined in the core JDK {@code java.lang.annotation} package.
*/
public static boolean notJavaLang(Annotation annotation) {
return !annotation.annotationType().getName().startsWith("java.lang.annotation");
}
/**
* Simple get on field or method with no meta-annotations or platform filtering.
*/
public static <A extends Annotation> A get(AnnotatedElement element, Class<A> annotation) {
return element.getAnnotation(annotation);
}
/**
* Simple has with no meta-annotations or platform filtering.
*/
public static <A extends Annotation> boolean has(AnnotatedElement element, Class<A> annotation) {
return get(element, annotation) != null;
}
/**
* On class get the annotation - includes inheritance.
*/
public static <A extends Annotation> A typeGet(Class<?> clazz, Class<A> annotationType) {
while (clazz != null && clazz != Object.class) {
final A val = clazz.getAnnotation(annotationType);
if (val != null) {
return val;
}
clazz = clazz.getSuperclass();
}
return null;
}
/**
* On class get all the annotations - includes inheritance.
*/
public static <A extends Annotation> Set<A> typeGetAll(Class<?> clazz, Class<A> annotationType) {
Set<A> result = new LinkedHashSet<>();
typeGetAllCollect(clazz, annotationType, result);
return result;
}
private static <A extends Annotation> void typeGetAllCollect(Class<?> clazz, Class<A> annotationType, Set<A> result) {
while (clazz != null && clazz != Object.class) {
final A val = clazz.getAnnotation(annotationType);
if (val != null) {
result.add(val);
}
clazz = clazz.getSuperclass();
}
}
/**
* On class simple check for annotation - includes inheritance.
*/
public static <A extends Annotation> boolean typeHas(Class<?> clazz, Class<A> annotation) {
return typeGet(clazz, annotation) != null;
}
/**
* Find all the annotations for the filter searching meta-annotations.
*/
public static Set<Annotation> metaFindAllFor(AnnotatedElement element, Set<Class<?>> filter) {
Set<Annotation> visited = new HashSet<>();
Set<Annotation> result = new LinkedHashSet<>();
for (Annotation ann : element.getAnnotations()) {
metaAdd(ann, filter, visited, result);
}
return result;
}
private static void metaAdd(Annotation ann, Set<Class<?>> filter, Set<Annotation> visited, Set<Annotation> result) {
if (notJavaLang(ann) && visited.add(ann)) {
if (filter.contains(ann.annotationType())) {
result.add(ann);
} else {
for (Annotation metaAnn : ann.annotationType().getAnnotations()) {
metaAdd(metaAnn, filter, visited, result);
}
}
}
}
}
@@ -1,147 +0,0 @@
package io.ebean.util;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Utility String class that supports String manipulation functions.
*/
public class StringHelper {
private static final Pattern SPLIT_NAMES = Pattern.compile("[\\s,;]+");
private static final String[] EMPTY_STRING_ARRAY = new String[0];
/**
* Return true if the value is null or an empty string.
*/
public static boolean isNull(String value) {
return value == null || value.trim().isEmpty();
}
/**
* Parses out a list of Name Value pairs that are delimited together. Will
* always return a StringMap. If allNameValuePairs is null, or no name values
* can be parsed out an empty StringMap is returned.
*
* @param source the entire string to be parsed.
* @param listDelimiter (typically ';') the delimited between the list
* @param nameValueSeparator (typically '=') the separator between the name and value
*/
public static Map<String, String> delimitedToMap(String source, String listDelimiter, String nameValueSeparator) {
Map<String, String> params = new HashMap<>();
if (source == null || source.isEmpty()) {
return params;
}
// trim off any leading listDelimiter...
source = trimFront(source, listDelimiter);
return delimitedToMap(params, source, listDelimiter, nameValueSeparator);
}
/**
* Trims off recurring strings from the front of a string.
*
* @param source the source string
* @param trim the string to trim off the front
*/
private static String trimFront(String source, String trim) {
while (true) {
if (source.indexOf(trim) == 0) {
source = source.substring(trim.length());
} else {
return source;
}
}
}
/**
* Recursively pulls out the key value pairs from a raw string.
*/
private static Map<String, String> delimitedToMap(Map<String, String> map, String source, String listDelimiter, String nameValueSeparator) {
int pos = 0;
while (true) {
if (pos >= source.length()) {
return map;
}
int equalsPos = source.indexOf(nameValueSeparator, pos);
int delimPos = source.indexOf(listDelimiter, pos);
if (delimPos == -1) {
delimPos = source.length();
}
if (equalsPos == -1) {
return map;
}
if (delimPos == (equalsPos + 1)) {
pos = delimPos + 1;
continue;
}
if (equalsPos > delimPos) {
// there is a key without a value?
String key = source.substring(pos, delimPos);
key = key.trim();
if (!key.isEmpty()) {
map.put(key, null);
}
pos = delimPos + 1;
continue;
}
String key = source.substring(pos, equalsPos);
String value = source.substring(equalsPos + 1, delimPos);
map.put(key.trim(), value);
pos = delimPos + 1;
}
}
/**
* This method takes a String and will replace all occurrences of the match
* String with that of the replace String.
*
* @param source the source string
* @param match the string used to find a match
* @param replace the string used to replace match with
* @return the source string after the search and replace
*/
public static String replace(String source, String match, String replace) {
if (source == null) {
return null;
}
if (replace == null) {
return source;
}
return source.replace(match, replace);
}
/**
* Return new line and carriage return with space.
*/
public static String removeNewLines(String source) {
source = source.replace('\n', ' ');
return source.replace('\r', ' ');
}
/**
* Splits at any whitespace "," or ";" and trims the result.
* It does not return empty entries.
*/
public static String[] splitNames(String names) {
if (names == null || names.isEmpty()) {
return EMPTY_STRING_ARRAY;
}
String[] result = SPLIT_NAMES.split(names);
if (result.length == 0) {
return EMPTY_STRING_ARRAY;
}
if ("".equals(result[0])) { // input string starts with whitespace
if (result.length == 1) { // input string contains only whitespace
return EMPTY_STRING_ARRAY;
} else {
String[] ret = new String[result.length-1]; // remove first entry
System.arraycopy(result, 1, ret, 0, ret.length);
return ret;
}
} else {
return result;
}
}
}
@@ -1,2 +0,0 @@
Manifest-Version: 1.0
Automatic-Module-Name: io.ebean.api
@@ -1,55 +0,0 @@
package io.ebean.config.dbplatform;
import org.junit.Test;
import java.sql.Types;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import static org.assertj.core.api.Assertions.assertThat;
public class DbDefaultValueTest {
@Test
public void toSqlLiteral_timestamp() {
assertThat(ts("2001-10-26T21:32:52")).isEqualTo("'2001-10-26T21:32:52'");
assertThat(ts("2001-10-26T21:32:52+02:00")).isEqualTo("'2001-10-26T21:32:52+02:00'");
assertThat(ts("2001-10-26T19:32:52Z")).isEqualTo("'2001-10-26T19:32:52Z'");
assertThat(ts("2001-10-26T19:32:52+00:00")).isEqualTo("'2001-10-26T19:32:52+00:00'");
assertThat(ts("-2001-10-26T21:32:52")).isEqualTo("'-2001-10-26T21:32:52'");
assertThat(ts("2001-10-26T21:32:52.12679")).isEqualTo("'2001-10-26T21:32:52.12679'");
}
private String ts(String input) {
return DbDefaultValue.toSqlLiteral(input, OffsetDateTime.class, Types.TIMESTAMP);
}
@Test
public void toSqlLiteral_date() {
assertThat(date("2001-10-26")).isEqualTo("'2001-10-26'");
assertThat(date("2001-10-26+02:00")).isEqualTo("'2001-10-26+02:00'");
assertThat(date("2001-10-26Z")).isEqualTo("'2001-10-26Z'");
assertThat(date("2001-10-26+00:00")).isEqualTo("'2001-10-26+00:00'");
assertThat(date("-2001-10-26")).isEqualTo("'-2001-10-26'");
assertThat(date("-20000-04-01")).isEqualTo("'-20000-04-01'");
}
private String date(String input) {
return DbDefaultValue.toSqlLiteral(input, LocalDate.class, Types.DATE);
}
@Test
public void toSqlLiteral_time() {
assertThat(time("21:32:52")).isEqualTo("'21:32:52'");
assertThat(time("21:32:52+02:00")).isEqualTo("'21:32:52+02:00'");
assertThat(time("19:32:52Z")).isEqualTo("'19:32:52Z'");
assertThat(time("19:32:52+00:00")).isEqualTo("'19:32:52+00:00'");
assertThat(time("21:32:52.12679")).isEqualTo("'21:32:52.12679'");
}
private String time(String input) {
return DbDefaultValue.toSqlLiteral(input, LocalTime.class, Types.TIME);
}
}
-85
View File
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.11.3</version>
</parent>
<!-- <parent>-->
<!-- <groupId>org.avaje</groupId>-->
<!-- <artifactId>java8-oss</artifactId>-->
<!-- <version>2.2</version>-->
<!-- </parent>-->
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-12.11.3</tag>
</scm>
<name>ebean autotune</name>
<description>ebean automatic query tuning module</description>
<artifactId>ebean-autotune</artifactId>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>12.11.3</version>
<scope>provided</scope>
</dependency>
<!-- needed for java 11+ -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje.composite</groupId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.repaint.maven</groupId>
<artifactId>tiles-maven-plugin</artifactId>
<version>2.19</version>
<extensions>true</extensions>
<configuration>
<tiles>
<!-- other tiles ... -->
<tile>io.ebean.tile:enhancement:12.6.0</tile>
</tiles>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -1,15 +0,0 @@
package io.ebeaninternal.server.autotune.service;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.server.autotune.AutoTuneService;
import io.ebeaninternal.server.autotune.AutoTuneServiceProvider;
public class AutoTuneServiceFactory implements AutoTuneServiceProvider {
@Override
public AutoTuneService create(SpiEbeanServer server, DatabaseConfig config) {
return new DefaultAutoTuneService(server, config);
}
}
@@ -1,2 +0,0 @@
Manifest-Version: 1.0
Automatic-Module-Name: io.ebean.autotune
@@ -1 +0,0 @@
io.ebeaninternal.server.autotune.service.AutoTuneServiceFactory
@@ -1,16 +0,0 @@
package org.tests.autofetch;
import io.ebean.DB;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.server.deploy.BeanDescriptor;
public class BaseTestCase {
protected SpiEbeanServer spiEbeanServer() {
return (SpiEbeanServer) DB.getDefault();
}
protected <T> BeanDescriptor<T> getBeanDescriptor(Class<T> cls) {
return spiEbeanServer().getBeanDescriptor(cls);
}
}
@@ -1,32 +0,0 @@
package org.tests.autofetch;
//import io.ebean.Ebean;
//import org.tests.model.basic.EBasicClob;
//import java.util.List;
public class MainAutoFetchExcludeLazyLobs {
// public static void main(String[] args) {
//
// EBasicClob a = new EBasicClob();
// a.setName("name 1");
// a.setTitle("a title");
// a.setDescription("not that meaningful");
//
// Ebean.save(a);
//
// List<EBasicClob> list = Ebean.find(EBasicClob.class)
// .setAutoTune(true)
// .findList();
//
// for (EBasicClob bean : list) {
// bean.getName();
// // although we read the description
// // autofetch will not include it later
// bean.getDescription();
// }
//
//
// }
}
@@ -1,28 +0,0 @@
package org.tests.autofetch;
public class MainAutoQueryTune1 {
// public static void main(String[] args) {
//
// ResetBasicData.reset();
//
// MainAutoQueryTune1 me = new MainAutoQueryTune1();
// me.tuneJoin();
// }
//
// private void tuneJoin() {
// List<Order> list = Ebean.find(Order.class)
// .setAutoTune(true)
// .fetch("customer")
// .where()
// .eq("status", Order.Status.NEW)
// .eq("customer.name", "Rob")
// .order().asc("id")
// .findList();
//
// for (Order order : list) {
// order.getId();
// order.getOrderDate();
// }
// }
}
@@ -1,172 +0,0 @@
package org.tests.autofetch;
//import io.ebean.BaseTestCase;
//import io.ebean.Ebean;
//import io.ebean.EbeanServer;
//import io.ebean.Query;
//import io.ebean.bean.EntityBean;
//import io.ebean.bean.EntityBeanIntercept;
//import io.ebean.cache.ServerCacheManager;
//import io.ebeaninternal.api.SpiQuery;
//import io.ebeaninternal.server.autotune.model.Origin;
//import io.ebeaninternal.server.autotune.service.TunedQueryInfo;
//import io.ebeaninternal.server.querydefn.OrmQueryDetail;
//import org.ebeantest.LoggedSqlCollector;
//import org.junit.Assert;
//import org.junit.Test;
//import org.tests.model.basic.Order;
//import org.tests.model.basic.ResetBasicData;
//
//import java.util.List;
//import java.util.Set;
public class TunedQueryInfoTest extends BaseTestCase {
// private void init() {
//
// ResetBasicData.reset();
//
// ServerCacheManager serverCacheManager = Ebean.getServer(null).getServerCacheManager();
// serverCacheManager.clearAll();
// }
//
// @Test
// public void withSelectEmpty() {
//
// init();
//
// OrmQueryDetail tunedDetail = new OrmQueryDetail();
// tunedDetail.select("");
//
// TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
//
// Query<Order> query = server.find(Order.class).setId(1);
//
// tunedInfo.tuneQuery((SpiQuery<?>) query);
//
// Order order = query.findOne();
// EntityBean eb = (EntityBean) order;
// EntityBeanIntercept ebi = eb._ebean_getIntercept();
//
// Assert.assertTrue(ebi.isFullyLoadedBean());
//
// Set<String> loadedPropertyNames = ebi.getLoadedPropertyNames();
// Assert.assertNull(loadedPropertyNames);
//
// // invoke lazy loading
// order.getCustomer();
// }
//
// @Test
// public void withSelectSomethingThatDoesNotExist() {
//
// init();
//
// OrmQueryDetail tunedDetail = new OrmQueryDetail();
// tunedDetail.select("somethingThatDoesNotExist");
//
// TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
//
// Query<Order> query = server.find(Order.class).setId(1);
//
// tunedInfo.tuneQuery((SpiQuery<?>) query);
//
// LoggedSqlCollector.start();
//
// Order order = query.findOne();
// EntityBean eb = (EntityBean) order;
// EntityBeanIntercept ebi = eb._ebean_getIntercept();
//
// Assert.assertFalse(ebi.isFullyLoadedBean());
//
// // id and any ToMany relationships
// Set<String> loadedPropertyNames = ebi.getLoadedPropertyNames();
// Assert.assertNotNull(loadedPropertyNames);
//
// // invoke lazy loading
// order.getCustomer();
//
// List<String> loggedSql = LoggedSqlCollector.stop();
// Assert.assertEquals(2, loggedSql.size());
//
// Assert.assertTrue(trimSql(loggedSql.get(0), 1).contains("select t0.id, t0.id from o_order t0 where t0.id = ?"));
// Assert.assertTrue(trimSql(loggedSql.get(1), 1).contains("select t0.id, t0.status,"));
// }
//
// private TunedQueryInfo createTunedQueryInfo(OrmQueryDetail tunedDetail) {
// Origin origin = new Origin();
// origin.setDetail(tunedDetail.asString());
// return new TunedQueryInfo(origin);
// }
//
// @Test
// public void withSelectSomeIncludeLazyLoaded() {
//
// init();
//
// OrmQueryDetail tunedDetail = new OrmQueryDetail();
// tunedDetail.select("status, customer");
//
// TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
//
// Query<Order> query = server.find(Order.class).setId(1);
//
// tunedInfo.tuneQuery((SpiQuery<?>) query);
//
// LoggedSqlCollector.start();
//
// Order order = query.findOne();
// EntityBean eb = (EntityBean) order;
// EntityBeanIntercept ebi = eb._ebean_getIntercept();
//
// Assert.assertFalse(ebi.isFullyLoadedBean());
//
// Set<String> loadedPropertyNames = ebi.getLoadedPropertyNames();
// Assert.assertNotNull(loadedPropertyNames);
//
// Assert.assertTrue(loadedPropertyNames.contains("status"));
// Assert.assertTrue(loadedPropertyNames.contains("customer"));
//
// // no lazy loading expected here
// order.getCustomer();
//
// List<String> loggedSql = LoggedSqlCollector.stop();
// Assert.assertEquals(1, loggedSql.size());
// }
//
// @Test
// public void withSelectSome() {
//
// init();
//
// OrmQueryDetail tunedDetail = new OrmQueryDetail();
// tunedDetail.select("status");
//
// TunedQueryInfo tunedInfo = createTunedQueryInfo(tunedDetail);
//
// Query<Order> query = server.find(Order.class).setId(1);
//
// tunedInfo.tuneQuery((SpiQuery<?>) query);
//
// LoggedSqlCollector.start();
//
// Order order = query.findOne();
// EntityBean eb = (EntityBean) order;
// EntityBeanIntercept ebi = eb._ebean_getIntercept();
//
// Assert.assertFalse(ebi.isFullyLoadedBean());
//
// Set<String> loadedPropertyNames = ebi.getLoadedPropertyNames();
// Assert.assertNotNull(loadedPropertyNames);
//
// Assert.assertTrue(loadedPropertyNames.contains("status"));
// Assert.assertFalse(loadedPropertyNames.contains("customer"));
//
// // no lazy loading expected here
// order.getCustomer();
//
// List<String> loggedSql = LoggedSqlCollector.stop();
// Assert.assertEquals(2, loggedSql.size());
// }
}
@@ -1,69 +0,0 @@
package org.tests.autofetch;
//import io.ebean.BaseTestCase;
//import io.ebean.Ebean;
//import io.ebean.EbeanServer;
//import io.ebean.Query;
//import io.ebean.bean.EntityBean;
//import io.ebean.bean.EntityBeanIntercept;
//import org.ebeantest.LoggedSqlCollector;
//import org.junit.Assert;
//import org.junit.Test;
//import org.tests.model.basic.Address;
//import org.tests.model.basic.Customer;
//import org.tests.model.basic.ResetBasicData;
import java.util.List;
import java.util.Set;
public class TunedQueryWithNullFetchedBeanTest extends BaseTestCase {
// EbeanServer server = Ebean.getServer(null);
//
// @Test
// public void withFetchOfNullBeanJoin() {
//
// ResetBasicData.reset();
//
// Customer newCustomer = new Customer();
// newCustomer.setName("TestFetchBillingAddress");
// server.save(newCustomer);
//
// Query<Customer> query = server.find(Customer.class)
// .setId(newCustomer.getId())
// .fetch("billingAddress", "id");
//
// LoggedSqlCollector.start();
//
// Customer customer = query.findOne();
// EntityBean eb = (EntityBean) customer;
// EntityBeanIntercept ebi = eb._ebean_getIntercept();
//
// Assert.assertTrue(ebi.isFullyLoadedBean());
//
// // find the internal property index for "billingAddress"
// String[] propNames = eb._ebean_getPropertyNames();
// int pos = 0;
// for (int i = 0; i < propNames.length; i++) {
// if (propNames[i].equals("billingAddress")) {
// pos = i;
// }
// }
//
// // The billing address is loaded (but value null)
// Assert.assertTrue(ebi.isLoadedProperty(pos));
//
// Set<String> loadedPropertyNames = ebi.getLoadedPropertyNames();
// Assert.assertNull(loadedPropertyNames);
//
// // no lazy loading expected here, value is null
// Address billingAddress = customer.getBillingAddress();
// Assert.assertNull(billingAddress);
//
// // assert only one query executed
// List<String> loggedSql = LoggedSqlCollector.stop();
// Assert.assertEquals(1, loggedSql.size());
//
// Ebean.delete(newCustomer);
// }
}
@@ -1,38 +0,0 @@
package org.tests.model.basic;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name = "address")
public class Address extends BaseModel {
String line1;
String line2;
String city;
public String getLine1() {
return line1;
}
public void setLine1(String line1) {
this.line1 = line1;
}
public String getLine2() {
return line2;
}
public void setLine2(String line2) {
this.line2 = line2;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
@@ -1,58 +0,0 @@
package org.tests.model.basic;
import io.ebean.Model;
import io.ebean.annotation.WhenCreated;
import io.ebean.annotation.WhenModified;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;
import java.time.Instant;
@MappedSuperclass
public class BaseModel extends Model {
@Id
long id;
@WhenCreated
Instant whenCreated;
@WhenModified
Instant whenModified;
@Version
long version;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public Instant getWhenCreated() {
return whenCreated;
}
public void setWhenCreated(Instant whenCreated) {
this.whenCreated = whenCreated;
}
public Instant getWhenModified() {
return whenModified;
}
public void setWhenModified(Instant whenModified) {
this.whenModified = whenModified;
}
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
}
@@ -1,41 +0,0 @@
package org.tests.model.basic;
import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
@Entity
@Table(name = "o_customer")
public class Customer extends BaseModel {
String name;
String note;
@ManyToOne
Address billingAddress;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Address getBillingAddress() {
return billingAddress;
}
public void setBillingAddress(Address billingAddress) {
this.billingAddress = billingAddress;
}
}
@@ -1,60 +0,0 @@
package org.tests.model.basic;
import io.ebean.Model;
import io.ebean.annotation.WhenModified;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Version;
import java.sql.Timestamp;
import java.time.LocalDate;
@Entity
@Table(name = "orders")
public class Order extends BaseModel {
public enum Status {
NEW,
APPROVED,
SHIPPED,
COMPLETE
}
@Enumerated(EnumType.STRING)
Status status = Status.NEW;
LocalDate orderDate;
@ManyToOne(cascade = CascadeType.PERSIST)
Customer customer;
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public LocalDate getOrderDate() {
return orderDate;
}
public void setOrderDate(LocalDate orderDate) {
this.orderDate = orderDate;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
}
@@ -1,11 +0,0 @@
ebean.ddl.generate=true
ebean.ddl.run=true
datasource.default=h2
datasource.h2.username=sa
datasource.h2.password=
datasource.h2.url=jdbc:h2:mem:h2AutoTune
datasource.pg.username=sa
datasource.pg.password=
datasource.pg.url=jdbc:h2:mem:h2AutoTune
@@ -1,21 +0,0 @@
<configuration scan="true" scanPeriod="10 seconds">
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>TRACE</level>
</filter>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="STDOUT"/>
</root>
<logger name="io.ebean.docker" level="TRACE"/>
<!-- <logger name="io.ebean.DDL" level="DEBUG"/>-->
<!-- <logger name="io.ebean.SQL" level="TRACE"/>-->
<!-- <logger name="io.ebean.TXN" level="TRACE"/>-->
<!-- <logger name="io.ebean.SUM" level="TRACE"/>-->
</configuration>
-162
View File
@@ -1,162 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.11.3</version>
</parent>
<name>ebean bom</name>
<description>ebean bill of materials pom</description>
<artifactId>ebean-bom</artifactId>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<!-- dependencies external to this ebean.git build -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-runner</artifactId>
<version>${ebean-ddl-runner.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration-auto</artifactId>
<version>${ebean-migration-auto.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>${ebean-migration.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource-api</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-agent</artifactId>
<version>${ebean-agent.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>${ebean-maven-plugin.version}</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test-docker</artifactId>
<version>${ebean-test-docker.version}</version>
</dependency>
<!-- modules -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-xml</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-autotune</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-querybean</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>querybean-generator</artifactId>
<version>12.11.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>kotlin-querybean-generator</artifactId>
<version>12.11.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test</artifactId>
<version>12.11.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-postgis</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-redis</artifactId>
<version>12.11.3</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
-31
View File
@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.11.3</version>
</parent>
<artifactId>ebean-core-type</artifactId>
<name>ebean core type</name>
<description>ebean scalar types api</description>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
@@ -1,177 +0,0 @@
package io.ebean.core.type;
import java.io.InputStream;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.List;
/**
* Data binder for ScalarTypes generally to an underlying PreparedStatement.
*/
public interface DataBinder {
/**
* Add something to the binding log.
*/
StringBuilder append(Object entry);
/**
* Return the binding log.
*/
StringBuilder log();
/**
* Close the underlying prepared statement.
*/
void close() throws SQLException;
/**
* Return the current position. Effectively column binding position.
*/
int currentPos();
/**
* Return the next position.
*/
int nextPos();
/**
* Decrement the position.
*/
void decrementPos();
/**
* Execute as a dml statement.
*/
int executeUpdate() throws SQLException;
/**
* Return the underlying PreparedStatement.
*/
PreparedStatement getPstmt();
/**
* Return any inputStreams that have been bound (and should be closed).
* This is used for batched statement execution only.
*/
List<InputStream> getInputStreams();
/**
* Bind an object.
*/
void setObject(Object value) throws SQLException;
/**
* Bind an object with given sql type.
*/
void setObject(Object value, int sqlType) throws SQLException;
/**
* Bind null.
*/
void setNull(int jdbcType) throws SQLException;
/**
* Bind a string value.
*/
void setString(String value) throws SQLException;
/**
* Bind a int value.
*/
void setInt(int value) throws SQLException;
/**
* Bind a long value.
*/
void setLong(long value) throws SQLException;
/**
* Bind a short value.
*/
void setShort(short value) throws SQLException;
/**
* Bind a float value.
*/
void setFloat(float value) throws SQLException;
/**
* Bind a double value.
*/
void setDouble(double value) throws SQLException;
/**
* Bind a BigDecimal value.
*/
void setBigDecimal(BigDecimal value) throws SQLException;
/**
* Bind a date value.
*/
void setDate(java.sql.Date value) throws SQLException;
/**
* Bind a timestamp value.
*/
void setTimestamp(Timestamp value) throws SQLException;
/**
* Bind a time value.
*/
void setTime(Time value) throws SQLException;
/**
* Bind a boolean value.
*/
void setBoolean(boolean value) throws SQLException;
/**
* Bind a byte array value.
*/
void setBytes(byte[] value) throws SQLException;
/**
* Bind a byte value.
*/
void setByte(byte value) throws SQLException;
/**
* Bind a char value.
*/
void setChar(char value) throws SQLException;
/**
* Bind a InputStream value.
*/
void setBinaryStream(InputStream inputStream, long length) throws SQLException;
/**
* Bind a byte array value.
*/
void setBlob(byte[] bytes) throws SQLException;
/**
* Bind a string clob value.
*/
void setClob(String content) throws SQLException;
/**
* Bind an array value.
*/
void setArray(String arrayType, Object[] elements) throws SQLException;
/**
* Push json from dirty detection to be available for binding.
*/
void pushJson(String json);
/**
* Pop json made during dirty detection for scalarType binding.
*/
String popJson();
}
@@ -1,16 +0,0 @@
package io.ebean.core.type;
import io.ebean.config.DatabaseConfig;
import java.util.List;
/**
* A factory that provides extra types to Ebean.
*/
public interface ExtraTypeFactory {
/**
* Provide extra types to Ebean.
*/
List<? extends ScalarType<?>> createTypes(DatabaseConfig config, Object objectMapper);
}
-375
View File
@@ -1,375 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>ebean-parent</artifactId>
<groupId>io.ebean</groupId>
<version>12.11.3</version>
</parent>
<artifactId>ebean-core</artifactId>
<packaging>jar</packaging>
<name>ebean core</name>
<description>ebean core module</description>
<url>https://ebean.io/</url>
<scm>
<developerConnection>scm:git:git@github.com:ebean-orm/ebean.git</developerConnection>
<tag>ebean-parent-12.11.3</tag>
</scm>
<profiles>
<profile>
<id>db2</id>
<dependencies>
<!-- https://mvnrepository.com/artifact/com.ibm.db2/jcc -->
<dependency>
<groupId>com.ibm.db2</groupId>
<artifactId>jcc</artifactId>
<version>11.5.5.0</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
</profiles>
<dependencies>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-runner</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>classpath-scanner</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration-auto</artifactId>
<version>1.1</version>
</dependency>
<!-- keep testing in core using ebean-ddl-generator & ebean-migration -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-migration</artifactId>
<version>12.4.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-ddl-generator</artifactId>
<version>12.11.0</version>
<scope>test</scope>
</dependency>
<!-- test scope for supporting ebean-ddl-generator -->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-api</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-core-type</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-externalmapping-api</artifactId>
<version>12.11.3</version>
</dependency>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>4.8-1</version>
</dependency>
<!--
Class retention Nonnull and Nullable annotations
to assist with IDE auto-completion with Ebean API
-->
<dependency>
<groupId>io.avaje</groupId>
<artifactId>avaje-jsr305</artifactId>
<version>1.0</version>
<scope>provided</scope>
</dependency>
<!-- Provided scope so that the H2HistoryTrigger can live in Ebean core
and not require a separate module for it -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.199</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.transaction</groupId>
<artifactId>jta</artifactId>
<version>1.1</version>
<optional>true</optional>
</dependency>
<!-- validation annotations Size etc -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.0.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.7</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
<optional>true</optional>
</dependency>
<!-- Jackson core used internally by Ebean -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<!-- Provided scope for Postgres JSON/JSONB support -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.20</version>
<optional>true</optional>
</dependency>
<!-- Test scope -->
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-datasource</artifactId>
<version>${ebean-datasource.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.nuodb.jdbc</groupId>
<artifactId>nuodb-jdbc</artifactId>
<version>20.2.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.oracle.ojdbc</groupId>
<artifactId>ojdbc10</artifactId>
<version>19.3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.ebean</groupId>
<artifactId>ebean-test-docker</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.15.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hsqldb</groupId>
<artifactId>hsqldb</artifactId>
<version>2.3.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
<version>7.2.2.jre8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.17</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mariadb.jdbc</groupId>
<artifactId>mariadb-java-client</artifactId>
<version>2.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.sap.cloud.db.jdbc</groupId>
<artifactId>ngdbc</artifactId>
<version>2.3.48</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.avaje.composite</groupId>
<artifactId>junit</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.avaje</groupId>
<artifactId>mod-uuid</artifactId>
<version>1.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.ebean</groupId>
<artifactId>ebean-maven-plugin</artifactId>
<version>${ebean-maven-plugin.version}</version>
<executions>
<execution>
<id>test</id>
<phase>process-test-classes</phase>
<configuration>
<transformArgs>debug=0</transformArgs>
</configuration>
<goals>
<goal>testEnhance</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M4</version>
<configuration>
<useSystemClassLoader>false</useSystemClassLoader>
<trimStackTrace>false</trimStackTrace>
<failIfNoTests>false</failIfNoTests>
<includes>
<include>**/Test*.java</include>
<include>**/*Test.java</include>
<include>**/*Tests.java</include>
</includes>
<systemProperties>
<property>
<!-- transfer datasource.default parameter -->
<name>datasource.default</name>
<value>${datasource.default}</value>
</property>
<property>
<!-- transfer dbClockDelta parameter -->
<name>dbClockDelta</name>
<value>${dbClockDelta}</value>
</property>
</systemProperties>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.5</version>
<configuration>
<archive>
<manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<doctitle>Ebean 12</doctitle>
<overview>src/main/java/io/ebean/overview.html</overview>
<excludePackageNames>io.ebeaninternal.*:io.ebeanservice:io.ebean.common:io.ebean.bean:io.ebean.service:io.ebean.metric:io.ebean.util:io.ebean.config.properties:io.ebean.config.dbplatform</excludePackageNames>
<linksource>true</linksource>
<overview>src/main/java/com/avaje/ebean/overview.html</overview>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -1,35 +0,0 @@
package io.ebeaninternal.api;
import java.util.ArrayList;
import java.util.List;
/**
* BindValues used for L2 query cache key matching.
* <p>
* The equals/hashCode implementation must meet the requirement that the query bind values
* match for L2 query cache hit (given the query plan hash is already a match).
*/
public final class BindValuesKey {
private final List<Object> values = new ArrayList<>();
/**
* Add a bind value.
*/
public BindValuesKey add(Object value) {
values.add(value);
return this;
}
@Override
public boolean equals(Object obj) {
return obj instanceof BindValuesKey && ((BindValuesKey) obj).values.equals(values);
}
@Override
public int hashCode() {
return values.hashCode();
}
}
@@ -1,25 +0,0 @@
package io.ebeaninternal.api;
import java.util.Collection;
import java.util.List;
/**
* Process Cache lookup by Id(s).
*/
public interface CacheIdLookup<T> {
/**
* Return the Id values to lookup against the L2 cache.
*/
Collection<?> idValues();
/**
* Remove the hits returning the beans fetched from L2 cache.
*/
List<T> removeHits(BeanCacheResult<T> cacheResult);
/**
* Return true if all beans where found in L2 cache.
*/
boolean allHits();
}
@@ -1,38 +0,0 @@
package io.ebeaninternal.api;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* Used for bean cache lookup with a single id value.
*/
public final class CacheIdLookupSingle<T> implements CacheIdLookup<T> {
private final Object idValue;
private boolean found;
public CacheIdLookupSingle(Object idValue) {
this.idValue = idValue;
}
@Override
public Collection<?> idValues() {
return Collections.singleton(idValue);
}
@Override
public List<T> removeHits(BeanCacheResult<T> cacheResult) {
final List<BeanCacheResult.Entry<T>> hits = cacheResult.hits();
if (hits.size() == 1) {
found = true;
return Collections.singletonList(hits.get(0).getBean());
}
return Collections.emptyList();
}
@Override
public boolean allHits() {
return found;
}
}
@@ -1,15 +0,0 @@
package io.ebeaninternal.api;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.server.type.GeoTypeBinder;
/**
* Provider of Geometry type binder support.
*/
public interface GeoTypeProvider {
/**
* Create a binder for binding geometry types.
*/
GeoTypeBinder createBinder(DatabaseConfig config);
}
@@ -1,16 +0,0 @@
package io.ebeaninternal.api;
import io.ebean.bean.BeanCollection;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
/**
* Controls the loading of ManyToOne and OneToOne relationships.
*/
public interface LoadBeanContext extends LoadSecondaryQuery {
/**
* Register a BeanCollection into the load context.
*/
void register(BeanPropertyAssocMany<?> many, BeanCollection<?> collection);
}
@@ -1,17 +0,0 @@
package io.ebeaninternal.api;
import io.ebean.bean.EntityBean;
/**
* SPI interface for underlying BeanDescriptor.
*/
public interface SpiBeanType {
/**
* Return true if the bean contains a many property that has modifications.
* <p>
* That is a ManyToMany or a OneToMany with orphan removal with additions
* or removals from the collection.
*/
boolean isToManyDirty(EntityBean bean);
}
@@ -1,13 +0,0 @@
package io.ebeaninternal.api;
/**
* Manager of SpiBeanTypes.
*/
public interface SpiBeanTypeManager {
/**
* Return the bean type for the given entity class.
*/
SpiBeanType getBeanType(Class<?> entityType);
}
@@ -1,26 +0,0 @@
package io.ebeaninternal.api;
import javax.persistence.PersistenceException;
import io.ebean.CancelableQuery;
/**
* Cancellable query, that has a delegate.
*
* @author Roland Praml, FOCONIS AG
*
*/
public interface SpiCancelableQuery extends CancelableQuery {
/**
* Checks if the query was cancelled.
* @throws PersistenceException if query was cancelled.
*/
void checkCancelled();
/**
* Set the underlying cancelable query (with the PreparedStatement).
*/
void setCancelableQuery(CancelableQuery cancelableQuery);
}
@@ -1,15 +0,0 @@
package io.ebeaninternal.api;
/**
* DDL generate and run for drop all/create all.
*/
public interface SpiDdlGenerator {
/**
* Generate and run the DDL for drop-all and create-all scripts.
* <p>
* Run based on on property settings for ebean.ddl.generate and ebean.ddl.run etc.
*/
void execute(boolean online);
}
@@ -1,13 +0,0 @@
package io.ebeaninternal.api;
/**
* Provides the DDL Generator for create-all/drop-all.
*/
public interface SpiDdlGeneratorProvider {
/**
* Provide the DDL generator.
*/
SpiDdlGenerator generator(SpiEbeanServer server);
}
@@ -1,17 +0,0 @@
package io.ebeaninternal.api;
import io.ebean.bean.PersistenceContext;
import java.util.List;
/**
* SPI extension to PersistenceContext.
*/
public interface SpiPersistenceContext extends PersistenceContext {
/**
* Return the list of dirty beans held by this persistence context.
*/
List<Object> dirtyBeans(SpiBeanTypeManager manager);
}
@@ -1,27 +0,0 @@
package io.ebeaninternal.api;
import io.ebean.FetchConfig;
import io.ebeaninternal.server.querydefn.OrmQueryDetail;
import java.util.Set;
/**
* Query select and fetch properties (that avoids parsing).
*/
public interface SpiQueryFetch {
/**
* Specify the select properties.
*/
void selectProperties(Set<String> properties);
/**
* Specify the fetch properties for the given path.
*/
void fetchProperties(String name, Set<String> properties, FetchConfig config);
/**
* Add a nested fetch graph.
*/
void addNested(String name, OrmQueryDetail nestedDetail, FetchConfig config);
}
@@ -1,26 +0,0 @@
package io.ebeaninternal.json;
import io.ebean.ModifyAwareType;
import java.io.Serializable;
/**
* Detects when content has been modified and as such needs to be persisted (included in an update).
*/
public final class ModifyAwareFlag implements ModifyAwareType, Serializable {
private static final long serialVersionUID = 1;
private boolean markedDirty;
@Override
public boolean isMarkedDirty() {
return markedDirty;
}
@Override
public void setMarkedDirty(boolean markedDirty) {
this.markedDirty = markedDirty;
}
}
@@ -1,9 +0,0 @@
package io.ebeaninternal.server.autotune;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.api.SpiEbeanServer;
public interface AutoTuneServiceProvider {
AutoTuneService create(SpiEbeanServer server, DatabaseConfig config);
}
@@ -1,34 +0,0 @@
package io.ebeaninternal.server.autotune;
import io.ebeaninternal.api.SpiQuery;
/**
* Noop service when AutoTuneService is not available.
*/
public final class NoAutoTuneService implements AutoTuneService {
@Override
public void startup() {
// do nothing
}
@Override
public boolean tuneQuery(SpiQuery<?> query) {
return false;
}
@Override
public void collectProfiling() {
// do nothing
}
@Override
public void reportProfiling() {
// do nothing
}
@Override
public void shutdown() {
// do nothing
}
}
@@ -1,54 +0,0 @@
package io.ebeaninternal.server.cache;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
/**
* Bean Id value plus discriminator type.
* <p>
* Put into L2 cache such that we know the type of a bean with inheritance.
*/
public final class CachedBeanId implements Externalizable {
private String discValue;
private Object id;
public CachedBeanId(String discValue, Object id) {
this.discValue = discValue;
this.id = id;
}
/**
* Construct from serialisation.
*/
public CachedBeanId() {
}
@Override
public void writeExternal(ObjectOutput out) throws IOException {
out.writeUTF(discValue);
out.writeObject(id);
}
@Override
public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
discValue = in.readUTF();
id = in.readObject();
}
@Override
public String toString() {
return discValue + ":" + id;
}
public String getDiscValue() {
return discValue;
}
public Object getId() {
return id;
}
}
@@ -1,262 +0,0 @@
package io.ebeaninternal.server.core;
import io.ebean.config.ContainerConfig;
import io.ebean.config.DatabaseConfig;
import io.ebean.config.DatabaseConfigProvider;
import io.ebean.config.ModuleInfoLoader;
import io.ebean.config.ServerConfig;
import io.ebean.config.ServerConfigProvider;
import io.ebean.config.TenantMode;
import io.ebean.config.UnderscoreNamingConvention;
import io.ebean.config.dbplatform.DatabasePlatform;
import io.ebean.config.dbplatform.h2.H2Platform;
import io.ebean.event.ShutdownManager;
import io.ebean.service.SpiContainer;
import io.ebeaninternal.api.DbOffline;
import io.ebeaninternal.api.SpiBackgroundExecutor;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.server.cluster.ClusterManager;
import io.ebeaninternal.server.core.bootup.BootupClassPathSearch;
import io.ebeaninternal.server.core.bootup.BootupClasses;
import io.ebeaninternal.server.executor.DefaultBackgroundExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.persistence.PersistenceException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.ServiceLoader;
import java.util.concurrent.locks.ReentrantLock;
/**
* Default Server side implementation of ServerFactory.
*/
public final class DefaultContainer implements SpiContainer {
private static final Logger logger = LoggerFactory.getLogger("io.ebean.DB");
private final ReentrantLock lock = new ReentrantLock();
private final ClusterManager clusterManager;
public DefaultContainer(ContainerConfig containerConfig) {
this.clusterManager = new ClusterManager(containerConfig);
// register so that we can shutdown any Ebean wide
// resources such as clustering
ShutdownManager.registerContainer(this);
}
@Override
public void shutdown() {
clusterManager.shutdown();
ShutdownManager.shutdown();
}
/**
* Create the server reading configuration information from ebean.properties.
*/
@Override
public SpiEbeanServer createServer(String name) {
DatabaseConfig config = new DatabaseConfig();
config.setName(name);
config.loadFromProperties();
return createServer(config);
}
private SpiBackgroundExecutor createBackgroundExecutor(DatabaseConfig config) {
String namePrefix = "ebean-" + config.getName();
int schedulePoolSize = config.getBackgroundExecutorSchedulePoolSize();
int shutdownSecs = config.getBackgroundExecutorShutdownSecs();
return new DefaultBackgroundExecutor(schedulePoolSize, shutdownSecs, namePrefix);
}
/**
* Create the implementation from the configuration.
*/
@Override
public SpiEbeanServer createServer(DatabaseConfig config) {
lock.lock();
try {
long start = System.currentTimeMillis();
applyConfigServices(config);
setNamingConvention(config);
BootupClasses bootupClasses = bootupClasses(config);
boolean online = true;
if (config.isDocStoreOnly()) {
config.setDatabasePlatform(new H2Platform());
} else {
TenantMode tenantMode = config.getTenantMode();
if (TenantMode.DB != tenantMode) {
setDataSource(config);
if (!tenantMode.isDynamicDataSource()) {
// check the autoCommit and Transaction Isolation
online = checkDataSource(config);
}
}
}
// determine database platform (Oracle etc)
setDatabasePlatform(config);
if (config.getDbEncrypt() != null) {
// use a configured DbEncrypt rather than the platform default
config.getDatabasePlatform().setDbEncrypt(config.getDbEncrypt());
}
// inform the NamingConvention of the associated DatabasePlatform
config.getNamingConvention().setDatabasePlatform(config.getDatabasePlatform());
// executor and l2 caching service setup early (used during server construction)
SpiBackgroundExecutor executor = createBackgroundExecutor(config);
InternalConfiguration c = new InternalConfiguration(online, clusterManager, executor, config, bootupClasses);
DefaultServer server = new DefaultServer(c, c.cacheManager());
// generate and run DDL if required plus other plugins
if (!DbOffline.isGenerateMigration()) {
startServer(online, server);
}
DbOffline.reset();
logger.info("started database[{}] platform[{}] in {}ms", config.getName(), config.getDatabasePlatform().getPlatform(), System.currentTimeMillis() - start);
return server;
} finally {
lock.unlock();
}
}
private void applyConfigServices(DatabaseConfig config) {
if (config.isDefaultServer()) {
boolean appliedConfig = false;
for (DatabaseConfigProvider configProvider : ServiceLoader.load(DatabaseConfigProvider.class)) {
configProvider.apply(config);
appliedConfig = true;
}
if (!appliedConfig && config instanceof ServerConfig) {
for (ServerConfigProvider configProvider : ServiceLoader.load(ServerConfigProvider.class)) {
configProvider.apply((ServerConfig)config);
}
}
}
if (config.isAutoLoadModuleInfo()) {
// auto register entity classes
for (ModuleInfoLoader loader : ServiceLoader.load(ModuleInfoLoader.class)) {
config.addAll(loader.classesFor(config.getName(), config.isDefaultServer()));
}
}
}
private void startServer(boolean online, DefaultServer server) {
server.executePlugins(online);
// initialise prior to registering with clusterManager
server.initialise();
if (online) {
if (clusterManager.isClustering()) {
clusterManager.registerServer(server);
}
}
// start any services after registering with clusterManager
server.start();
}
/**
* Get the entities, scalarTypes, Listeners etc combining the class registered
* ones with the already created instances.
*/
private BootupClasses bootupClasses(DatabaseConfig config) {
BootupClasses bootup = bootupClasses1(config);
bootup.addIdGenerators(config.getIdGenerators());
bootup.addPersistControllers(config.getPersistControllers());
bootup.addPostLoaders(config.getPostLoaders());
bootup.addPostConstructListeners(config.getPostConstructListeners());
bootup.addFindControllers(config.getFindControllers());
bootup.addPersistListeners(config.getPersistListeners());
bootup.addQueryAdapters(config.getQueryAdapters());
bootup.addServerConfigStartup(config.getServerConfigStartupListeners());
bootup.addChangeLogInstances(config);
bootup.runServerConfigStartup(config);
return bootup;
}
/**
* Get the class based entities, scalarTypes, Listeners etc.
*/
private BootupClasses bootupClasses1(DatabaseConfig config) {
List<Class<?>> entityClasses = config.getClasses();
if (config.isDisableClasspathSearch() || (entityClasses != null && !entityClasses.isEmpty())) {
// use classes we explicitly added via configuration
return new BootupClasses(entityClasses);
}
return BootupClassPathSearch.search(config);
}
/**
* Set the naming convention to underscore if it has not already been set.
*/
private void setNamingConvention(DatabaseConfig config) {
if (config.getNamingConvention() == null) {
config.setNamingConvention(new UnderscoreNamingConvention());
}
}
/**
* Set the DatabasePlatform if it has not already been set.
*/
private void setDatabasePlatform(DatabaseConfig config) {
DatabasePlatform platform = config.getDatabasePlatform();
if (platform == null) {
if (config.getTenantMode().isDynamicDataSource()) {
throw new IllegalStateException("DatabasePlatform must be explicitly set on DatabaseConfig for TenantMode "+config.getTenantMode());
}
// automatically determine the platform
platform = new DatabasePlatformFactory().create(config);
config.setDatabasePlatform(platform);
}
platform.configure(config.getPlatformConfig());
}
/**
* Set the DataSource if it has not already been set.
*/
private void setDataSource(DatabaseConfig config) {
if (isOfflineMode(config)) {
logger.debug("... DbOffline using platform [{}]", DbOffline.getPlatform());
} else {
InitDataSource.init(config);
}
}
private boolean isOfflineMode(DatabaseConfig config) {
return config.isDbOffline() || DbOffline.isSet();
}
/**
* Check the autoCommit and Transaction Isolation levels of the DataSource.
* <p>
* If autoCommit is true this could be a real problem.
* </p>
* <p>
* If the Isolation level is not READ_COMMITTED then optimistic concurrency
* checking may not work as expected.
* </p>
*/
private boolean checkDataSource(DatabaseConfig config) {
if (isOfflineMode(config)) {
return false;
}
if (config.getDataSource() == null) {
if (config.getDataSourceConfig().isOffline()) {
// this is ok - offline DDL generation etc
return false;
}
throw new RuntimeException("DataSource not set?");
}
if (config.skipDataSourceCheck()) {
return true;
}
try (Connection connection = config.getDataSource().getConnection()) {
if (connection.getAutoCommit()) {
logger.warn("DataSource [{}] has autoCommit defaulting to true!", config.getName());
}
return true;
} catch (SQLException ex) {
throw new PersistenceException(ex);
}
}
}
@@ -1,25 +0,0 @@
package io.ebeaninternal.server.core;
import io.ebean.config.QueryPlanCapture;
import io.ebean.config.QueryPlanListener;
import io.ebean.meta.MetaQueryPlan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
final class DefaultQueryPlanListener implements QueryPlanListener {
static final QueryPlanListener INSTANT = new DefaultQueryPlanListener();
private static final Logger log = LoggerFactory.getLogger("io.ebean.QUERYPLAN");
@Override
public void process(QueryPlanCapture capture) {
// better to log this in JSON form?
String dbName = capture.getDatabase().name();
for (MetaQueryPlan plan : capture.getPlans()) {
log.info("queryPlan db:{} label:{} queryTimeMicros:{} loc:{} sql:{} bind:{} plan:{}",
dbName, plan.label(), plan.queryTimeMicros(), plan.profileLocation(),
plan.sql(), plan.bind(), plan.plan());
}
}
}
@@ -1,8 +0,0 @@
package io.ebeaninternal.server.core;
/**
* Used to create column alias for encrypted columns.
*/
public interface EncryptAlias {
String PREFIX = "zx__";
}
@@ -1,144 +0,0 @@
package io.ebeaninternal.server.core;
import io.ebean.config.DatabaseConfig;
import io.ebean.datasource.DataSourceAlertFactory;
import io.ebean.datasource.DataSourceConfig;
import io.ebean.datasource.DataSourceFactory;
import io.ebean.datasource.DataSourcePoolListener;
import javax.persistence.PersistenceException;
import javax.sql.DataSource;
/**
* Initialise the main DataSource and read-only DataSource.
*/
final class InitDataSource {
private final JndiDataSourceLookup jndiDataSourceFactory = new JndiDataSourceLookup();
private final DatabaseConfig config;
/**
* Create and set the main DataSource and read-only DataSource.
*/
static void init(DatabaseConfig config) {
new InitDataSource(config).initialise();
}
InitDataSource(DatabaseConfig config) {
this.config = config;
}
private void initialise() {
if (config.getDataSource() == null) {
config.setDataSource(initDataSource());
}
if (config.getReadOnlyDataSource() == null) {
config.setReadOnlyDataSource(initReadOnlyDataSource());
}
}
/**
* Initialise the "main" read write DataSource from configuration.
*/
private DataSource initDataSource() {
final String jndiName = config.getDataSourceJndiName();
if (jndiName != null) {
return jndiDataSource(jndiName);
}
return createFromConfig(config.getDataSourceConfig(), false);
}
private DataSource jndiDataSource(String jndiName) {
DataSource ds = jndiDataSourceFactory.lookup(jndiName);
if (ds == null) {
throw new PersistenceException("JNDI lookup for DataSource " + jndiName + " returned null.");
}
return ds;
}
/**
* Initialise the "read only" DataSource from configuration.
*/
private DataSource initReadOnlyDataSource() {
DataSourceConfig roConfig = readOnlyConfig();
return roConfig == null ? null : createFromConfig(roConfig, true);
}
DataSourceConfig readOnlyConfig() {
DataSourceConfig roConfig = config.getReadOnlyDataSourceConfig();
if (roConfig == null) {
// it has explicitly been set to null, not expected but ok
return null;
}
if (urlSet(roConfig.getUrl())) {
return roConfig;
}
// convenient alternate place to set the read-only url
final String readOnlyUrl = config.getDataSourceConfig().getReadOnlyUrl();
if (urlSet(readOnlyUrl)) {
roConfig.setUrl(readOnlyUrl);
return roConfig;
}
if (config.isAutoReadOnlyDataSource()) {
roConfig.setUrl(null); // blank out in case it is "none"
return roConfig;
} else {
return null;
}
}
private boolean urlSet(String url) {
return url != null && !"none".equalsIgnoreCase(url) && !url.trim().isEmpty();
}
private DataSource createFromConfig(DataSourceConfig dsConfig, boolean readOnly) {
if (dsConfig == null) {
throw new PersistenceException("No DataSourceConfig defined for " + config.getName());
}
if (dsConfig.isOffline()) {
if (config.getDatabasePlatformName() == null) {
throw new PersistenceException("You MUST specify a DatabasePlatformName on DatabaseConfig when offline");
}
return null;
}
attachAlert(dsConfig);
attachListener(dsConfig);
if (readOnly) {
// setup to use AutoCommit such that we skip explicit commit
dsConfig.setAutoCommit(true);
dsConfig.setReadOnly(true);
dsConfig.setDefaults(config.getDataSourceConfig());
dsConfig.setIsolationLevel(config.getDataSourceConfig().getIsolationLevel());
}
return create(dsConfig, readOnly);
}
private DataSource create(DataSourceConfig dsConfig, boolean readOnly) {
String poolName = config.getName() + (readOnly ? "-ro" : "");
return DataSourceFactory.create(poolName, dsConfig);
}
/**
* Attach DataSourceAlert via service loader if present.
*/
private void attachAlert(DataSourceConfig dsConfig) {
DataSourceAlertFactory alertFactory = config.service(DataSourceAlertFactory.class);
if (alertFactory != null) {
dsConfig.setAlert(alertFactory.createAlert());
}
}
/**
* Create and attach a DataSourcePoolListener if it has been specified via properties and there is not one already attached.
*/
private void attachListener(DataSourceConfig dsConfig) {
if (dsConfig.getListener() == null) {
String poolListener = dsConfig.getPoolListener();
if (poolListener != null) {
dsConfig.setListener((DataSourcePoolListener) config.getClassLoadConfig().newInstance(poolListener));
}
}
}
}
@@ -1,70 +0,0 @@
package io.ebeaninternal.server.core;
import io.ebeaninternal.server.dto.DtoNamedQueries;
import io.ebeaninternal.xmapping.api.XmapDto;
import io.ebeaninternal.xmapping.api.XmapEbean;
import io.ebeaninternal.xmapping.api.XmapRawSql;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Reads the Xml deployment information.
*/
final class InternalConfigXmlMap {
private static final Logger log = LoggerFactory.getLogger(InternalConfigXmlMap.class);
private final List<XmapEbean> xmlEbeanList;
private final ClassLoader classLoader;
private final Map<Class<?>, DtoNamedQueries> dtoNamedQueries = new HashMap<>();
InternalConfigXmlMap(List<XmapEbean> xmlEbeanList, ClassLoader classLoader) {
this.xmlEbeanList = xmlEbeanList;
this.classLoader = classLoader;
initDtoMapping();
}
void initDtoMapping() {
if (xmlEbeanList != null) {
for (XmapEbean mapping : xmlEbeanList) {
List<XmapDto> dtoList = mapping.getDto();
for (XmapDto dto : dtoList) {
readDtoMapping(dto);
}
}
}
}
/**
* Return the XML deployment information for entity beans.
*/
List<XmapEbean> xmlDeployment() {
return xmlEbeanList;
}
/**
* Return the named queries for Dto beans.
*/
Map<Class<?>, DtoNamedQueries> readDtoMapping() {
return dtoNamedQueries;
}
private void readDtoMapping(XmapDto dto) {
Class<?> dtoClass;
try {
dtoClass = Class.forName(dto.getClazz(), false, classLoader);
} catch (Exception e) {
log.error("Could not load dto bean class " + dto.getClazz() + " for ebean xml entry");
return;
}
DtoNamedQueries namedQueries = dtoNamedQueries.computeIfAbsent(dtoClass, aClass -> new DtoNamedQueries());
for (XmapRawSql sql : dto.getRawSql()) {
namedQueries.addRawSql(sql.getName(), sql.getQuery());
}
}
}
@@ -1,14 +0,0 @@
package io.ebeaninternal.server.core;
import java.sql.SQLException;
/**
* Read a row building a result for that row.
*/
public interface RowReader<T> {
/**
* Build and return a result for a row.
*/
T read() throws SQLException;
}
@@ -1,58 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.bean.EntityBean;
import io.ebean.core.type.DataReader;
import io.ebean.text.TextException;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import javax.persistence.PersistenceException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Map;
/**
* A DbJson property that does not use Jackson ObjectMapper.
*/
public class BeanPropertyJsonBasic extends BeanProperty {
public BeanPropertyJsonBasic(BeanDescriptor<?> descriptor, DeployBeanProperty deploy) {
super(descriptor, deploy);
}
protected BeanPropertyJsonBasic(BeanProperty source, BeanPropertyOverride override) {
super(source, override);
}
@Override
public BeanProperty override(BeanPropertyOverride override) {
return new BeanPropertyJsonBasic(this, override);
}
protected Object checkForEmpty(EntityBean bean) {
final Object value = getValue(bean);
if (value instanceof Collection && ((Collection<?>) value).isEmpty()
|| value instanceof Map && ((Map<?, ?>) value).isEmpty()) {
return value;
}
return null;
}
@Override
public Object readSet(DataReader reader, EntityBean bean) throws SQLException {
try {
Object value = scalarType.read(reader);
if (value == null) {
value = checkForEmpty(bean);
}
if (bean != null) {
setValue(bean, value);
}
return value;
} catch (TextException e) {
throw e;
} catch (Exception e) {
throw new PersistenceException("Error readSet on " + descriptor + "." + name, e);
}
}
}
@@ -1,222 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.annotation.MutationDetection;
import io.ebean.bean.EntityBean;
import io.ebean.bean.EntityBeanIntercept;
import io.ebean.bean.MutableValueInfo;
import io.ebean.bean.MutableValueNext;
import io.ebean.bean.PersistenceContext;
import io.ebean.core.type.DataReader;
import io.ebean.core.type.ScalarType;
import io.ebean.text.TextException;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import io.ebeaninternal.server.util.Checksum;
import javax.persistence.PersistenceException;
import java.sql.SQLException;
import java.util.Objects;
/**
* Handle json property with MutationDetection of SOURCE or HASH only.
*/
public final class BeanPropertyJsonMapper extends BeanPropertyJsonBasic {
private final boolean sourceDetection;
public BeanPropertyJsonMapper(BeanDescriptor<?> desc, DeployBeanProperty deployProp) {
super(desc, deployProp);
this.sourceDetection = deployProp.getMutationDetection() == MutationDetection.SOURCE;
}
private BeanPropertyJsonMapper(BeanPropertyJsonMapper source, BeanPropertyOverride override) {
super(source, override);
this.sourceDetection = source.sourceDetection;
}
@Override
public BeanProperty override(BeanPropertyOverride override) {
return new BeanPropertyJsonMapper(this, override);
}
@Override
public MutableValueInfo createMutableInfo(String json) {
if (sourceDetection) {
return new SourceMutableValue(scalarType, json);
} else {
return new ChecksumMutableValue(scalarType, json);
}
}
/**
* Next when no prior MutableValueInfo.
*/
private MutableValueNext next(String json) {
if (sourceDetection) {
return new SourceMutableValue(scalarType, json);
} else {
return new NextPair(json, new ChecksumMutableValue(scalarType, json));
}
}
/**
* Return true if the json property is considered dirty.
*/
@Override
boolean checkMutable(Object value, boolean alreadyDirty, EntityBeanIntercept ebi) {
// mutation detection based on json content or checksum of json content
// only perform serialisation to json once
final String json = scalarType.format(value);
final MutableValueInfo oldHash = ebi.mutableInfo(propertyIndex);
if (oldHash == null) {
if (value == null) {
return false; // no change, still null
}
ebi.mutableNext(propertyIndex, next(json));
return true;
}
// only perform compute of checksum/hash once (if checksum based)
final MutableValueNext next = oldHash.nextDirty(json);
if (next != null) {
ebi.mutableNext(propertyIndex, next);
return true;
}
return false;
}
@Override
public Object readSet(DataReader reader, EntityBean bean) throws SQLException {
try {
Object value = scalarType.read(reader);
if (value == null) {
value = checkForEmpty(bean);
}
if (bean != null) {
setValue(bean, value);
String json = reader.popJson();
if (json != null) {
final MutableValueInfo hash = createMutableInfo(json);
bean._ebean_getIntercept().mutableInfo(propertyIndex, hash);
}
}
return value;
} catch (TextException e) {
throw e;
} catch (Exception e) {
throw new PersistenceException("Error readSet on " + descriptor + "." + name, e);
}
}
@Override
public void setCacheDataValue(EntityBean bean, Object cacheData, PersistenceContext context) {
if (cacheData instanceof String) {
// parse back from string to support optimisation of java object serialisation
final String jsonContent = (String) cacheData;
final MutableValueInfo hash = createMutableInfo(jsonContent);
bean._ebean_getIntercept().mutableInfo(propertyIndex, hash);
cacheData = scalarType.parse(jsonContent);
}
setValue(bean, cacheData);
}
private static final class NextPair implements MutableValueNext {
private final String json;
private final MutableValueInfo next;
NextPair(String json, MutableValueInfo next) {
this.json = json;
this.next = next;
}
@Override
public String content() {
return json;
}
@Override
public MutableValueInfo info() {
return next;
}
}
/**
* Hold checksum of json source content to use for dirty detection.
* <p>
* Does not support rebuilding 'oldValue' as no original json content.
*/
private static final class ChecksumMutableValue implements MutableValueInfo {
private final ScalarType<?> parent;
private final long checksum;
ChecksumMutableValue(ScalarType<?> parent, String json) {
this.parent = parent;
this.checksum = Checksum.checksum(json);
}
/**
* Create with pre-computed checksum.
*/
ChecksumMutableValue(ScalarType<?> parent, long checksum) {
this.parent = parent;
this.checksum = checksum;
}
@Override
public MutableValueNext nextDirty(String json) {
final long nextChecksum = Checksum.checksum(json);
return nextChecksum == checksum ? null : new NextPair(json, new ChecksumMutableValue(parent, nextChecksum));
}
@Override
public boolean isEqualToObject(Object obj) {
return Checksum.checksum(parent.format(obj)) == checksum;
}
@Override
public Object get() {
return null; // cannot create object from json
}
}
/**
* Hold json source content. This supports rebuilding the 'oldValue'.
*/
private static final class SourceMutableValue implements MutableValueInfo, MutableValueNext {
private final String originalJson;
private final ScalarType<?> parent;
SourceMutableValue(ScalarType<?> parent, String json) {
this.parent = parent;
this.originalJson = json;
}
@Override
public MutableValueNext nextDirty(String json) {
return Objects.equals(originalJson, json) ? null : new SourceMutableValue(parent, json);
}
@Override
public boolean isEqualToObject(Object obj) {
return Objects.equals(originalJson, parent.format(obj));
}
@Override
public Object get() {
// rebuild the 'oldValue' for change log etc
return parent.parse(originalJson);
}
@Override
public String content() {
return originalJson;
}
@Override
public MutableValueInfo info() {
return this;
}
}
}
@@ -1,51 +0,0 @@
package io.ebeaninternal.server.deploy;
import io.ebean.util.StringHelper;
import io.ebeaninternal.server.core.InternString;
/**
* Used hold meta data when a bean property is overridden.
* <p>
* Typically this is for Embedded Beans.
* </p>
*/
final class BeanPropertyOverride {
private final String dbColumn;
private final boolean dbNullable;
private final int dbLength;
private final int dbScale;
private final String dbColumnDefn;
BeanPropertyOverride(String dbColumn, boolean dbNullable, int dbLength, int dbScale, String dbColumnDefn) {
this.dbColumn = InternString.intern(dbColumn);
this.dbNullable = dbNullable;
this.dbLength = dbLength;
this.dbScale = dbScale;
this.dbColumnDefn = dbColumnDefn;
}
String getDbColumn() {
return dbColumn;
}
boolean isDbNullable() {
return dbNullable;
}
int getDbLength() {
return dbLength;
}
int getDbScale() {
return dbScale;
}
String getDbColumnDefn() {
return dbColumnDefn;
}
String replace(String src, String srcDbColumn) {
return StringHelper.replace(src, srcDbColumn, dbColumn);
}
}
@@ -1,39 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.config.BeanNotRegisteredException;
import io.ebeaninternal.server.deploy.BeanDescriptorManager;
import io.ebeaninternal.server.deploy.BeanTable;
import io.ebeaninternal.server.deploy.meta.DeployBeanPropertyAssoc;
abstract class AnnotationAssoc extends AnnotationParser {
final BeanDescriptorManager factory;
AnnotationAssoc(DeployBeanInfo<?> info, ReadAnnotationConfig readConfig, BeanDescriptorManager factory) {
super(info, readConfig);
this.factory = factory;
}
void setTargetType(Class<?> targetType, DeployBeanPropertyAssoc<?> prop) {
if (!targetType.equals(void.class)) {
prop.setTargetType(targetType);
}
}
void setBeanTable(DeployBeanPropertyAssoc<?> prop) {
BeanTable assoc = getBeanTable(prop);
if (assoc == null) {
throw new BeanNotRegisteredException(errorMsgMissingBeanTable(prop.getTargetType(), prop.getFullBeanName()));
}
prop.setBeanTable(assoc);
}
BeanTable getBeanTable(DeployBeanPropertyAssoc<?> prop) {
return factory.getBeanTable(prop.getTargetType());
}
private String errorMsgMissingBeanTable(Class<?> type, String from) {
return "Error with association to [" + type + "] from [" + from + "]. Is " + type + " registered? See https://ebean.io/docs/trouble-shooting#not-registered";
}
}
@@ -1,75 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.annotation.DbMigration;
import io.ebean.annotation.Index;
import io.ebean.annotation.Indices;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import static io.ebean.util.AnnotationUtil.get;
final class AnnotationFind {
public static Set<JoinColumn> joinColumns(Field field) {
final JoinColumn col = get(field, JoinColumn.class);
if (col != null) {
return Collections.singleton(col);
}
final JoinColumns cols = get(field, JoinColumns.class);
if (cols != null) {
Set<JoinColumn> result = new LinkedHashSet<>();
Collections.addAll(result, cols.value());
return result;
}
return Collections.emptySet();
}
public static Set<AttributeOverride> attributeOverrides(Field field) {
final AttributeOverride ann = get(field, AttributeOverride.class);
if (ann != null) {
return Collections.singleton(ann);
}
final AttributeOverrides collection = get(field, AttributeOverrides.class);
if (collection != null) {
Set<AttributeOverride> result = new LinkedHashSet<>();
Collections.addAll(result, collection.value());
return result;
}
return Collections.emptySet();
}
public static Set<Index> indexes(Field field) {
final Index ann = get(field, Index.class);
if (ann != null) {
return Collections.singleton(ann);
}
final Indices collection = get(field, Indices.class);
if (collection != null) {
Set<Index> result = new LinkedHashSet<>();
Collections.addAll(result, collection.value());
return result;
}
return Collections.emptySet();
}
public static Set<DbMigration> dbMigrations(Field field) {
final DbMigration ann = get(field, DbMigration.class);
if (ann != null) {
return Collections.singleton(ann);
}
final DbMigration.List collection = get(field, DbMigration.List.class);
if (collection != null) {
Set<DbMigration> result = new LinkedHashSet<>();
Collections.addAll(result, collection.value());
return result;
}
return Collections.emptySet();
}
}
@@ -1,8 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
final class InitMetaJacksonAnnotation {
static void init(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(com.fasterxml.jackson.annotation.JacksonAnnotation.class);
}
}
@@ -1,129 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.annotation.Aggregation;
import io.ebean.annotation.Formula;
import io.ebean.annotation.Where;
import io.ebean.config.ClassLoadConfig;
import io.ebean.config.DatabaseConfig;
import io.ebeaninternal.server.deploy.generatedproperty.GeneratedPropertyFactory;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import javax.persistence.Column;
import java.util.HashSet;
import java.util.Set;
/**
* Configuration used when reading the deployment annotations.
*/
final class ReadAnnotationConfig {
private final GeneratedPropertyFactory generatedPropFactory;
private final String asOfViewSuffix;
private final String versionsBetweenSuffix;
private final boolean disableL2Cache;
private final boolean eagerFetchLobs;
private final boolean javaxValidationAnnotations;
private final boolean jakartaValidationAnnotations;
private final boolean jacksonAnnotations;
private final boolean idGeneratorAutomatic;
private final boolean useValidationNotNull;
private final ReadValidationAnnotations javaxValidation;
private final ReadValidationAnnotations jakartaValidation;
private final Set<Class<?>> metaAnnotations = new HashSet<>();
ReadAnnotationConfig(GeneratedPropertyFactory generatedPropFactory, String asOfViewSuffix, String versionsBetweenSuffix, DatabaseConfig config) {
this.generatedPropFactory = generatedPropFactory;
this.asOfViewSuffix = asOfViewSuffix;
this.versionsBetweenSuffix = versionsBetweenSuffix;
this.disableL2Cache = config.isDisableL2Cache();
this.eagerFetchLobs = config.isEagerFetchLobs();
this.idGeneratorAutomatic = config.isIdGeneratorAutomatic();
this.useValidationNotNull = config.isUseValidationNotNull();
ClassLoadConfig classLoadConfig = generatedPropFactory.getClassLoadConfig();
this.javaxValidationAnnotations = classLoadConfig.isJavaxValidationAnnotationsPresent();
this.jakartaValidationAnnotations = classLoadConfig.isJakartaValidationAnnotationsPresent();
this.jacksonAnnotations = classLoadConfig.isJacksonAnnotationsPresent();
this.metaAnnotations.add(Column.class);
this.metaAnnotations.add(Formula.class);
this.metaAnnotations.add(Formula.List.class);
this.metaAnnotations.add(Where.class);
this.metaAnnotations.add(Where.List.class);
this.metaAnnotations.add(Aggregation.class);
this.javaxValidation = javaxValidationAnnotations ? new ReadValidationAnnotationsJavax(this) : null;
this.jakartaValidation = jakartaValidationAnnotations ? new ReadValidationAnnotationsJakarta(this) : null;
if (jacksonAnnotations) {
InitMetaJacksonAnnotation.init(this);
}
}
void addMetaAnnotation(Class<?> annotation) {
metaAnnotations.add(annotation);
}
boolean checkValidationAnnotations() {
return javaxValidationAnnotations || jakartaValidationAnnotations;
}
GeneratedPropertyFactory getGeneratedPropFactory() {
return generatedPropFactory;
}
String getAsOfViewSuffix() {
return asOfViewSuffix;
}
String getVersionsBetweenSuffix() {
return versionsBetweenSuffix;
}
boolean isDisableL2Cache() {
return disableL2Cache;
}
boolean isEagerFetchLobs() {
return eagerFetchLobs;
}
boolean isIdGeneratorAutomatic() {
return idGeneratorAutomatic;
}
boolean isJacksonAnnotations() {
return jacksonAnnotations;
}
public Set<Class<?>> getMetaAnnotations() {
return metaAnnotations;
}
/**
* Return true if a NotNull validation annotation is on the property.
*/
boolean isValidationNotNull(DeployBeanProperty property) {
if (!useValidationNotNull) {
return false;
}
if (javaxValidation != null && javaxValidation.isValidationNotNull(property)) {
return true;
}
if (jakartaValidation != null && jakartaValidation.isValidationNotNull(property)) {
return true;
}
return false;
}
/**
* Return the max size of all validation @Size annotations.
*/
int maxValidationSize(DeployBeanProperty prop) {
int maxSize = 0;
if (javaxValidation != null) {
maxSize = Math.max(maxSize, javaxValidation.maxSize(prop));
}
if (jakartaValidation != null) {
maxSize = Math.max(maxSize, jakartaValidation.maxSize(prop));
}
return maxSize;
}
}
@@ -1,19 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
/**
* Reads validation NotNull and Size annotations for mapping.
*/
interface ReadValidationAnnotations {
/**
* Return true if the property has a NotNull validation annotation.
*/
boolean isValidationNotNull(DeployBeanProperty property);
/**
* Return the max value of the Size validation annotations on the property.
*/
int maxSize(DeployBeanProperty property);
}
@@ -1,51 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jakarta.validation.groups.Default;
import java.util.Collections;
import java.util.List;
/**
* Jakarta validation annotations reader.
*/
final class ReadValidationAnnotationsJakarta implements ReadValidationAnnotations {
ReadValidationAnnotationsJakarta(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
@Override
public boolean isValidationNotNull(DeployBeanProperty property) {
NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class);
return (notNull != null && isEbeanValidationGroups(notNull.groups()));
}
private boolean isEbeanValidationGroups(Class<?>[] groups) {
return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]);
}
@Override
public int maxSize(DeployBeanProperty property) {
int maxSize = 0;
for (Size size : getMetaAnnotationJavaxSize(property)) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
return maxSize;
}
private List<Size> getMetaAnnotationJavaxSize(DeployBeanProperty prop) {
final List<Size> size = prop.getMetaAnnotations(Size.class);
final List<Size.List> lists = prop.getMetaAnnotations(Size.List.class);
for (Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
}
@@ -1,52 +0,0 @@
package io.ebeaninternal.server.deploy.parse;
import io.ebean.util.AnnotationUtil;
import io.ebeaninternal.server.deploy.meta.DeployBeanProperty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.groups.Default;
import java.util.Collections;
import java.util.List;
/**
* Javax validation annotations reader.
*/
final class ReadValidationAnnotationsJavax implements ReadValidationAnnotations {
ReadValidationAnnotationsJavax(ReadAnnotationConfig readConfig) {
readConfig.addMetaAnnotation(Size.class);
readConfig.addMetaAnnotation(Size.List.class);
}
@Override
public boolean isValidationNotNull(DeployBeanProperty property) {
NotNull notNull = AnnotationUtil.get(property.getField(), NotNull.class);
return (notNull != null && isEbeanValidationGroups(notNull.groups()));
}
private boolean isEbeanValidationGroups(Class<?>[] groups) {
return groups.length == 0 || groups.length == 1 && Default.class.isAssignableFrom(groups[0]);
}
@Override
public int maxSize(DeployBeanProperty prop) {
int maxSize = 0;
for (Size size : getMetaAnnotationJavaxSize(prop)) {
if (size.max() < Integer.MAX_VALUE) {
maxSize = Math.max(maxSize, size.max());
}
}
return maxSize;
}
private List<Size> getMetaAnnotationJavaxSize(DeployBeanProperty prop) {
final List<Size> size = prop.getMetaAnnotations(Size.class);
final List<Size.List> lists = prop.getMetaAnnotations(Size.List.class);
for (Size.List list : lists) {
Collections.addAll(size, list.value());
}
return size;
}
}
@@ -1,89 +0,0 @@
package io.ebeaninternal.server.dto;
import io.ebean.ProfileLocation;
import io.ebean.metric.MetricFactory;
import io.ebean.metric.QueryPlanMetric;
import io.ebeaninternal.api.SpiDtoQuery;
/**
* Request to map a resultSet columns for a query into a DTO bean.
*/
public final class DtoMappingRequest {
private final Class type;
private final String label;
private final ProfileLocation profileLocation;
private final String sql;
private final boolean relaxedMode;
private final DtoColumn[] columnMeta;
public DtoMappingRequest(SpiDtoQuery query, String sql, DtoColumn[] columnMeta) {
this.type = query.getType();
this.label = query.getPlanLabel();
this.profileLocation = query.getProfileLocation();
this.sql = sql;
this.relaxedMode = query.isRelaxedMode();
this.columnMeta = columnMeta;
}
public DtoColumn[] getColumnMeta() {
return columnMeta;
}
public boolean isRelaxedMode() {
return relaxedMode;
}
public String getLabel() {
return label;
}
public String getSql() {
return sql;
}
public QueryPlanMetric createMetric() {
return MetricFactory.get().createQueryPlanMetric(type, label, profileLocation, sql);
}
/**
* Map all DB columns to setters.
*/
DtoReadSet[] mapSetters(DtoMeta meta) {
DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length];
for (int i = 0; i < columnMeta.length; i++) {
setterProps[i] = mapColumn(i, meta);
}
return setterProps;
}
/**
* Map DB columns after constructor to setters.
*/
DtoReadSet[] mapArgPlusSetters(DtoMeta meta, int firstOnes) {
DtoReadSet[] setterProps = new DtoReadSet[columnMeta.length - firstOnes];
int pos = 0;
for (int i = firstOnes; i < columnMeta.length; i++) {
setterProps[pos++] = mapColumn(i, meta);
}
return setterProps;
}
private DtoReadSet mapColumn(int pos, DtoMeta meta) {
String label = columnMeta[pos].getLabel();
DtoReadSet property = meta.findProperty(label);
if (property == null || property.isReadOnly()) {
if (isRelaxedMode()) {
property = DtoReadSetColumnSkip.INSTANCE;
} else {
throw new IllegalStateException(unableToMapColumnMessage(columnMeta[pos], meta));
}
}
return property;
}
private String unableToMapColumnMessage(DtoColumn col, DtoMeta meta) {
return "Unable to map DB column " + col + " to a property with a setter method on " + meta.dtoType()+". Consider query.setRelaxedMode() to skip mapping this column.";
}
}
@@ -1,118 +0,0 @@
package io.ebeaninternal.server.executor;
import io.ebeaninternal.api.SpiBackgroundExecutor;
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
* The default implementation of the BackgroundExecutor.
*/
public final class DefaultBackgroundExecutor implements SpiBackgroundExecutor {
private final ScheduledExecutorService executor;
/**
* Construct the default implementation of BackgroundExecutor.
*/
public DefaultBackgroundExecutor(int schedulePoolSize, int shutdownWaitSeconds, String namePrefix) {
this.executor = new DaemonScheduleThreadPool(schedulePoolSize, shutdownWaitSeconds, namePrefix);
}
/**
* Wrap the task with MDC context if defined.
*/
<T> Callable<T> wrapMDC(Callable<T> task) {
final Map<String, String> map = MDC.getCopyOfContextMap();
if (map == null) {
return task;
} else {
return () -> {
MDC.setContextMap(map);
try {
return task.call();
} finally {
MDC.clear();
}
};
}
}
/**
* Wrap the task with MDC context if defined.
*/
Runnable wrapMDC(Runnable task) {
final Map<String, String> map = MDC.getCopyOfContextMap();
if (map == null) {
return task;
} else {
return () -> {
MDC.setContextMap(map);
try {
task.run();
} finally {
MDC.clear();
}
};
}
}
@Override
public <T> Future<T> submit(Callable<T> task) {
return executor.submit(wrapMDC(task));
}
/**
* Execute a Runnable using a background thread.
*/
@Override
public Future<?> submit(Runnable task) {
return executor.submit(wrapMDC(task));
}
@Override
public void execute(Runnable task) {
submit(task);
}
@Override
public void executePeriodically(Runnable task, long delay, TimeUnit unit) {
executor.scheduleWithFixedDelay(wrapMDC(task), delay, delay, unit);
}
@Override
public void executePeriodically(Runnable task, long initialDelay, long delay, TimeUnit unit) {
executor.scheduleWithFixedDelay(wrapMDC(task), initialDelay, delay, unit);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long initialDelay, long delay, TimeUnit unit) {
return executor.scheduleWithFixedDelay(wrapMDC(task), initialDelay, delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long delay, TimeUnit unit) {
return executor.scheduleAtFixedRate(wrapMDC(task), initialDelay, delay, unit);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, long delay, TimeUnit unit) {
return executor.schedule(wrapMDC(task), delay, unit);
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> task, long delay, TimeUnit unit) {
return executor.schedule(wrapMDC(task), delay, unit);
}
@Override
public void shutdown() {
executor.shutdown();
}
}
@@ -1,16 +0,0 @@
package io.ebeaninternal.server.expression.platform;
import io.ebeaninternal.api.SpiExpressionRequest;
import io.ebeaninternal.server.expression.Op;
/**
* MariaDB specific handling of platform specific expressions.
*/
final class MariaDbExpression extends BasicDbExpression {
@Override
public void json(SpiExpressionRequest request, String propName, String path, Op operator, Object value) {
request.append("(").append(propName).append(" ->> '$.").append(path).append("')");
request.append(operator.bind());
}
}
@@ -1,329 +0,0 @@
// Generated from /home/rob/github/ebean-dir/ebean/src/test/resources/EQL.g4 by ANTLR 4.8
package io.ebeaninternal.server.grammer.antlr;
import org.antlr.v4.runtime.tree.AbstractParseTreeVisitor;
/**
* This class provides an empty implementation of {@link EQLVisitor},
* which can be extended to create a visitor which only needs to handle a subset
* of the available methods.
*
* @param <T> The return type of the visit operation. Use {@link Void} for
* operations with no return type.
*/
public class EQLBaseVisitor<T> extends AbstractParseTreeVisitor<T> implements EQLVisitor<T> {
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSelect_statement(EQLParser.Select_statementContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSelect_properties(EQLParser.Select_propertiesContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitSelect_clause(EQLParser.Select_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitDistinct(EQLParser.DistinctContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_clause(EQLParser.Fetch_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitWhere_clause(EQLParser.Where_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOrderby_clause(EQLParser.Orderby_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOrderby_property(EQLParser.Orderby_propertyContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitNulls_firstlast(EQLParser.Nulls_firstlastContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAsc_desc(EQLParser.Asc_descContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLimit_clause(EQLParser.Limit_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitOffset_clause(EQLParser.Offset_clauseContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_path(EQLParser.Fetch_pathContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_property_set(EQLParser.Fetch_property_setContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_property_group(EQLParser.Fetch_property_groupContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_path_path(EQLParser.Fetch_path_pathContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_property(EQLParser.Fetch_propertyContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_query_hint(EQLParser.Fetch_query_hintContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_lazy_hint(EQLParser.Fetch_lazy_hintContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_option(EQLParser.Fetch_optionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_query_option(EQLParser.Fetch_query_optionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_lazy_option(EQLParser.Fetch_lazy_optionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitFetch_batch_size(EQLParser.Fetch_batch_sizeContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitConditional_expression(EQLParser.Conditional_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitConditional_term(EQLParser.Conditional_termContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitConditional_factor(EQLParser.Conditional_factorContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitConditional_primary(EQLParser.Conditional_primaryContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitAny_expression(EQLParser.Any_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitInOrEmpty_expression(EQLParser.InOrEmpty_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIn_expression(EQLParser.In_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIn_value(EQLParser.In_valueContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitBetween_expression(EQLParser.Between_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitInrange_expression(EQLParser.Inrange_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitInrange_op(EQLParser.Inrange_opContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitPropertyBetween_expression(EQLParser.PropertyBetween_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIsNull_expression(EQLParser.IsNull_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIsNotNull_expression(EQLParser.IsNotNull_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIsEmpty_expression(EQLParser.IsEmpty_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitIsNotEmpty_expression(EQLParser.IsNotEmpty_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLike_expression(EQLParser.Like_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLike_op(EQLParser.Like_opContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitComparison_expression(EQLParser.Comparison_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitComparison_operator(EQLParser.Comparison_operatorContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitValue_expression(EQLParser.Value_expressionContext ctx) { return visitChildren(ctx); }
/**
* {@inheritDoc}
*
* <p>The default implementation returns the result of calling
* {@link #visitChildren} on {@code ctx}.</p>
*/
@Override public T visitLiteral(EQLParser.LiteralContext ctx) { return visitChildren(ctx); }
}

Some files were not shown because too many files have changed in this diff Show More