mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge remote-tracking branch 'upstream/master'
# Conflicts: # ebean-bom/pom.xml
This commit is contained in:
@@ -36,5 +36,5 @@ jobs:
|
||||
# - name: Maven single test
|
||||
# run: mvn --batch-mode clean verify -Dtest="io.ebeaninternal.server.core.DefaultServer_getReferenceTest" -DfailIfNoTests=false
|
||||
- name: Build with Maven
|
||||
run: mvn clean package
|
||||
run: mvn -T 8 clean test
|
||||
|
||||
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: db2
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-db2.properties
|
||||
|
||||
@@ -37,5 +37,5 @@ jobs:
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
- name: H2Database
|
||||
run: mvn clean package
|
||||
run: mvn -T 8 clean package
|
||||
|
||||
|
||||
@@ -35,5 +35,5 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
run: mvn -T 8 test
|
||||
|
||||
|
||||
@@ -39,5 +39,5 @@ jobs:
|
||||
- name: Maven version
|
||||
run: mvn --version
|
||||
- name: Build with Maven
|
||||
run: mvn package
|
||||
run: mvn -T 8 test
|
||||
|
||||
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: mariadb 10.6
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mariadb.properties
|
||||
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: mysql
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-mysql.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-mysql.properties
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
name: Oracle18
|
||||
name: Oracle
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: oracle
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-oracle.properties
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: postgres
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-postgres.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-postgres.properties
|
||||
|
||||
@@ -35,4 +35,4 @@ jobs:
|
||||
~/.m2
|
||||
key: build-${{ env.cache-name }}
|
||||
- name: sqlserver 2017
|
||||
run: mvn clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
run: mvn -T 8 clean test -Dprops.file=testconfig/ebean-sqlserver17.properties
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/postgres.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mysql.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/mariadb.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/oracle.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/sqlserver.yml)
|
||||
[](https://github.com/ebean-orm/ebean/actions/workflows/yugabyte.yml)
|
||||
|
||||
|
||||
@@ -802,20 +802,6 @@ public class DatabasePlatform {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if partitions exist for the given table.
|
||||
*/
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the SQL to create an initial partition for the given table.
|
||||
*/
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes the like string for this DB-Platform
|
||||
*/
|
||||
|
||||
@@ -16,25 +16,24 @@ import java.sql.SQLException;
|
||||
* <p>
|
||||
* Scalar in the sense that the types are not compound types. Scalar types only
|
||||
* map to a single database column.
|
||||
* </p>
|
||||
* <p>
|
||||
* These types fall into two categories. Types that are mapped natively to JDBC
|
||||
* types and the rest. Types that map to native JDBC types do not require any
|
||||
* data type conversion to be persisted to the database. These are java types
|
||||
* that map via java.sql.Types.
|
||||
* </p>
|
||||
* <p>
|
||||
* Types that are not native to JDBC require some conversion. These include some
|
||||
* common java types such as java.util.Date, java.util.Calendar,
|
||||
* java.math.BigInteger.
|
||||
* </p>
|
||||
* <p>
|
||||
* Note that Booleans may be native for some databases and require conversion on
|
||||
* other databases.
|
||||
* </p>
|
||||
*/
|
||||
public interface ScalarType<T> extends StringParser, StringFormatter, ScalarDataReader<T> {
|
||||
|
||||
/**
|
||||
* Return true for types that do mutation detection based on json content.
|
||||
*/
|
||||
default boolean isJsonMapper() {
|
||||
return false;
|
||||
}
|
||||
@@ -43,38 +42,40 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* Return true if this is a binary type and can not support parse() and format() from/to string.
|
||||
* This allows Ebean to optimise marshalling types to string.
|
||||
*/
|
||||
boolean isBinaryType();
|
||||
default boolean isBinaryType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if this is a mutable scalar type (like hstore).
|
||||
*/
|
||||
boolean isMutable();
|
||||
default boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For mutable scalarType's return true if the value is dirty.
|
||||
* Non-dirty properties may be excluded from updates.
|
||||
*/
|
||||
boolean isDirty(Object value);
|
||||
default boolean isDirty(Object value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default DB column length for this type.
|
||||
* <p>
|
||||
* If a BeanProperty has no explicit length defined then this length should
|
||||
* be assigned.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is primarily to support defining a length on Enum types (to
|
||||
* supplement defining the length on the BeanProperty directly).
|
||||
* </p>
|
||||
*/
|
||||
int getLength();
|
||||
default int getLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the type is native to JDBC.
|
||||
* <p>
|
||||
* If it is native to JDBC then its values/instances do not need to be
|
||||
* converted to and from an associated JDBC type.
|
||||
* </p>
|
||||
*/
|
||||
boolean isJdbcNative();
|
||||
|
||||
@@ -83,16 +84,13 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* <p>
|
||||
* This type should be consistent with the toJdbcType() method in converting
|
||||
* the type to the appropriate type for binding to preparedStatements.
|
||||
* </p>
|
||||
*/
|
||||
int getJdbcType();
|
||||
|
||||
/**
|
||||
* Return the type that matches the bean property type.
|
||||
* <p>
|
||||
* This represents the 'logical' type rather than the JDBC type this maps
|
||||
* to.
|
||||
* </p>
|
||||
* This represents the 'logical' type rather than the JDBC type this maps to.
|
||||
*/
|
||||
Class<T> getType();
|
||||
|
||||
@@ -104,7 +102,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
T read(DataReader reader) throws SQLException;
|
||||
|
||||
/**
|
||||
* Ignore the reading of this value. Typically this means moving the index
|
||||
* Ignore the reading of this value. Typically, this means moving the index
|
||||
* position in the ResultSet.
|
||||
*/
|
||||
void loadIgnore(DataReader reader);
|
||||
@@ -114,20 +112,16 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* <p>
|
||||
* value may need to be converted from the logical bean property type to the
|
||||
* JDBC type.
|
||||
* </p>
|
||||
*/
|
||||
void bind(DataBinder binder, T value) throws SQLException;
|
||||
|
||||
/**
|
||||
* Convert the value as necessary to the JDBC type.
|
||||
* <p>
|
||||
* Note that this should also match the type as per the getJdbcType()
|
||||
* method.
|
||||
* </p>
|
||||
* Note that this should also match the type as per the getJdbcType() method.
|
||||
* <p>
|
||||
* This is typically used when the matching type is used in a where clause
|
||||
* and we use this to ensure it is an appropriate jdbc type.
|
||||
* </p>
|
||||
*/
|
||||
Object toJdbcType(Object value);
|
||||
|
||||
@@ -135,19 +129,14 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* Convert the value as necessary to the logical Bean type.
|
||||
* <p>
|
||||
* The type as per the bean property.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is used to automatically convert id values (typically from a string
|
||||
* to a int, long or UUID).
|
||||
* </p>
|
||||
*/
|
||||
T toBeanType(Object value);
|
||||
|
||||
/**
|
||||
* Convert the type into a string representation.
|
||||
* <p>
|
||||
* Reciprocal of parse().
|
||||
* </p>
|
||||
*/
|
||||
String formatValue(T value);
|
||||
|
||||
@@ -155,10 +144,8 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* Convert the type into a string representation.
|
||||
* <p>
|
||||
* This assumes the value is of the correct type.
|
||||
* </p>
|
||||
* <p>
|
||||
* This is so that ScalarType also implements the StringFormatter interface.
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
String format(Object value);
|
||||
@@ -167,10 +154,6 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
* Convert the string value to the appropriate java object.
|
||||
* <p>
|
||||
* Mostly used to support CSV, JSON and XML parsing.
|
||||
* </p>
|
||||
* <p>
|
||||
* Reciprocal of formatValue().
|
||||
* </p>
|
||||
*/
|
||||
@Override
|
||||
T parse(String value);
|
||||
@@ -183,29 +166,32 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
/**
|
||||
* Return true if the type can accept long systemTimeMillis input.
|
||||
* <p>
|
||||
* This is used to determine if is is sensible to use the
|
||||
* This is used to determine if it is sensible to use the
|
||||
* {@link #convertFromMillis(long)} method.
|
||||
* </p>
|
||||
* <p>
|
||||
* This includes the Date, Calendar, sql Date, Time, Timestamp, JODA types
|
||||
* as well as Long, BigDecimal and String (although it generally is not
|
||||
* expected to parse systemTimeMillis to a String or BigDecimal).
|
||||
* </p>
|
||||
*/
|
||||
boolean isDateTimeCapable();
|
||||
default boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the value into a long version value.
|
||||
*/
|
||||
long asVersion(T value);
|
||||
default long asVersion(T value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the systemTimeMillis into the appropriate java object.
|
||||
* <p>
|
||||
* For non dateTime types this will throw an exception.
|
||||
* </p>
|
||||
*/
|
||||
T convertFromMillis(long dateTime);
|
||||
default T convertFromMillis(long dateTime) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the value from binary input.
|
||||
@@ -215,7 +201,7 @@ public interface ScalarType<T> extends StringParser, StringFormatter, ScalarData
|
||||
/**
|
||||
* Write the value to binary output.
|
||||
*/
|
||||
void writeData(DataOutput dataOutput, T v) throws IOException;
|
||||
void writeData(DataOutput dataOutput, T value) throws IOException;
|
||||
|
||||
/**
|
||||
* Read the value from JsonParser.
|
||||
|
||||
@@ -77,8 +77,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
private List<BeanPropertyAssocMany<?>> updatedManys;
|
||||
/**
|
||||
* Need to get and store the updated properties because the persist listener is notified
|
||||
* later on a different thread and the bean has been reset at that point.
|
||||
* Store the updated properties to notify persist listener.
|
||||
*/
|
||||
private Set<String> updatedProperties;
|
||||
/**
|
||||
@@ -122,7 +121,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
*/
|
||||
private boolean complete;
|
||||
/**
|
||||
* Many to many intersection table changes that are held for later batch processing.
|
||||
* Many-to-many intersection table changes that are held for later batch processing.
|
||||
*/
|
||||
private List<SaveMany> saveMany;
|
||||
|
||||
@@ -148,9 +147,10 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
// 'stateless update' - set loaded properties as dirty
|
||||
intercept.setNewBeanForUpdate();
|
||||
statelessUpdate = true;
|
||||
} else if (!intercept.isDirty()) {
|
||||
// check if any mutable scalar properties are dirty
|
||||
beanDescriptor.checkAnyMutableProperties(intercept);
|
||||
}
|
||||
// Mark Mutable scalar properties (like Hstore) as dirty where necessary
|
||||
beanDescriptor.checkMutableProperties(intercept);
|
||||
}
|
||||
this.concurrencyMode = beanDescriptor.concurrencyMode(intercept);
|
||||
this.publish = Flags.isPublish(flags);
|
||||
@@ -726,10 +726,6 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
executeInsert();
|
||||
return -1;
|
||||
case UPDATE:
|
||||
if (beanPersistListener != null) {
|
||||
// store the updated properties for sending later
|
||||
updatedProperties = updatedProperties();
|
||||
}
|
||||
executeUpdate();
|
||||
return -1;
|
||||
case DELETE_SOFT:
|
||||
@@ -1208,6 +1204,11 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
private void executeUpdate() {
|
||||
setTenantId();
|
||||
if (controller == null || controller.preUpdate(this)) {
|
||||
// check dirty state for all mutable scalar properties (like DbJson, Hstore)
|
||||
beanDescriptor.checkAllMutableProperties(intercept);
|
||||
if (beanPersistListener != null) {
|
||||
updatedProperties = updatedProperties();
|
||||
}
|
||||
postControllerPrepareUpdate();
|
||||
beanManager.getBeanPersister().update(this);
|
||||
}
|
||||
|
||||
@@ -3140,9 +3140,9 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for mutable scalar types and mark as dirty if necessary.
|
||||
* Check all mutable scalar types and mark as dirty if necessary.
|
||||
*/
|
||||
public void checkMutableProperties(EntityBeanIntercept ebi) {
|
||||
public void checkAllMutableProperties(EntityBeanIntercept ebi) {
|
||||
for (BeanProperty beanProperty : propertiesMutable) {
|
||||
int propertyIndex = beanProperty.propertyIndex();
|
||||
if (ebi.isLoadedProperty(propertyIndex)) {
|
||||
@@ -3156,6 +3156,23 @@ public class BeanDescriptor<T> implements BeanType<T>, STreeType, SpiBeanType {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if any mutable properties are dirty.
|
||||
*/
|
||||
public boolean checkAnyMutableProperties(EntityBeanIntercept ebi) {
|
||||
for (BeanProperty beanProperty : propertiesMutable) {
|
||||
int propertyIndex = beanProperty.propertyIndex();
|
||||
if (ebi.isLoadedProperty(propertyIndex)) {
|
||||
Object value = beanProperty.getValue(ebi.getOwner());
|
||||
if (beanProperty.checkMutable(value, ebi.isDirtyProperty(propertyIndex), ebi)) {
|
||||
ebi.markPropertyAsChanged(propertyIndex);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ConcurrencyMode concurrencyMode(EntityBeanIntercept ebi) {
|
||||
if (!hasVersionProperty(ebi)) {
|
||||
return ConcurrencyMode.NONE;
|
||||
|
||||
@@ -359,6 +359,9 @@ public final class DefaultTypeManager implements TypeManager {
|
||||
Type genericType = prop.getGenericType();
|
||||
boolean hasJacksonAnnotations = objectMapperPresent && checkJacksonAnnotations(prop);
|
||||
|
||||
if (type.equals(String.class)) {
|
||||
return ScalarTypeJsonString.typeFor(postgres, dbType);
|
||||
}
|
||||
if (type.equals(List.class)) {
|
||||
DocPropertyType docType = getDocType(genericType);
|
||||
if (!hasJacksonAnnotations && isValueTypeSimple(genericType)) {
|
||||
|
||||
@@ -18,41 +18,6 @@ abstract class ScalarTypeBase<T> implements ScalarType<T> {
|
||||
this.jdbcType = jdbcType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(T value) {
|
||||
throw new RuntimeException("not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
// override for binary/byte based types
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation of mutable false.
|
||||
*/
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default to true.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Just return 0.
|
||||
*/
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJdbcNative() {
|
||||
return jdbcNative;
|
||||
|
||||
@@ -88,16 +88,6 @@ abstract class ScalarTypeBaseVarchar<T> extends ScalarTypeBase<T> {
|
||||
return format(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public String format(Object value) {
|
||||
|
||||
@@ -234,7 +234,6 @@ public final class ScalarTypeBoolean {
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
// typically this will return 1
|
||||
return Math.max(trueValue.length(), falseValue.length());
|
||||
}
|
||||
|
||||
@@ -329,16 +328,6 @@ public final class ScalarTypeBoolean {
|
||||
return Boolean.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -85,16 +85,6 @@ final class ScalarTypeByte extends ScalarTypeBase<Byte> {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Byte readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -59,16 +59,6 @@ public abstract class ScalarTypeBytesBase extends ScalarTypeBase<byte[]> {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -26,26 +26,11 @@ public final class ScalarTypeBytesEncrypted implements ScalarType<byte[]> {
|
||||
this.dataEncryptSupport = dataEncryptSupport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(byte[] value) {
|
||||
throw new RuntimeException("not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBinder binder, byte[] value) throws SQLException {
|
||||
value = dataEncryptSupport.encrypt(value);
|
||||
|
||||
@@ -93,16 +93,6 @@ class ScalarTypeDuration extends ScalarTypeBase<Duration> {
|
||||
return Duration.parse(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Duration jsonRead(JsonParser parser) throws IOException {
|
||||
return Duration.parse(parser.getValueAsString());
|
||||
|
||||
@@ -30,11 +30,6 @@ public final class ScalarTypeEncryptedWrapper<T> implements ScalarType<T>, Local
|
||||
return dataEncryptSupport.encryptObject(formatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(T value) {
|
||||
throw new RuntimeException("not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
return wrapped.isBinaryType();
|
||||
|
||||
@@ -229,16 +229,6 @@ final class ScalarTypeEnumStandard {
|
||||
return Enum.valueOf(enumType, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object jsonRead(JsonParser parser) throws IOException {
|
||||
if (parser.getCodec() != null) {
|
||||
|
||||
@@ -39,16 +39,6 @@ class ScalarTypeEnumWithMapping extends ScalarTypeEnumStandard.EnumBase implemen
|
||||
return enumType == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(Object value) {
|
||||
throw new RuntimeException("not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the IN values for DB constraint construction.
|
||||
*/
|
||||
|
||||
@@ -126,16 +126,6 @@ final class ScalarTypeFile extends ScalarTypeBase<File> {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public File readData(DataInput dataInput) throws IOException {
|
||||
// skip reading large file
|
||||
|
||||
@@ -80,16 +80,6 @@ abstract class ScalarTypeJsonCollection<T> extends ScalarTypeBase<T> implements
|
||||
return docPropertyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertFromMillis(long dateTime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -215,16 +215,6 @@ abstract class ScalarTypeJsonMap extends ScalarTypeBase<Map> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map convertFromMillis(long dateTime) {
|
||||
throw new RuntimeException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -167,16 +167,6 @@ abstract class ScalarTypeJsonNode extends ScalarTypeBase<JsonNode> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode convertFromMillis(long dateTime) {
|
||||
throw new RuntimeException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonNode readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
+5
-25
@@ -55,16 +55,6 @@ final class ScalarTypeJsonObjectMapper {
|
||||
NoMutationDetection(TypeJsonManager jsonManager, AnnotatedField field, int dbType, DocPropertyType docType) {
|
||||
super(Object.class, jsonManager, field, dbType, docType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,6 +69,11 @@ final class ScalarTypeJsonObjectMapper {
|
||||
this.jsonb = "jsonb".equals(pgType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJsonMapper() {
|
||||
return true;
|
||||
@@ -144,11 +139,6 @@ final class ScalarTypeJsonObjectMapper {
|
||||
this.objectWriter = helper.objectWriter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T read(DataReader reader) throws SQLException {
|
||||
String json = reader.getString();
|
||||
@@ -212,16 +202,6 @@ final class ScalarTypeJsonObjectMapper {
|
||||
return docType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T convertFromMillis(long dateTime) {
|
||||
throw new IllegalStateException("Not supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final T jsonRead(JsonParser parser) throws IOException {
|
||||
return objectReader.readValue(parser, deserType);
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.config.dbplatform.DbPlatformType;
|
||||
import io.ebean.config.dbplatform.ExtraDbTypes;
|
||||
import io.ebean.core.type.DataBinder;
|
||||
import io.ebean.core.type.ScalarType;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
final class ScalarTypeJsonString {
|
||||
|
||||
static final Postgres JSONB = new Postgres(ExtraDbTypes.JSONB, PostgresHelper.JSONB_TYPE);
|
||||
static final Postgres JSON = new Postgres(ExtraDbTypes.JSON, PostgresHelper.JSON_TYPE);
|
||||
|
||||
static ScalarType<?> typeFor(boolean postgres, int dbType) {
|
||||
if (postgres) {
|
||||
switch (dbType) {
|
||||
case DbPlatformType.JSONB:
|
||||
return JSONB;
|
||||
case DbPlatformType.JSON:
|
||||
return JSON;
|
||||
}
|
||||
}
|
||||
return ScalarTypeString.INSTANCE;
|
||||
}
|
||||
|
||||
private static class Postgres extends ScalarTypeStringBase {
|
||||
final String postgresType;
|
||||
|
||||
Postgres(int jdbcType, String postgresType) {
|
||||
super(true, jdbcType);
|
||||
this.postgresType = postgresType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bind(DataBinder binder, String rawJson) throws SQLException {
|
||||
binder.setObject(PostgresHelper.asObject(postgresType, rawJson));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -78,16 +78,6 @@ final class ScalarTypeMonthDay extends ScalarTypeBase<MonthDay> {
|
||||
return MonthDay.parse(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonthDay convertFromMillis(long dateTime) {
|
||||
throw new RuntimeException("Not supported on this type");
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonthDay readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -22,25 +22,6 @@ class ScalarTypeNotFound implements ScalarType<Void> {
|
||||
|
||||
public static final ScalarTypeNotFound INSTANCE = new ScalarTypeNotFound();
|
||||
private ScalarTypeNotFound() { }
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJdbcNative() {
|
||||
@@ -102,21 +83,6 @@ class ScalarTypeNotFound implements ScalarType<Void> {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(Void value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void convertFromMillis(long dateTime) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void readData(DataInput dataInput) throws IOException {
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
@@ -82,16 +82,6 @@ final class ScalarTypePostgresHstore extends ScalarTypeBase<Map> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map convertFromMillis(long dateTime) {
|
||||
throw new RuntimeException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -57,16 +57,6 @@ final class ScalarTypeShort extends ScalarTypeBase<Short> {
|
||||
return Short.valueOf(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Short readData(DataInput dataInput) throws IOException {
|
||||
if (!dataInput.readBoolean()) {
|
||||
|
||||
@@ -25,16 +25,6 @@ abstract class ScalarTypeUUIDBase extends ScalarTypeBase<UUID> implements Scalar
|
||||
return DbPlatformType.UUID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(Object value) {
|
||||
return String.valueOf(value);
|
||||
@@ -50,16 +40,6 @@ abstract class ScalarTypeUUIDBase extends ScalarTypeBase<UUID> implements Scalar
|
||||
return UUID.fromString(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID convertFromMillis(long dateTime) {
|
||||
throw new RuntimeException("Should never be called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID toBeanType(Object value) {
|
||||
return BasicTypeConverter.toUUID(value, false);
|
||||
|
||||
@@ -44,8 +44,7 @@ public class ScalarTypeWrapper<B, S> implements ScalarType<B> {
|
||||
|
||||
@Override
|
||||
public long asVersion(B value) {
|
||||
S unwrapValue = converter.unwrapValue(value);
|
||||
return scalarType.asVersion(unwrapValue);
|
||||
return scalarType.asVersion(converter.unwrapValue(value));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -81,16 +81,6 @@ final class ScalarTypeYear extends ScalarTypeBase<Year> {
|
||||
return Year.parse(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Year convertFromMillis(long systemTimeMillis) {
|
||||
throw new TextException("Not Supported");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Year jsonRead(JsonParser parser) throws IOException {
|
||||
return Year.of(parser.getIntValue());
|
||||
|
||||
+2
-2
@@ -17,11 +17,11 @@ class BasicProfileLocationTest {
|
||||
assertThat(loc.fullLocation()).endsWith("invoke0(Native Method:12)");
|
||||
assertThat(loc.location()).isEqualTo("sun.reflect.NativeMethodAccessorImpl.invoke0");
|
||||
assertThat(loc.label()).isEqualTo("NativeMethodAccessorImpl.invoke0");
|
||||
} else if (javaVersion.startsWith("18") || javaVersion.startsWith("19")){
|
||||
} else if (javaVersion.startsWith("18") || javaVersion.startsWith("19") || javaVersion.startsWith("20")){
|
||||
assertThat(loc.fullLocation()).endsWith("jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)");
|
||||
assertThat(loc.location()).isEqualTo("java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke");
|
||||
assertThat(loc.label()).isEqualTo("DirectMethodHandleAccessor.invoke");
|
||||
} else {
|
||||
} else if (javaVersion.startsWith("11") || javaVersion.startsWith("17")) {
|
||||
assertThat(loc.fullLocation()).endsWith("jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method:12)");
|
||||
assertThat(loc.location()).isEqualTo("java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0");
|
||||
assertThat(loc.label()).isEqualTo("NativeMethodAccessorImpl.invoke0");
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.text.TextException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -11,13 +10,12 @@ import java.time.Duration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ScalarTypeDurationTest {
|
||||
class ScalarTypeDurationTest {
|
||||
|
||||
ScalarTypeDuration type = new ScalarTypeDuration();
|
||||
|
||||
@Test
|
||||
public void testReadData() throws Exception {
|
||||
|
||||
void testReadData() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(1234);
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
@@ -39,8 +37,7 @@ public class ScalarTypeDurationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJdbcType() throws Exception {
|
||||
|
||||
void testToJdbcType() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(1234);
|
||||
long seconds = duration.getSeconds();
|
||||
|
||||
@@ -52,8 +49,7 @@ public class ScalarTypeDurationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToBeanType() throws Exception {
|
||||
|
||||
void testToBeanType() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(1234);
|
||||
long seconds = duration.getSeconds();
|
||||
|
||||
@@ -67,37 +63,34 @@ public class ScalarTypeDurationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatValue() throws Exception {
|
||||
|
||||
void testFormatValue() {
|
||||
Duration duration = Duration.ofSeconds(1234);
|
||||
String formatValue = type.formatValue(duration);
|
||||
assertEquals("PT20M34S", formatValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
void testParse() {
|
||||
Duration duration = type.parse("PT20M34S");
|
||||
assertEquals(Duration.ofSeconds(1234), duration);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDateTimeCapable() {
|
||||
void testIsDateTimeCapable() {
|
||||
assertFalse(type.isDateTimeCapable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromMillis() {
|
||||
assertThrows(TextException.class, () -> type.convertFromMillis(1000));
|
||||
void testConvertFromMillis() {
|
||||
assertThrows(UnsupportedOperationException.class, () -> type.convertFromMillis(1000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonRead() throws Exception {
|
||||
|
||||
void testJsonRead() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(1234);
|
||||
|
||||
JsonTester<Duration> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(duration);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
-15
@@ -1,6 +1,5 @@
|
||||
package io.ebeaninternal.server.type;
|
||||
|
||||
import io.ebean.text.TextException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
@@ -12,13 +11,12 @@ import java.time.Duration;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ScalarTypeDurationWithNanosTest {
|
||||
class ScalarTypeDurationWithNanosTest {
|
||||
|
||||
ScalarTypeDurationWithNanos type = new ScalarTypeDurationWithNanos();
|
||||
|
||||
@Test
|
||||
public void testReadData() throws Exception {
|
||||
|
||||
void testReadData() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
@@ -40,8 +38,7 @@ public class ScalarTypeDurationWithNanosTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJdbcType() throws Exception {
|
||||
|
||||
void testToJdbcType() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
BigDecimal bigDecimal = DecimalUtils.toDecimal(duration);
|
||||
|
||||
@@ -53,8 +50,7 @@ public class ScalarTypeDurationWithNanosTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToBeanType() throws Exception {
|
||||
|
||||
void testToBeanType() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
BigDecimal bigDecimal = DecimalUtils.toDecimal(duration);
|
||||
|
||||
@@ -66,32 +62,31 @@ public class ScalarTypeDurationWithNanosTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatValue() throws Exception {
|
||||
|
||||
void testFormatValue() {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
String formatValue = type.formatValue(duration);
|
||||
assertEquals("PT5M23.0015S", formatValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
void testParse() {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
Duration val1 = type.parse("PT5M23.0015S");
|
||||
assertEquals(duration, val1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDateTimeCapable() {
|
||||
void testIsDateTimeCapable() {
|
||||
assertFalse(type.isDateTimeCapable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromMillis() {
|
||||
assertThrows(TextException.class, () -> type.convertFromMillis(1000));
|
||||
void testConvertFromMillis() {
|
||||
assertThrows(UnsupportedOperationException.class, () -> type.convertFromMillis(1000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJsonRead() throws Exception {
|
||||
void testJsonRead() throws Exception {
|
||||
Duration duration = Duration.ofSeconds(323, 1500000);
|
||||
|
||||
JsonTester<Duration> jsonTester = new JsonTester<>(type);
|
||||
|
||||
@@ -11,13 +11,12 @@ import java.time.Year;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class ScalarTypeYearTest {
|
||||
class ScalarTypeYearTest {
|
||||
|
||||
ScalarTypeYear type = new ScalarTypeYear();
|
||||
|
||||
@Test
|
||||
public void testReadData() throws Exception {
|
||||
|
||||
void testReadData() throws Exception {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ObjectOutputStream out = new ObjectOutputStream(os);
|
||||
|
||||
@@ -37,8 +36,7 @@ public class ScalarTypeYearTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToJdbcType() throws Exception {
|
||||
|
||||
void testToJdbcType() throws Exception {
|
||||
Integer year = 2013;
|
||||
Object val1 = type.toJdbcType(Year.of(2013));
|
||||
Object val2 = type.toJdbcType(2013);
|
||||
@@ -50,8 +48,7 @@ public class ScalarTypeYearTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToBeanType() throws Exception {
|
||||
|
||||
void testToBeanType() throws Exception {
|
||||
Year year = Year.of(2013);
|
||||
Year val1 = type.toBeanType(year);
|
||||
Year val2 = type.toBeanType(2013);
|
||||
@@ -63,29 +60,29 @@ public class ScalarTypeYearTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatValue() throws Exception {
|
||||
void testFormatValue() {
|
||||
String formatted = type.formatValue(Year.of(2013));
|
||||
assertEquals("2013", formatted);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParse() {
|
||||
void testParse() {
|
||||
Year year = type.parse("2013");
|
||||
assertEquals(Year.of(2013), year);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsDateTimeCapable() {
|
||||
void testIsDateTimeCapable() {
|
||||
assertFalse(type.isDateTimeCapable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertFromMillis() {
|
||||
assertThrows(TextException.class, () -> type.convertFromMillis(1000));
|
||||
void testConvertFromMillis() {
|
||||
assertThrows(UnsupportedOperationException.class, () -> type.convertFromMillis(1000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJson() throws Exception {
|
||||
void testJson() throws Exception {
|
||||
JsonTester<Year> jsonTester = new JsonTester<>(type);
|
||||
jsonTester.test(Year.of(2013));
|
||||
}
|
||||
|
||||
@@ -11,19 +11,12 @@ import io.ebean.util.IOUtils;
|
||||
import io.ebean.util.JdbcClose;
|
||||
import io.ebeaninternal.api.SpiEbeanServer;
|
||||
import io.ebeaninternal.dbmigration.model.CurrentModel;
|
||||
import io.ebeaninternal.dbmigration.model.MTable;
|
||||
import io.ebeaninternal.extraddl.model.ExtraDdlXmlReader;
|
||||
import io.ebeaninternal.server.deploy.PartitionMeta;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.persistence.PersistenceException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.LineNumberReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.io.*;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
|
||||
@@ -201,7 +194,6 @@ public class DdlPlugin implements Plugin {
|
||||
createAllContent = readFile(getCreateFileName());
|
||||
}
|
||||
runScript(connection, false, createAllContent, getCreateFileName());
|
||||
|
||||
if (extraDdl && jaxbPresent) {
|
||||
if (currentModel().isTablePartitioning()) {
|
||||
String extraPartitioning = ExtraDdlXmlReader.buildPartitioning(platform);
|
||||
@@ -209,43 +201,10 @@ public class DdlPlugin implements Plugin {
|
||||
runScript(connection, false, extraPartitioning, "builtin-partitioning-ddl");
|
||||
}
|
||||
}
|
||||
|
||||
String extraApply = ExtraDdlXmlReader.buildExtra(platform, false);
|
||||
if (extraApply != null) {
|
||||
runScript(connection, false, extraApply, "extra-ddl");
|
||||
}
|
||||
|
||||
if (currentModel().isTablePartitioning()) {
|
||||
checkInitialTablePartitions(connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if table partitions exist and if not create some. The expectation is that
|
||||
* extra-ddl.xml should have some partition initialisation but this helps people get going.
|
||||
*/
|
||||
private void checkInitialTablePartitions(Connection connection) {
|
||||
DatabasePlatform databasePlatform = server.databasePlatform();
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (MTable table : currentModel.getPartitionedTables()) {
|
||||
String tableName = table.getName();
|
||||
if (!databasePlatform.tablePartitionsExist(connection, tableName)) {
|
||||
log.info("No table partitions for table {}", tableName);
|
||||
PartitionMeta meta = table.getPartitionMeta();
|
||||
String initPart = databasePlatform.tablePartitionInit(tableName, meta.getMode());
|
||||
sb.append(initPart).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
String initialPartitionSql = sb.toString();
|
||||
if (!initialPartitionSql.isEmpty()) {
|
||||
runScript(connection, false, initialPartitionSql, "initial table partitions");
|
||||
}
|
||||
|
||||
} catch (SQLException e) {
|
||||
log.error("Error checking initial table partitions", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -214,6 +214,8 @@ public class BaseTableDdl implements TableDdl {
|
||||
String partitionMode = createTable.getPartitionMode();
|
||||
if (partitionMode != null) {
|
||||
platformDdl.addTablePartition(apply, partitionMode, createTable.getPartitionColumn());
|
||||
apply.endOfStatement().newLine();
|
||||
platformDdl.addDefaultTablePartition(apply, createTable.getName());
|
||||
}
|
||||
apply.endOfStatement();
|
||||
|
||||
|
||||
+16
@@ -13,6 +13,22 @@ public class NuoDbDdl extends PlatformDdl {
|
||||
this.dropConstraintIfExists = "drop constraint";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createSequence(String sequenceName, DdlIdentity identity) {
|
||||
StringBuilder sb = new StringBuilder("create sequence ");
|
||||
sb.append(quote(sequenceName));
|
||||
int start = identity.getStart();
|
||||
if (start > 0) {
|
||||
sb.append(" ").append(sequenceStartWith).append(" ").append(start);
|
||||
}
|
||||
int cache = identity.getCache();
|
||||
if (cache > 0) {
|
||||
sb.append(" quantum size ").append(cache);
|
||||
}
|
||||
sb.append(";");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTableComment(DdlBuffer apply, String tableName, String tableComment) {
|
||||
// do nothing
|
||||
|
||||
+5
-1
@@ -733,7 +733,11 @@ public class PlatformDdl {
|
||||
}
|
||||
|
||||
public void addTablePartition(DdlBuffer apply, String partitionMode, String partitionColumn) {
|
||||
// only supported by postgres initially
|
||||
// only supported by postgres and yugabyte
|
||||
}
|
||||
|
||||
public void addDefaultTablePartition(DdlBuffer apply, String tableName) {
|
||||
// only supported by postgres and yugabyte
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+5
@@ -45,6 +45,11 @@ public class PostgresDdl extends PlatformDdl {
|
||||
apply.append(" partition by range (").append(partitionColumn).append(")");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addDefaultTablePartition(DdlBuffer apply, String tableName) {
|
||||
apply.append("create table ").append(tableName).append("_default partition of ").append(tableName).append(" default");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dropIndex(String indexName, String tableName, boolean concurrent) {
|
||||
return (concurrent ? dropIndexConcurrentlyIfExists : dropIndexIfExists) + maxConstraintName(indexName);
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<extra-ddl xmlns="http://ebean-orm.github.io/xml/ns/extraddl">
|
||||
|
||||
<ddl-script name="partition help" init="true" platforms="postgres">
|
||||
<ddl-script name="partition help" init="true" platforms="postgres,yugabyte">
|
||||
-- partitioning helper functions (UTC based)
|
||||
|
||||
------------------------------------------------------------------------------------
|
||||
|
||||
+2
-3
@@ -7,11 +7,10 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class PostgresPlatformTest {
|
||||
class PostgresPlatformTest {
|
||||
|
||||
@Test
|
||||
public void testTypeConversion() {
|
||||
|
||||
void testTypeConversion() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
PlatformDdl ddl = PlatformDdlBuilder.create(platform);
|
||||
|
||||
|
||||
@@ -86,26 +86,6 @@ abstract class ScalarTypePgisBase<T extends Geometry> implements ScalarType<T> {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadIgnore(DataReader reader) {
|
||||
reader.incrementPos(1);
|
||||
@@ -141,22 +121,6 @@ abstract class ScalarTypePgisBase<T extends Geometry> implements ScalarType<T> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(T value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertFromMillis(long dateTime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T jsonRead(JsonParser parser) {
|
||||
return null;
|
||||
|
||||
@@ -77,26 +77,6 @@ abstract class ScalarTypeGeoLatteBase<T extends Geometry> implements ScalarType<
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBinaryType() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMutable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirty(Object value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLength() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadIgnore(DataReader reader) {
|
||||
reader.incrementPos(1);
|
||||
@@ -132,21 +112,6 @@ abstract class ScalarTypeGeoLatteBase<T extends Geometry> implements ScalarType<
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDateTimeCapable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long asVersion(T value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertFromMillis(long dateTime) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T jsonRead(JsonParser parser) {
|
||||
return null;
|
||||
|
||||
+1
-1
@@ -228,7 +228,7 @@
|
||||
<dependency>
|
||||
<groupId>com.nuodb.jdbc</groupId>
|
||||
<artifactId>nuodb-jdbc</artifactId>
|
||||
<version>22.0.0</version>
|
||||
<version>23.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class Config {
|
||||
/**
|
||||
* Common optional docker parameters that we just transfer to docker properties.
|
||||
*/
|
||||
private static final String[] DOCKER_TEST_PARAMS = {"fastStartMode", "inMemory", "initSqlFile", "seedSqlFile", "adminUser", "adminPassword", "extraDb", "extraDb.dbName", "extraDb.username", "extraDb.password", "extraDb.initSqlFile", "extraDb.seedSqlFile"};
|
||||
private static final String[] DOCKER_TEST_PARAMS = {"fastStartMode", "inMemory", "initSqlFile", "seedSqlFile", "adminUser", "adminPassword", "extraDb", "extraDb.dbName", "extraDb.username", "extraDb.password", "extraDb.extensions", "extraDb.initSqlFile", "extraDb.seedSqlFile"};
|
||||
private static final String[] DOCKER_PLATFORM_PARAMS = {"containerName", "image", "internalPort", "startMode", "shutdownMode", "maxReadyAttempts", "tmpfs", "collation", "characterSet"};
|
||||
|
||||
private static final String DDL_MODE_OPTIONS = "dropCreate, create, none, migration, createOnly or migrationDropCreate";
|
||||
@@ -224,14 +224,22 @@ class Config {
|
||||
properties.setProperty(dsKey, val);
|
||||
}
|
||||
|
||||
void setUrl(String urlPattern) {
|
||||
String val = getKey("url", urlPattern);
|
||||
private void setUrl(String key, String urlPattern) {
|
||||
String val = getKey(key, urlPattern);
|
||||
val = val.replace("${host}", host());
|
||||
val = val.replace("${port}", String.valueOf(port));
|
||||
val = val.replace("${databaseName}", databaseName);
|
||||
this.url = val;
|
||||
}
|
||||
|
||||
void setUrl(String urlPattern) {
|
||||
setUrl("url", urlPattern);
|
||||
}
|
||||
|
||||
void setExtraUrl(String urlPattern) {
|
||||
setUrl("extraDb.url", urlPattern);
|
||||
}
|
||||
|
||||
String host() {
|
||||
String explicitDockerHost = getKey("dockerHost", null);
|
||||
return getKey("host", dockerHost.dockerHost(explicitDockerHost));
|
||||
@@ -343,9 +351,17 @@ class Config {
|
||||
|
||||
void setExtensions(String defaultValue) {
|
||||
// ebean.test.postgres.extensions=hstore,pgcrypto
|
||||
String val = getKey("extensions", defaultValue);
|
||||
setExtensionsInternal("extensions", defaultValue);
|
||||
}
|
||||
|
||||
void setExtraExtensions(String defaultValue) {
|
||||
setExtensionsInternal("extraDb.extensions", defaultValue);
|
||||
}
|
||||
|
||||
void setExtensionsInternal(String key, String defaultValue) {
|
||||
String val = getKey(key, defaultValue);
|
||||
if (val != null) {
|
||||
dockerProperties.setProperty(dockerKey("extensions"), trimExtensions(val));
|
||||
dockerProperties.setProperty(dockerKey(key), trimExtensions(val));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,25 +6,21 @@ class OracleSetup implements PlatformSetup {
|
||||
|
||||
@Override
|
||||
public Properties setup(Config config) {
|
||||
|
||||
config.ddlMode("dropCreate");
|
||||
config.setDefaultPort(1521);
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setDatabaseName("XE");
|
||||
config.setUrl("jdbc:oracle:thin:@localhost:${port}:${databaseName}");
|
||||
config.setDriver("oracle.jdbc.driver.OracleDriver");
|
||||
config.datasourceDefaults();
|
||||
return dockerProperties(config);
|
||||
}
|
||||
|
||||
private Properties dockerProperties(Config dbConfig) {
|
||||
|
||||
if (!dbConfig.isUseDocker()) {
|
||||
return new Properties();
|
||||
}
|
||||
|
||||
dbConfig.setDockerVersion("latest");
|
||||
dbConfig.setDockerVersion("21.3.0-slim");
|
||||
return dbConfig.getDockerProperties();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,7 @@ class PostgisSetup implements PlatformSetup {
|
||||
@Override
|
||||
public Properties setup(Config config) {
|
||||
int defaultPort = config.isUseDocker() ? 7432 : 5432;
|
||||
|
||||
config.setDockerPlatform("postgres");
|
||||
config.setDockerPlatform("postgis");
|
||||
config.ddlMode("dropCreate");
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setUsernameDefault();
|
||||
@@ -35,14 +34,18 @@ class PostgisSetup implements PlatformSetup {
|
||||
}
|
||||
config.setExtensions("hstore,pgcrypto,postgis");
|
||||
config.setDockerContainerName("ut_postgis");
|
||||
config.setDockerImage("postgis/postgis");
|
||||
config.setDockerVersion("14");
|
||||
config.setDockerVersion("14-3.2");
|
||||
return config.getDockerProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupExtraDbDataSource(Config config) {
|
||||
// not supported yet
|
||||
int defaultPort = config.isUseDocker() ? 7432 : 5432;
|
||||
config.setDefaultPort(defaultPort);
|
||||
config.setExtraUsernameDefault();
|
||||
config.setExtraDbPasswordDefault();
|
||||
config.setExtraUrl("jdbc:postgresql_lwgis://${host}:${port}/${databaseName}");
|
||||
config.extraDatasourceDefaults();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,43 @@ class ConfigTest {
|
||||
assertThat(config.trimExtensions(" a , , b ")).isEqualTo("a,b");
|
||||
}
|
||||
|
||||
@Test
|
||||
void extensions_whenNoSetValues() {
|
||||
DatabaseConfig databaseConfig = new DatabaseConfig();
|
||||
databaseConfig.loadFromProperties(new Properties());
|
||||
|
||||
Config config = new Config("db", "postgis", "db", databaseConfig);
|
||||
|
||||
config.setUsernameDefault();
|
||||
config.setPasswordDefault();
|
||||
config.setDefaultPort(42);
|
||||
config.setExtensions("a,b");
|
||||
config.setExtraExtensions("c,d");
|
||||
|
||||
Properties dockerProperties = config.getDockerProperties();
|
||||
assertThat(dockerProperties.getProperty("postgis.extensions")).isEqualTo("a,b");
|
||||
assertThat(dockerProperties.getProperty("postgis.extraDb.extensions")).isEqualTo("c,d");
|
||||
}
|
||||
|
||||
@Test
|
||||
void extensions_whenSetValues() {
|
||||
DatabaseConfig databaseConfig = new DatabaseConfig();
|
||||
Properties properties = new Properties();
|
||||
properties.setProperty("ebean.test.extensions", "x,y");
|
||||
properties.setProperty("ebean.test.extraDb.extensions", "z");
|
||||
databaseConfig.loadFromProperties(properties);
|
||||
|
||||
Config config = new Config("db", "postgis", "db", databaseConfig);
|
||||
|
||||
config.setExtensions("a,b");
|
||||
config.setExtraExtensions("c,d");
|
||||
|
||||
Properties dockerProperties = config.getDockerProperties();
|
||||
assertThat(dockerProperties.getProperty("postgis.extensions")).isEqualTo("x,y");
|
||||
assertThat(dockerProperties.getProperty("postgis.extraDb.extensions")).isEqualTo("z");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void extraDbProperties_basic() {
|
||||
Properties p = new Properties();
|
||||
|
||||
@@ -4,6 +4,7 @@ package io.ebean.xtest.event;
|
||||
import io.ebean.Database;
|
||||
import io.ebean.DatabaseFactory;
|
||||
import io.ebean.Transaction;
|
||||
import io.ebean.ValuePair;
|
||||
import io.ebean.config.DatabaseConfig;
|
||||
import io.ebean.event.BeanDeleteIdRequest;
|
||||
import io.ebean.event.BeanPersistAdapter;
|
||||
@@ -13,9 +14,7 @@ import org.tests.model.basic.EBasicVer;
|
||||
import org.tests.model.basic.UTDetail;
|
||||
import org.tests.model.basic.UTMaster;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -26,8 +25,30 @@ public class BeanPersistControllerTest {
|
||||
private final PersistAdapter stopPersistingAdapter = new PersistAdapter(false);
|
||||
|
||||
@Test
|
||||
public void issue_1341() {
|
||||
public void issued1() {
|
||||
Database db = getDatabase(continuePersistingAdapter);
|
||||
|
||||
UTMaster bean0 = new UTMaster("m0");
|
||||
bean0.setJournal(new UTMaster.Journal());
|
||||
db.save(bean0);
|
||||
|
||||
UTMaster change0 = db.find(UTMaster.class, bean0.getId());
|
||||
change0.setName("change0");
|
||||
db.save(change0);
|
||||
|
||||
UTMaster change1 = db.find(UTMaster.class, bean0.getId());
|
||||
change1.setName("change1");
|
||||
db.save(change1);
|
||||
|
||||
UTMaster again = db.find(UTMaster.class, bean0.getId());
|
||||
UTMaster.Journal journal = again.getJournal();
|
||||
assertThat(journal.getEntries()).hasSize(2);
|
||||
|
||||
db.shutdown();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void issue_1341() {
|
||||
Database db = getDatabase(continuePersistingAdapter);
|
||||
|
||||
UTMaster bean0 = new UTMaster("one0");
|
||||
@@ -118,7 +139,6 @@ public class BeanPersistControllerTest {
|
||||
}
|
||||
|
||||
private Database getDatabase(PersistAdapter persistAdapter) {
|
||||
|
||||
DatabaseConfig config = new DatabaseConfig();
|
||||
config.setName("h2ebasicver");
|
||||
config.loadFromProperties();
|
||||
@@ -133,7 +153,6 @@ public class BeanPersistControllerTest {
|
||||
config.getClasses().add(UTDetail.class);
|
||||
|
||||
config.add(persistAdapter);
|
||||
|
||||
return DatabaseFactory.create(config);
|
||||
}
|
||||
|
||||
@@ -177,6 +196,16 @@ public class BeanPersistControllerTest {
|
||||
// invoke lazy loading ... which invoke the flush of the jdbc batch
|
||||
detail.setQty(42);
|
||||
}
|
||||
if (bean instanceof UTMaster) {
|
||||
UTMaster master = (UTMaster)bean;
|
||||
UTMaster.Journal journal = master.getJournal();
|
||||
if (journal == null) {
|
||||
journal = new UTMaster.Journal();
|
||||
master.setJournal(journal);
|
||||
}
|
||||
// modify a "mutable scalar type" in preUpdate, should be included in update
|
||||
journal.addEntry();
|
||||
}
|
||||
|
||||
return continueDefaultPersisting;
|
||||
}
|
||||
|
||||
+6
-6
@@ -178,16 +178,16 @@ class DefaultPersistenceContextTest {
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(100);
|
||||
assertThat(pc.size(Contact.class)).isEqualTo(1010);
|
||||
|
||||
addCustomers(pc, 200, 100);
|
||||
addContacts(pc, 2000, 1010);
|
||||
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(200);
|
||||
assertThat(pc.size(Contact.class)).isEqualTo(2020);
|
||||
addCustomers(pc, 200, 103);
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(203);
|
||||
addContacts(pc, 2000, 1013);
|
||||
assertThat(pc.size(Contact.class)).isEqualTo(2023);
|
||||
pc.endIterate();
|
||||
|
||||
System.gc();
|
||||
Thread.sleep(50); // give the GC some time
|
||||
Thread.sleep(100); // give the GC some time
|
||||
|
||||
// back to pre beginIterate() now
|
||||
assertThat(pc.size(Customer.class)).isEqualTo(100);
|
||||
assertThat(pc.size(Contact.class)).isEqualTo(1010);
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import io.ebean.test.containers.PostgresContainer;
|
||||
public class StartPostgres {
|
||||
|
||||
public static void main(String[] args) {
|
||||
PostgresContainer.builder("13")
|
||||
.port(5432)
|
||||
PostgresContainer.builder("14")
|
||||
.dbName("unit")
|
||||
.user("unit")
|
||||
.password("unit")
|
||||
.containerName("pg13x")
|
||||
//.port(6432)
|
||||
//.user("unit")
|
||||
//.password("test")
|
||||
//.containerName("ut_postgres")
|
||||
.extensions("hstore,pgcrypto")
|
||||
.build()
|
||||
.startWithDropCreate();
|
||||
|
||||
@@ -7,45 +7,15 @@ import org.tests.model.basic.ESimple;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class TestSimpleIdInsert extends BaseTestCase {
|
||||
class TestSimpleIdInsert extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
void test() {
|
||||
ESimple e = new ESimple();
|
||||
e.setName("name");
|
||||
|
||||
DB.save(e);
|
||||
|
||||
assertNotNull(e.getId());
|
||||
|
||||
}
|
||||
|
||||
// // This test fails with jdbc drivers that don't
|
||||
// // support batch insert with getGeneratedKeys
|
||||
// public void testJdbcBatch() {
|
||||
//
|
||||
// GlobalProperties.put("datasource.default", "hsqldb");
|
||||
// GlobalProperties.put("ebean.classes", ESimple.class.getName());
|
||||
//
|
||||
// Transaction transaction = DB.beginTransaction();
|
||||
// try {
|
||||
// transaction.setBatchMode(true);
|
||||
// transaction.setLogLevel(LogLevel.SQL);
|
||||
// ESimple e = new ESimple();
|
||||
// e.setName("name");
|
||||
// DB.save(e);
|
||||
//
|
||||
// ESimple e2 = new ESimple();
|
||||
// e2.setName("name2");
|
||||
// DB.save(e2);
|
||||
// transaction.commit();
|
||||
//
|
||||
// Assert.assertNotNull(e.getId());
|
||||
// Assert.assertNotNull(e2.getId());
|
||||
//
|
||||
// } finally {
|
||||
// DB.endTransaction();
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.tests.json;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.json.EBasicJsonBString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestDbJsonBStringType {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
var bean = new EBasicJsonBString("hi").content("{\"mykey\": 42}"); // JsonB format with space
|
||||
DB.save(bean);
|
||||
|
||||
var found = DB.find(EBasicJsonBString.class, bean.id());
|
||||
// Note that Postgres JsonB will format the result
|
||||
assertThat(found.content()).isEqualTo("{\"mykey\": 42}");
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
// change title only, expect content not in update
|
||||
found.title("changeTitleOnly");
|
||||
DB.save(found);
|
||||
List<String> sql = LoggedSql.collect();
|
||||
// update does NOT contain our json content
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_bstring set title=?, version=? where id=? and version=?");
|
||||
|
||||
// change title and content
|
||||
found.title("changeAgain");
|
||||
found.content("{\"mykey\": 92}");
|
||||
DB.save(found);
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_bstring set title=?, content=?, version=? where id=? and version=?");
|
||||
|
||||
|
||||
// change content only
|
||||
found.content("{\"mykey\": 95}");
|
||||
DB.save(found);
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_bstring set content=?, version=? where id=? and version=?");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.tests.json;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.json.EBasicJsonString;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class TestDbJsonStringType {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
var bean = new EBasicJsonString("hi").content("{\"mykey\": 52}"); // JsonB format with space
|
||||
DB.save(bean);
|
||||
|
||||
var found = DB.find(EBasicJsonString.class, bean.id());
|
||||
// Note that Postgres JsonB will format the result
|
||||
assertThat(found.content()).isEqualTo("{\"mykey\": 52}");
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
// change title only, expect content not in update
|
||||
found.title("changeTitleOnly");
|
||||
DB.save(found);
|
||||
List<String> sql = LoggedSql.collect();
|
||||
// update does NOT contain our json content
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_string set title=?, version=? where id=? and version=?");
|
||||
|
||||
// change title and content
|
||||
found.title("changeAgain");
|
||||
found.content("{\"mykey\": 92}");
|
||||
DB.save(found);
|
||||
sql = LoggedSql.collect();
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_string set title=?, content=?, version=? where id=? and version=?");
|
||||
|
||||
|
||||
// change content only
|
||||
found.content("{\"mykey\": 95}");
|
||||
DB.save(found);
|
||||
sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).contains("update ebasic_json_string set content=?, version=? where id=? and version=?");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
package org.tests.model.basic;
|
||||
|
||||
import io.ebean.Model;
|
||||
import io.ebean.annotation.DbJsonB;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,12 +22,31 @@ public class UTMaster extends Model {
|
||||
|
||||
LocalDate eventDate;
|
||||
|
||||
@DbJsonB
|
||||
Journal journal;
|
||||
|
||||
@Version
|
||||
Integer version;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
List<UTDetail> details;
|
||||
|
||||
/**
|
||||
* Mutating content persisted as JSON.
|
||||
*/
|
||||
public static class Journal {
|
||||
private List<String> entries = new ArrayList<>();
|
||||
public List<String> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
public void setEntries(List<String> entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
public void addEntry() {
|
||||
entries.add(LocalDateTime.now().toString());
|
||||
}
|
||||
}
|
||||
|
||||
public UTMaster() {
|
||||
|
||||
}
|
||||
@@ -74,6 +95,14 @@ public class UTMaster extends Model {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public Journal getJournal() {
|
||||
return journal;
|
||||
}
|
||||
|
||||
public void setJournal(Journal journal) {
|
||||
this.journal = journal;
|
||||
}
|
||||
|
||||
public List<UTDetail> getDetails() {
|
||||
return details;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
import io.ebean.annotation.DbJsonB;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class EBasicJsonBString {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String title;
|
||||
|
||||
@DbJsonB
|
||||
String content;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public EBasicJsonBString(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public EBasicJsonBString id(long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String title() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public EBasicJsonBString title(String title) {
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public EBasicJsonBString content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public EBasicJsonBString version(long version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.tests.model.json;
|
||||
|
||||
import io.ebean.annotation.DbJson;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class EBasicJsonString {
|
||||
|
||||
@Id
|
||||
long id;
|
||||
|
||||
String title;
|
||||
|
||||
@DbJson
|
||||
String content;
|
||||
|
||||
@Version
|
||||
long version;
|
||||
|
||||
public EBasicJsonString(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public long id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public EBasicJsonString id(long id) {
|
||||
this.id = id;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String title() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public EBasicJsonString title(String title) {
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
public String content() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public EBasicJsonString content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public EBasicJsonString version(long version) {
|
||||
this.version = version;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
ebean.test.platform=nuodb
|
||||
ebean.test.dbName=testdb
|
||||
ebean.test.nuodb.version=latest
|
||||
ebean.test.nuodb.version=4.3.2
|
||||
|
||||
@@ -147,40 +147,4 @@ public class PostgresPlatform extends DatabasePlatform {
|
||||
}
|
||||
return FOR_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tablePartitionsExist(Connection connection, String table) throws SQLException {
|
||||
try (PreparedStatement statement = connection.prepareStatement("select count(*) from pg_inherits i WHERE i.inhparent = ?::regclass")) {
|
||||
statement.setString(1, table);
|
||||
try (ResultSet resultSet = statement.executeQuery()) {
|
||||
return resultSet.next() && resultSet.getInt(1) > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return SQL using built in partition helper functions to create some initial partitions.
|
||||
* <p>
|
||||
* Only use this if extra-ddl doesn't have some initial partitions defined (which it should).
|
||||
*/
|
||||
@Override
|
||||
public String tablePartitionInit(String tableName, PartitionMode mode) {
|
||||
// default partition required pg11 but this is only used for testing but bumped test docker container to pg14 by default
|
||||
String[] schemaTable = SplitName.split(tableName);
|
||||
|
||||
String baseTable;
|
||||
String plusSchema;
|
||||
if (schemaTable[0] == null) {
|
||||
plusSchema = "";
|
||||
baseTable = tableName;
|
||||
} else {
|
||||
// table in an explicit schema
|
||||
plusSchema = ",'" + schemaTable[0] + "'";
|
||||
baseTable = schemaTable[1];
|
||||
}
|
||||
return
|
||||
"create table " + tableName + "_default" + " partition of " + tableName + " default;\n" +
|
||||
"select partition('" + mode.name().toLowerCase() + "','" + baseTable + "',1" + plusSchema + ");";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-16
@@ -1,6 +1,5 @@
|
||||
package io.ebean.platform.postgres;
|
||||
|
||||
import io.ebean.annotation.PartitionMode;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.config.PlatformConfig;
|
||||
import io.ebean.config.dbplatform.DatabasePlatform;
|
||||
@@ -16,7 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
class PostgresPlatformTest {
|
||||
|
||||
@Test
|
||||
void testUuidType() {
|
||||
void testUuidType() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
platform.configure(new PlatformConfig());
|
||||
|
||||
@@ -26,20 +25,6 @@ class PostgresPlatformTest {
|
||||
assertThat(columnDefn).isEqualTo("uuid");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tablePartitionInit() {
|
||||
String sql = new PostgresPlatform().tablePartitionInit("foo", PartitionMode.WEEK);
|
||||
assertThat(sql).isEqualTo("create table foo_default partition of foo default;\n" +
|
||||
"select partition('week','foo',1);");
|
||||
}
|
||||
|
||||
@Test
|
||||
void tablePartitionInit_withSchema() {
|
||||
String sql = new PostgresPlatform().tablePartitionInit("bar.foo", PartitionMode.WEEK);
|
||||
assertThat(sql).isEqualTo("create table bar.foo_default partition of bar.foo default;\n" +
|
||||
"select partition('week','foo',1,'bar');");
|
||||
}
|
||||
|
||||
@Test
|
||||
void default_forUpdate_expect_noKeyUsed() {
|
||||
PostgresPlatform platform = new PostgresPlatform();
|
||||
|
||||
@@ -44,10 +44,10 @@
|
||||
<ebean-ddl-runner.version>2.0</ebean-ddl-runner.version>
|
||||
<ebean-migration-auto.version>1.2</ebean-migration-auto.version>
|
||||
<ebean-migration.version>13.6.0</ebean-migration.version>
|
||||
<ebean-test-containers.version>6.0</ebean-test-containers.version>
|
||||
<ebean-test-containers.version>6.1</ebean-test-containers.version>
|
||||
<ebean-datasource.version>8.0</ebean-datasource.version>
|
||||
<ebean-agent.version>13.6.3</ebean-agent.version>
|
||||
<ebean-maven-plugin.version>13.6.3</ebean-maven-plugin.version>
|
||||
<ebean-agent.version>13.6.4</ebean-agent.version>
|
||||
<ebean-maven-plugin.version>13.6.4</ebean-maven-plugin.version>
|
||||
<surefire.useModulePath>false</surefire.useModulePath>
|
||||
</properties>
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
<path>
|
||||
<groupId>io.ebean</groupId>
|
||||
<artifactId>querybean-generator</artifactId>
|
||||
<version>13.6.4-SNAPSHOT</version>
|
||||
<version>13.6.5-SNAPSHOT</version>
|
||||
</path>
|
||||
</annotationProcessorPaths>
|
||||
</configuration>
|
||||
|
||||
Reference in New Issue
Block a user