Merge pull request #567 from aperaverzeu/4.3-FEATURE-CAY-provide-ability-to-add-extra-modules-in-declarative-way
Provide ability to add extra modules in declarative way
diff --git a/.github/workflows/verify-deploy-on-push.yml b/.github/workflows/verify-deploy-on-push.yml
index dabe35d..a891b5c 100644
--- a/.github/workflows/verify-deploy-on-push.yml
+++ b/.github/workflows/verify-deploy-on-push.yml
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-name: verify and deploy
+name: verify and deploy 5.0
on: push
diff --git a/.github/workflows/verify-on-pr.yml b/.github/workflows/verify-on-pr.yml
index 79390a4..bf0e8de 100644
--- a/.github/workflows/verify-on-pr.yml
+++ b/.github/workflows/verify-on-pr.yml
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-name: verify PR
+name: verify PR 5.0
on: pull_request
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 4d2d670..77fdda9 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -36,6 +36,8 @@
CAY-2781 Enable 'Create PK properties' by default in the cgen configuration
CAY-2784 Remove 'Use Java primitive types' option from dbimport
CAY-2788 DbImport: Add fallback option for the batch attribute loader
+CAY-2795 Add unit tests for the Json type
+CAY-2802 Upgrade Gradle to 7.6.1
Bug Fixes:
@@ -49,4 +51,5 @@
CAY-2774 Overriding service ordering in DI List causes DIRuntimeException
CAY-2782 Modeler: save button becomes active on DataMap comment field focus
CAY-2783 DbEntity to ObjEntity synchronization should check mandatory flag for primitive java types
-CAY-2792 Fix Insertion Order For Reflexive DataObjects
\ No newline at end of file
+CAY-2792 Fix Insertion Order For Reflexive DataObjects
+CAY-2801 Incorrect equals() implementation in IdGenerationMarker could cause data missing in the commit
\ No newline at end of file
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java
index 5f769c9..3bff928 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table1.java
@@ -8,11 +8,11 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table1;
import org.apache.cayenne.crypto.db.Table7;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.ListProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.StringProperty;
/**
@@ -25,7 +25,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table1> SELF = PropertyFactory.createSelf(Table1.class);
+ public static final SelfProperty<Table1> SELF = PropertyFactory.createSelf(Table1.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table1", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table2.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table2.java
index 7ccd3e5..f8f0272 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table2.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table2.java
@@ -7,9 +7,9 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table2;
import org.apache.cayenne.exp.property.BaseProperty;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
/**
* Class _Table2 was generated by Cayenne.
@@ -21,7 +21,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table2> SELF = PropertyFactory.createSelf(Table2.class);
+ public static final SelfProperty<Table2> SELF = PropertyFactory.createSelf(Table2.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table2", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table3.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table3.java
index bc9e695..c01e383 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table3.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table3.java
@@ -6,9 +6,9 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table3;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.StringProperty;
/**
@@ -21,7 +21,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table3> SELF = PropertyFactory.createSelf(Table3.class);
+ public static final SelfProperty<Table3> SELF = PropertyFactory.createSelf(Table3.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table3", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
index 862d110..591f439 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table4.java
@@ -6,10 +6,10 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table4;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.StringProperty;
/**
@@ -22,7 +22,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table4> SELF = PropertyFactory.createSelf(Table4.class);
+ public static final SelfProperty<Table4> SELF = PropertyFactory.createSelf(Table4.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table4", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table5.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table5.java
index f5cd4d8..b12bd98 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table5.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table5.java
@@ -6,10 +6,10 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table5;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
/**
* Class _Table5 was generated by Cayenne.
@@ -21,7 +21,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table5> SELF = PropertyFactory.createSelf(Table5.class);
+ public static final SelfProperty<Table5> SELF = PropertyFactory.createSelf(Table5.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table5", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table6.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table6.java
index 9404fd8..b925ff7 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table6.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table6.java
@@ -6,10 +6,10 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table6;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
/**
* Class _Table6 was generated by Cayenne.
@@ -21,7 +21,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table6> SELF = PropertyFactory.createSelf(Table6.class);
+ public static final SelfProperty<Table6> SELF = PropertyFactory.createSelf(Table6.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table6", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java
index ef0cc9e..11141ab 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table7.java
@@ -11,6 +11,7 @@
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.NumericProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.StringProperty;
/**
@@ -23,7 +24,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table7> SELF = PropertyFactory.createSelf(Table7.class);
+ public static final SelfProperty<Table7> SELF = PropertyFactory.createSelf(Table7.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table7", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table8.java b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table8.java
index 1003a6f..cc632f9 100644
--- a/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table8.java
+++ b/cayenne-crypto/src/test/java/org/apache/cayenne/crypto/db/auto/_Table8.java
@@ -6,9 +6,9 @@
import org.apache.cayenne.BaseDataObject;
import org.apache.cayenne.crypto.db.Table8;
-import org.apache.cayenne.exp.property.EntityProperty;
import org.apache.cayenne.exp.property.NumericIdProperty;
import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
import org.apache.cayenne.exp.property.StringProperty;
/**
@@ -21,7 +21,7 @@
private static final long serialVersionUID = 1L;
- public static final EntityProperty<Table8> SELF = PropertyFactory.createSelf(Table8.class);
+ public static final SelfProperty<Table8> SELF = PropertyFactory.createSelf(Table8.class);
public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "Table8", Integer.class);
public static final String ID_PK_COLUMN = "ID";
diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/AttributeLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/AttributeLoaderIT.java
index d811e48..378de73 100644
--- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/AttributeLoaderIT.java
+++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/AttributeLoaderIT.java
@@ -44,8 +44,9 @@
DbEntity artist = getDbEntity("ARTIST");
DbAttribute a = getDbAttribute(artist, "ARTIST_ID");
assertNotNull(a);
- if(accessStackAdapter.onlyGenericNumberType()) {
- assertEquals(Types.INTEGER, a.getType());
+ if (accessStackAdapter.onlyGenericNumberType()) {
+ // All integer types are mapped to NUMERIC in Oracle DB.
+ assertEquals(Types.NUMERIC, a.getType());
} else {
assertEquals(Types.BIGINT, a.getType());
}
@@ -105,15 +106,27 @@
// check varchar
assertEquals(msgForTypeMismatch(Types.VARCHAR, varcharAttr), Types.VARCHAR, varcharAttr.getType());
assertEquals(255, varcharAttr.getMaxLength());
+
// check integer
- assertEquals(msgForTypeMismatch(Types.INTEGER, integerAttr), Types.INTEGER, integerAttr.getType());
+ // All integer types are mapped to NUMERIC in Oracle DB.
+ if (accessStackAdapter.onlyGenericNumberType()) {
+ assertEquals(msgForTypeMismatch(Types.NUMERIC, integerAttr), Types.NUMERIC, integerAttr.getType());
+ } else {
+ assertEquals(msgForTypeMismatch(Types.INTEGER, integerAttr), Types.INTEGER, integerAttr.getType());
+ }
+
// check float
assertTrue(msgForTypeMismatch(Types.FLOAT, floatAttr), Types.FLOAT == floatAttr.getType()
|| Types.DOUBLE == floatAttr.getType() || Types.REAL == floatAttr.getType());
// check smallint
- assertTrue(msgForTypeMismatch(Types.SMALLINT, smallintAttr), Types.SMALLINT == smallintAttr.getType()
- || Types.INTEGER == smallintAttr.getType());
+ // All integer types are mapped to NUMERIC in Oracle DB.
+ if (accessStackAdapter.onlyGenericNumberType()) {
+ assertEquals(msgForTypeMismatch(Types.NUMERIC, smallintAttr), Types.NUMERIC, smallintAttr.getType());
+ } else {
+ assertTrue(msgForTypeMismatch(Types.SMALLINT, smallintAttr),
+ Types.SMALLINT == smallintAttr.getType() || Types.INTEGER == smallintAttr.getType());
+ }
}
private void assertGenerated() {
diff --git a/cayenne-gradle-plugin/gradle/wrapper/gradle-wrapper.properties b/cayenne-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
index 1c1126a..edd4bfc 100644
--- a/cayenne-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
+++ b/cayenne-gradle-plugin/gradle/wrapper/gradle-wrapper.properties
@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/IdGenerationMarker.java b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/IdGenerationMarker.java
index 299e352..5aead02 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/flush/IdGenerationMarker.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/flush/IdGenerationMarker.java
@@ -31,10 +31,8 @@
class IdGenerationMarker implements Serializable, InternalUnsupportedTypeFactory.Marker {
private static final long serialVersionUID = -5339942931435878094L;
- private final static IdGenerationMarker INSTANCE = new IdGenerationMarker();
-
static IdGenerationMarker marker() {
- return INSTANCE;
+ return new IdGenerationMarker();
}
private IdGenerationMarker() {
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
index 1f48871..eae298b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/db2/DB2Adapter.java
@@ -35,6 +35,7 @@
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.JsonType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
@@ -78,10 +79,13 @@
super.configureExtendedTypes(map);
// create specially configured CharType handler
- map.registerType(new CharType(true, true));
+ CharType charType = new CharType(true, true);
+ map.registerType(charType);
// configure boolean type to work with numeric columns
map.registerType(new DB2BooleanType());
+
map.registerType(new ByteArrayType(false, false));
+ map.registerType(new JsonType(charType, true));
}
/**
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
index ea13e66..e598202 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/h2/H2Adapter.java
@@ -26,6 +26,7 @@
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.JsonType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
@@ -36,6 +37,7 @@
import org.apache.cayenne.query.SQLAction;
import org.apache.cayenne.resource.ResourceLocator;
+import java.sql.Types;
import java.util.List;
/**
@@ -106,6 +108,19 @@
super.configureExtendedTypes(map);
// create specially configured CharType handler
- map.registerType(new H2CharType());
+ H2CharType charType = new H2CharType();
+ map.registerType(charType);
+
+ map.registerType(new JsonType(charType, false));
}
+
+ @Override
+ public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+ if ("json".equalsIgnoreCase(typeName)) {
+ type = Types.OTHER;
+ }
+ return super.buildAttribute(name, typeName, type, size, scale, allowNulls);
+ }
+
+
}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
index a2273c0..b19c685 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/hsqldb/HSQLDBAdapter.java
@@ -28,6 +28,7 @@
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.JsonType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
@@ -50,7 +51,7 @@
* DbAdapter implementation for the <a href="http://hsqldb.sourceforge.net/">
* HSQLDB RDBMS </a>. Sample connection settings to use with HSQLDB are shown
* below:
- *
+ *
* <pre>
* test-hsqldb.jdbc.username = test
* test-hsqldb.jdbc.password = secret
@@ -80,7 +81,10 @@
super.configureExtendedTypes(map);
// create specially configured CharType handler
- map.registerType(new CharType(true, true));
+ CharType charType = new CharType(true, true);
+ map.registerType(charType);
+
+ map.registerType(new JsonType(charType, true));
}
/**
@@ -104,7 +108,7 @@
/**
* Generate fully-qualified name for 1.8 and on. Subclass generates
* unqualified name.
- *
+ *
* @since 1.2
*/
protected String getTableName(DbEntity entity) {
@@ -114,7 +118,7 @@
/**
* Returns DbEntity schema name for 1.8 and on. Subclass generates
* unqualified name.
- *
+ *
* @since 1.2
*/
protected String getSchemaName(DbEntity entity) {
@@ -123,7 +127,7 @@
/**
* Uses special action builder to create the right action.
- *
+ *
* @since 1.2
*/
@Override
@@ -133,7 +137,7 @@
/**
* Returns a DDL string to create a unique constraint over a set of columns.
- *
+ *
* @since 1.1
*/
@Override
@@ -171,7 +175,7 @@
/**
* Adds an ADD CONSTRAINT clause to a relationship constraint.
- *
+ *
* @see JdbcAdapter#createFkConstraint(DbRelationship)
*/
@Override
@@ -224,7 +228,7 @@
/**
* Uses "CREATE CACHED TABLE" instead of "CREATE TABLE".
- *
+ *
* @since 1.2
*/
@Override
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
index 2f2b7b3..276fbe8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/oracle/OracleAdapter.java
@@ -36,9 +36,11 @@
import org.apache.cayenne.access.translator.ParameterBinding;
import org.apache.cayenne.access.translator.ejbql.EJBQLTranslatorFactory;
import org.apache.cayenne.access.types.ByteType;
+import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.JsonType;
import org.apache.cayenne.access.types.ShortType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
@@ -200,7 +202,8 @@
super.configureExtendedTypes(map);
// create specially configured CharType handler
- map.registerType(new OracleCharType());
+ OracleCharType charType = new OracleCharType();
+ map.registerType(charType);
// create specially configured ByteArrayType handler
map.registerType(new OracleByteArrayType());
@@ -211,7 +214,9 @@
// At least on MacOS X, driver does not handle Short and Byte properly
map.registerType(new ShortType(true));
map.registerType(new ByteType(true));
+
map.registerType(new OracleBooleanType());
+ map.registerType(new JsonType(charType, true));
}
/**
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
index d1373a0..465433b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/postgres/PostgresAdapter.java
@@ -116,10 +116,13 @@
@Override
public DbAttribute buildAttribute(String name, String typeName, int type, int size, int scale, boolean allowNulls) {
+ if ("json".equalsIgnoreCase(typeName)) {
+ type = Types.OTHER;
+ }
// "bytea" maps to pretty much any binary type, so
// it is up to us to select the most sensible default.
// And the winner is LONGVARBINARY
- if (BYTEA.equalsIgnoreCase(typeName)) {
+ else if (BYTEA.equalsIgnoreCase(typeName)) {
type = Types.LONGVARBINARY;
}
// oid is returned as INTEGER, need to make it BLOB
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
index e191bc8..b3b4484 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/sqlserver/SQLServerAdapter.java
@@ -24,8 +24,11 @@
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.sqlbuilder.sqltree.SQLTreeProcessor;
+import org.apache.cayenne.access.types.CharType;
import org.apache.cayenne.access.types.ExtendedType;
import org.apache.cayenne.access.types.ExtendedTypeFactory;
+import org.apache.cayenne.access.types.ExtendedTypeMap;
+import org.apache.cayenne.access.types.JsonType;
import org.apache.cayenne.access.types.ValueObjectTypeRegistry;
import org.apache.cayenne.configuration.Constants;
import org.apache.cayenne.configuration.RuntimeProperties;
@@ -120,6 +123,15 @@
return new SQLServerTreeProcessor();
}
+ @Override
+ protected void configureExtendedTypes(ExtendedTypeMap map) {
+ super.configureExtendedTypes(map);
+
+ CharType charType = new CharType(true, false);
+ map.registerType(charType);
+ map.registerType(new JsonType(charType, true));
+ }
+
/**
* Uses SQLServerActionBuilder to create the right action.
*
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/value/Json.java b/cayenne-server/src/main/java/org/apache/cayenne/value/Json.java
index d824b41..309ce55 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/value/Json.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/value/Json.java
@@ -19,20 +19,31 @@
package org.apache.cayenne.value;
+import java.io.Serializable;
import java.util.Objects;
import org.apache.cayenne.value.json.JsonUtils;
+import org.apache.cayenne.value.json.MalformedJsonException;
/**
* A Cayenne-supported values object that holds Json string.
*
* @since 4.2
*/
-public class Json {
+public class Json implements Serializable {
+ private static final long serialVersionUID = 7594825997288498022L;
private final String json;
+ /**
+ *
+ * @param json json string representation
+ * @throws MalformedJsonException if json is empty or blank
+ */
public Json(String json) {
+ if (json.isBlank()) {
+ throw new MalformedJsonException("Unexpected EOF");
+ }
this.json = json;
}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/value/json/AbstractJsonConsumer.java b/cayenne-server/src/main/java/org/apache/cayenne/value/json/AbstractJsonConsumer.java
index d364868..254213c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/value/json/AbstractJsonConsumer.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/value/json/AbstractJsonConsumer.java
@@ -52,8 +52,11 @@
protected abstract T output();
T process() {
- JsonTokenizer.JsonToken token;
- while((token = tokenizer.nextToken()).getType() != JsonTokenizer.TokenType.NONE) {
+ JsonTokenizer.JsonToken token = tokenizer.nextToken();
+ if (token.getType() == JsonTokenizer.TokenType.NONE) {
+ throw new MalformedJsonException("Unexpected EOF");
+ }
+ do {
switch (token.getType()) {
case ARRAY_START:
onArrayStart();
@@ -79,7 +82,7 @@
processValue(token);
break;
}
- }
+ } while ((token = tokenizer.nextToken()).getType() != JsonTokenizer.TokenType.NONE);
return output();
}
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonFormatter.java b/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonFormatter.java
index 3d697a1..384143f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonFormatter.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonFormatter.java
@@ -41,6 +41,10 @@
builder.delete(builder.length() - 2, builder.length());
}
builder.append(']');
+ if (State.OBJECT_VALUE.equals(currentState())) {
+ setState(State.OBJECT_KEY);
+ builder.append(", ");
+ }
}
@Override
@@ -54,6 +58,9 @@
builder.delete(builder.length() - 2, builder.length());
}
builder.append('}');
+ if (State.ARRAY.equals(currentState())) {
+ builder.append(", ");
+ }
}
@Override
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonUtils.java b/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonUtils.java
index bbcb0cf..4d407d6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonUtils.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/value/json/JsonUtils.java
@@ -19,6 +19,8 @@
package org.apache.cayenne.value.json;
+import java.util.Objects;
+
/**
* Simple utils to process JSON.
*
@@ -53,7 +55,7 @@
public static boolean compare(String json1, String json2) {
Object object1 = new JsonReader(json1).process();
Object object2 = new JsonReader(json2).process();
- return object1.equals(object2);
+ return Objects.equals(object1, object2);
}
private JsonUtils() {
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
index 96432c1..d17ab2b 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/oracle/types.xml
@@ -106,7 +106,7 @@
<db-type name="RAW"/>
</jdbc-type>
<jdbc-type name="VARCHAR">
- <db-type name="VARCHAR"/>
+ <db-type name="VARCHAR2"/>
</jdbc-type>
<jdbc-type name="NVARCHAR">
<db-type name="NVARCHAR2"/>
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml b/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
index 7b8db93..bb886aa 100644
--- a/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/dba/postgres/types.xml
@@ -84,7 +84,9 @@
<jdbc-type name="NUMERIC">
<db-type name="numeric"/>
</jdbc-type>
- <jdbc-type name="OTHER"/>
+ <jdbc-type name="OTHER">
+ <db-type name="json"/>
+ </jdbc-type>
<jdbc-type name="REAL">
<db-type name="real"/>
</jdbc-type>
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/CircularDependencyIT.java b/cayenne-server/src/test/java/org/apache/cayenne/CircularDependencyIT.java
index 6cfc68f..8d21b73 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/CircularDependencyIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/CircularDependencyIT.java
@@ -22,6 +22,8 @@
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.testdo.relationships.E1;
import org.apache.cayenne.testdo.relationships.E2;
+import org.apache.cayenne.unit.OracleUnitDbAdapter;
+import org.apache.cayenne.unit.UnitDbAdapter;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
@@ -33,8 +35,11 @@
public class CircularDependencyIT extends ServerCase {
@Inject
+ private UnitDbAdapter unitDbAdapter;
+
+ @Inject
private ObjectContext context;
-
+
@Test()
public void testCycle() {
E1 e1 = context.newObject(E1.class);
@@ -50,8 +55,15 @@
context.commitChanges();
fail("Exception should be thrown here");
} catch (CayenneRuntimeException ex) {
- assertTrue("Unexpected exception message: " + ex.getMessage(),
- ex.getMessage().contains("PK is not generated"));
+ // TODO: Oracle adapter still does not fully support key generation.
+ if (unitDbAdapter instanceof OracleUnitDbAdapter) {
+ assertTrue(ex.getCause().getMessage().contains("parent key not found"));
+ } else {
+ assertTrue(String.format("Unexpected exception message: %s%nCause: %s - %s",
+ ex.getMessage(), ex.getCause(),
+ ex.getCause() != null ? ex.getCause().getMessage() : null),
+ ex.getMessage().contains("PK is not generated"));
+ }
}
}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2641IT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2641IT.java
index 98d51b8..aeb062d 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2641IT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/Cay2641IT.java
@@ -35,6 +35,8 @@
import org.apache.cayenne.unit.di.server.UseServerRuntime;
import org.junit.Before;
import org.junit.Test;
+import org.testcontainers.shaded.org.hamcrest.MatcherAssert;
+import org.testcontainers.shaded.org.hamcrest.Matchers;
import java.sql.Types;
import java.util.List;
@@ -78,8 +80,8 @@
String sql = translator.getSql();
assertFalse(sql.contains("t0.NAME"));
- String string = "SELECT t0.SURNAME, t0.ID FROM ArtistLazy t0";
- assertEquals(sql, string);
+ String pattern = "SELECT t0.SURNAME( c0)?, t0.ID( c1)? FROM ArtistLazy t0";
+ MatcherAssert.assertThat(sql, Matchers.matchesPattern(pattern));
ColumnSelect<String> select = ObjectSelect.columnQuery(ArtistLazy.class, ArtistLazy.NAME);
translator = new DefaultSelectTranslator(select, adapter, context.getEntityResolver());
@@ -118,8 +120,9 @@
String sql = translator.getSql();
assertFalse(sql.contains("t0.NAME"));
- String string = "SELECT t0.ARTIST_ID, t0.ID, t1.ID, t1.SURNAME FROM PaintingLazy t0 LEFT JOIN ArtistLazy t1 ON t0.ARTIST_ID = t1.ID";
- assertEquals(sql, string);
+ String pattern = "SELECT t0.ARTIST_ID( c0)?, t0.ID( c1)?, t1.ID( c2)?, t1.SURNAME( c3)?"
+ + " FROM PaintingLazy t0 LEFT JOIN ArtistLazy t1 ON t0.ARTIST_ID = t1.ID";
+ MatcherAssert.assertThat(sql, Matchers.matchesPattern(pattern));
}
@Test
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
index 4ec42b6..ee04557 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextFlattenedAttributesIT.java
@@ -509,7 +509,7 @@
ObjectContext context1 = runtime.newContext();
CompoundPainting o1 = context1.newObject(CompoundPainting.class);
o1.setArtistName("A1");
- o1.setEstimatedPrice(new BigDecimal(1d));
+ o1.setEstimatedPrice(BigDecimal.valueOf(1));
o1.setGalleryName("G1");
o1.setPaintingTitle("P1");
o1.setTextReview("T1");
@@ -524,7 +524,7 @@
CompoundPainting o2 = SelectById.query(CompoundPainting.class, id).selectFirst(context2);
o2.setArtistName("AX1");
- o2.setEstimatedPrice(new BigDecimal(2d));
+ o2.setEstimatedPrice(BigDecimal.valueOf(2));
o2.setGalleryName("XG1");
o2.setPaintingTitle("PX1");
o2.setTextReview("TX1");
@@ -538,7 +538,7 @@
CompoundPainting o3 = SelectById.query(CompoundPainting.class, id).selectFirst(context3);
assertEquals("AX1", o3.getArtistName());
- assertEquals("2.00", o3.getEstimatedPrice().toPlainString());
+ assertEquals(0, BigDecimal.valueOf(2).compareTo(o3.getEstimatedPrice()));
assertEquals("XG1", o3.getGalleryName());
assertEquals("PX1", o3.getPaintingTitle());
assertEquals("TX1", o3.getTextReview());
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
index 3d4398d..f15d316 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/NumericTypesIT.java
@@ -143,29 +143,29 @@
public void testBigDecimal_Decimal() {
// this matches the column scale exactly
- String v1 = "7890.123456";
+ BigDecimal v1 = new BigDecimal("7890.123456");
// this has lower scale than the column
- String v2 = "7890.1";
- String v2_padded = "7890.100000";
+ BigDecimal v2 = new BigDecimal("7890.1");
+ BigDecimal v2_padded = new BigDecimal("7890.100000");
BigDecimalEntity o = context.newObject(BigDecimalEntity.class);
- o.setBigDecimalDecimal(new BigDecimal(v1));
+ o.setBigDecimalDecimal(v1);
o.getObjectContext().commitChanges();
assertEquals(1, commitStats.getCommitCount());
BigDecimalEntity o1 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v1, o1.getBigDecimalDecimal().toString());
+ assertEquals(0, v1.compareTo(o1.getBigDecimalDecimal()));
- o.setBigDecimalDecimal(new BigDecimal(v2));
+ o.setBigDecimalDecimal(v2);
o.getObjectContext().commitChanges();
BigDecimalEntity o2 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v2_padded, o2.getBigDecimalDecimal().toString());
+ assertEquals(0, v2_padded.compareTo(o2.getBigDecimalDecimal()));
assertEquals(2, commitStats.getCommitCount());
- o2.setBigDecimalDecimal(new BigDecimal(v2));
+ o2.setBigDecimalDecimal(v2);
o2.getObjectContext().commitChanges();
assertEquals("Commit was not expected. The difference is purely in value padding", 2, commitStats.getCommitCount());
BigDecimalEntity o3 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v2_padded, o3.getBigDecimalDecimal().toString());
+ assertEquals(0, v2_padded.compareTo(o3.getBigDecimalDecimal()));
o3.setBigDecimalDecimal(null);
o3.getObjectContext().commitChanges();
@@ -177,27 +177,27 @@
@Test
public void testBigDecimal_Numeric() {
- String v1 = "1234567890.44";
- String v2 = "1234567890.4";
- String v2_padded = "1234567890.40";
+ BigDecimal v1 = new BigDecimal("1234567890.44");
+ BigDecimal v2 = new BigDecimal("1234567890.4");
+ BigDecimal v2_padded = new BigDecimal("1234567890.40");
BigDecimalEntity o = context.newObject(BigDecimalEntity.class);
- o.setBigDecimalNumeric(new BigDecimal(v1));
+ o.setBigDecimalNumeric(v1);
o.getObjectContext().commitChanges();
assertEquals(1, commitStats.getCommitCount());
BigDecimalEntity o1 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v1, o1.getBigDecimalNumeric().toString());
+ assertEquals(0, v1.compareTo(o1.getBigDecimalNumeric()));
- o1.setBigDecimalNumeric(new BigDecimal(v2));
+ o1.setBigDecimalNumeric(v2);
o1.getObjectContext().commitChanges();
assertEquals(2, commitStats.getCommitCount());
BigDecimalEntity o2 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v2_padded, o2.getBigDecimalNumeric().toString());
+ assertEquals(0, v2_padded.compareTo(o2.getBigDecimalNumeric()));
- o2.setBigDecimalNumeric(new BigDecimal(v2));
+ o2.setBigDecimalNumeric(v2);
assertEquals("Commit was not expected. The difference is purely in value padding", 2, commitStats.getCommitCount());
BigDecimalEntity o3 = ObjectSelect.query(BigDecimalEntity.class).selectFirst(runtime.newContext());
- assertEquals(v2_padded, o3.getBigDecimalNumeric().toString());
+ assertEquals(0, v2_padded.compareTo(o3.getBigDecimalNumeric()));
o3.setBigDecimalNumeric(null);
o3.getObjectContext().commitChanges();
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/flush/EffectiveOpIdTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/flush/EffectiveOpIdTest.java
index 4877e0c..d9a7dbc 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/flush/EffectiveOpIdTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/flush/EffectiveOpIdTest.java
@@ -40,6 +40,7 @@
EffectiveOpId effectiveOpId2 = new EffectiveOpId("test", Collections.singletonMap("pk", ObjectIdValueSupplier.getFor(id1, "pk")));
assertEquals(effectiveOpId1, effectiveOpId2);
+ assertNotEquals(id1.getReplacementIdMap().get("pk"), IdGenerationMarker.marker());
}
}
\ No newline at end of file
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/AggregateExpInMemoryEvaluationIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/AggregateExpInMemoryEvaluationIT.java
index 8a2c3b8..fae99a8 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/AggregateExpInMemoryEvaluationIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/AggregateExpInMemoryEvaluationIT.java
@@ -111,17 +111,17 @@
Expression maxExp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE).max().getExpression();
- Object max0 = maxExp.evaluate(artists.get(0));
+ BigDecimal max0 = (BigDecimal) maxExp.evaluate(artists.get(0));
BigDecimal expected0 = BigDecimal.valueOf(20000, 2);
- assertEquals(expected0, max0);
+ assertEquals(0, expected0.compareTo(max0));
- Object max1 = maxExp.evaluate(artists.get(1));
+ BigDecimal max1 = (BigDecimal) maxExp.evaluate(artists.get(1));
BigDecimal expected1 = BigDecimal.valueOf(100000, 2);
- assertEquals(expected1, max1);
+ assertEquals(0, expected1.compareTo(max1));
- Object max4 = maxExp.evaluate(artists.get(4));
+ BigDecimal max4 = (BigDecimal) maxExp.evaluate(artists.get(4));
BigDecimal expected4 = BigDecimal.valueOf(19000, 2);
- assertEquals(expected4, max4);
+ assertEquals(0, expected4.compareTo(max4));
}
@Test
@@ -133,17 +133,17 @@
Expression minExp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE).min().getExpression();
- Object min0 = minExp.evaluate(artists.get(0));
+ BigDecimal min0 = (BigDecimal) minExp.evaluate(artists.get(0));
BigDecimal expected0 = BigDecimal.valueOf(5000, 2);
- assertEquals(expected0, min0);
+ assertEquals(0, expected0.compareTo(min0));
- Object min3 = minExp.evaluate(artists.get(3));
+ BigDecimal min3 = (BigDecimal) minExp.evaluate(artists.get(3));
BigDecimal expected1 = BigDecimal.valueOf(3000, 2);
- assertEquals(expected1, min3);
+ assertEquals(0, expected1.compareTo(min3));
- Object min4 = minExp.evaluate(artists.get(4));
+ BigDecimal min4 = (BigDecimal) minExp.evaluate(artists.get(4));
BigDecimal expected4 = BigDecimal.valueOf(4000, 2);
- assertEquals(expected4, min4);
+ assertEquals(0, expected4.compareTo(min4));
}
@Test
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
index e738c75..e91ce8d 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTFunctionCallStringIT.java
@@ -27,6 +27,8 @@
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.query.ObjectSelect;
import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.unit.OracleUnitDbAdapter;
+import org.apache.cayenne.unit.UnitDbAdapter;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
@@ -34,6 +36,7 @@
import static junit.framework.TestCase.assertEquals;
import static junit.framework.TestCase.assertNull;
+import static org.junit.Assume.assumeFalse;
/**
* @since 4.0
@@ -42,6 +45,9 @@
public class ASTFunctionCallStringIT extends ServerCase {
@Inject
+ private UnitDbAdapter unitDbAdapter;
+
+ @Inject
private ObjectContext context;
private Artist createArtist(String name) throws Exception {
@@ -62,6 +68,10 @@
@Test
public void testASTUpperInWhere() throws Exception {
+ // TODO: This will fail for Oracle, so skip for now.
+ // It is necessary to provide connection with "fixedString=true" property somehow.
+ // Also see CAY-1470.
+ assumeFalse(unitDbAdapter instanceof OracleUnitDbAdapter);
Artist a1 = createArtist("name");
Artist a2 = ObjectSelect.query(Artist.class)
.where(Artist.ARTIST_NAME.upper().eq("NAME")).selectOne(context);
@@ -70,6 +80,10 @@
@Test
public void testASTLowerInWhere() throws Exception {
+ // TODO: This will fail for Oracle, so skip for now.
+ // It is necessary to provide connection with "fixedString=true" property somehow.
+ // Also see CAY-1470.
+ assumeFalse(unitDbAdapter instanceof OracleUnitDbAdapter);
Artist a1 = createArtist("NAME");
Artist a2 = ObjectSelect.query(Artist.class)
.where(Artist.ARTIST_NAME.lower().eq("name")).selectOne(context);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
index fe6e25a..b4b5554 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_RunIT.java
@@ -25,11 +25,14 @@
import org.apache.cayenne.ResultBatchIterator;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.dba.oracle.OracleAdapter;
import org.apache.cayenne.di.Inject;
import org.apache.cayenne.test.jdbc.DBHelper;
import org.apache.cayenne.test.jdbc.TableHelper;
import org.apache.cayenne.testdo.testmap.Artist;
import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.OracleUnitDbAdapter;
+import org.apache.cayenne.unit.UnitDbAdapter;
import org.apache.cayenne.unit.di.server.CayenneProjects;
import org.apache.cayenne.unit.di.server.ServerCase;
import org.apache.cayenne.unit.di.server.UseServerRuntime;
@@ -38,6 +41,7 @@
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assume.assumeFalse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
@@ -46,6 +50,9 @@
public class ObjectSelect_RunIT extends ServerCase {
@Inject
+ private UnitDbAdapter unitDbAdapter;
+
+ @Inject
private DataContext context;
@Inject
@@ -199,6 +206,10 @@
@Test
public void test_Select_CustomFunction() {
+ // TODO: This will fail for Oracle, so skip for now.
+ // It is necessary to provide connection with "fixedString=true" property somehow.
+ // Also see CAY-1470.
+ assumeFalse(unitDbAdapter instanceof OracleUnitDbAdapter);
Artist a = ObjectSelect.query(Artist.class)
.where(Artist.ARTIST_NAME.function("UPPER", String.class).eq("ARTIST1"))
.selectOne(context);
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
index f1b44a0..2617c0c 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/SQLTemplateIT.java
@@ -31,6 +31,7 @@
import org.apache.cayenne.testdo.testmap.Artist;
import org.apache.cayenne.testdo.testmap.Gallery;
import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.OracleUnitDbAdapter;
import org.apache.cayenne.unit.UnitDbAdapter;
import org.apache.cayenne.unit.di.DataChannelInterceptor;
import org.apache.cayenne.unit.di.server.CayenneProjects;
@@ -39,6 +40,7 @@
import org.junit.Before;
import org.junit.Test;
+import java.math.BigDecimal;
import java.sql.Date;
import java.sql.SQLException;
import java.time.LocalDateTime;
@@ -311,7 +313,10 @@
assertEquals(2, artists.size());
assertEquals(1, artists.get(0).length);
assertTrue(artists.get(0) instanceof Object[]);
- assertTrue(artists.get(0)[0] instanceof Long);
+
+ // TODO: JDBC's BIGINT matches Oracle's NUMERIC, which matches BigDecimal.
+ Class<?> idType = unitDbAdapter instanceof OracleUnitDbAdapter ? BigDecimal.class : Long.class;
+ assertThat(artists.get(0)[0], instanceOf(idType));
}
@Test
@@ -325,7 +330,10 @@
assertEquals(2, artists.size());
assertEquals(2, artists.get(0).length);
assertTrue(artists.get(0) instanceof Object[]);
- assertTrue(artists.get(0)[0] instanceof Long);
+
+ // JDBC's BIGINT matches Oracle's NUMERIC, which matches BigDecimal.
+ Class<?> idType = unitDbAdapter instanceof OracleUnitDbAdapter ? BigDecimal.class : Long.class;
+ assertThat(artists.get(0)[0], instanceOf(idType));
}
@Test
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonOther.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonOther.java
new file mode 100644
index 0000000..7a5fd7d
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonOther.java
@@ -0,0 +1,28 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.testdo.json;
+
+import org.apache.cayenne.testdo.json.auto._JsonOther;
+
+public class JsonOther extends _JsonOther {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonVarchar.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonVarchar.java
new file mode 100644
index 0000000..8c8ac93
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/JsonVarchar.java
@@ -0,0 +1,28 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.testdo.json;
+
+import org.apache.cayenne.testdo.json.auto._JsonVarchar;
+
+public class JsonVarchar extends _JsonVarchar {
+
+ private static final long serialVersionUID = 1L;
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonOther.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonOther.java
new file mode 100644
index 0000000..651123f
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonOther.java
@@ -0,0 +1,113 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.testdo.json.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.BaseProperty;
+import org.apache.cayenne.exp.property.NumericIdProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
+import org.apache.cayenne.testdo.json.JsonOther;
+import org.apache.cayenne.value.Json;
+
+/**
+ * Class _JsonOther was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _JsonOther extends BaseDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final SelfProperty<JsonOther> SELF = PropertyFactory.createSelf(JsonOther.class);
+
+ public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "JsonOther", Integer.class);
+ public static final String ID_PK_COLUMN = "ID";
+
+ public static final BaseProperty<Json> DATA = PropertyFactory.createBase("data", Json.class);
+
+ protected Json data;
+
+
+ public void setData(Json data) {
+ beforePropertyWrite("data", this.data, data);
+ this.data = data;
+ }
+
+ public Json getData() {
+ beforePropertyRead("data");
+ return this.data;
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "data":
+ return this.data;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "data":
+ this.data = (Json)val;
+ break;
+ default:
+ super.writePropertyDirectly(propName, val);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeSerialized(out);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ readSerialized(in);
+ }
+
+ @Override
+ protected void writeState(ObjectOutputStream out) throws IOException {
+ super.writeState(out);
+ out.writeObject(this.data);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.data = (Json)in.readObject();
+ }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonVarchar.java b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonVarchar.java
new file mode 100644
index 0000000..8a3ade2
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/testdo/json/auto/_JsonVarchar.java
@@ -0,0 +1,113 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.testdo.json.auto;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.cayenne.BaseDataObject;
+import org.apache.cayenne.exp.property.BaseProperty;
+import org.apache.cayenne.exp.property.NumericIdProperty;
+import org.apache.cayenne.exp.property.PropertyFactory;
+import org.apache.cayenne.exp.property.SelfProperty;
+import org.apache.cayenne.testdo.json.JsonVarchar;
+import org.apache.cayenne.value.Json;
+
+/**
+ * Class _JsonVarchar was generated by Cayenne.
+ * It is probably a good idea to avoid changing this class manually,
+ * since it may be overwritten next time code is regenerated.
+ * If you need to make any customizations, please use subclass.
+ */
+public abstract class _JsonVarchar extends BaseDataObject {
+
+ private static final long serialVersionUID = 1L;
+
+ public static final SelfProperty<JsonVarchar> SELF = PropertyFactory.createSelf(JsonVarchar.class);
+
+ public static final NumericIdProperty<Integer> ID_PK_PROPERTY = PropertyFactory.createNumericId("ID", "JsonVarchar", Integer.class);
+ public static final String ID_PK_COLUMN = "ID";
+
+ public static final BaseProperty<Json> DATA = PropertyFactory.createBase("data", Json.class);
+
+ protected Json data;
+
+
+ public void setData(Json data) {
+ beforePropertyWrite("data", this.data, data);
+ this.data = data;
+ }
+
+ public Json getData() {
+ beforePropertyRead("data");
+ return this.data;
+ }
+
+ @Override
+ public Object readPropertyDirectly(String propName) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch(propName) {
+ case "data":
+ return this.data;
+ default:
+ return super.readPropertyDirectly(propName);
+ }
+ }
+
+ @Override
+ public void writePropertyDirectly(String propName, Object val) {
+ if(propName == null) {
+ throw new IllegalArgumentException();
+ }
+
+ switch (propName) {
+ case "data":
+ this.data = (Json)val;
+ break;
+ default:
+ super.writePropertyDirectly(propName, val);
+ }
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeSerialized(out);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ readSerialized(in);
+ }
+
+ @Override
+ protected void writeState(ObjectOutputStream out) throws IOException {
+ super.writeState(out);
+ out.writeObject(this.data);
+ }
+
+ @Override
+ protected void readState(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ super.readState(in);
+ this.data = (Json)in.readObject();
+ }
+
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/PostgresUnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/PostgresUnitDbAdapter.java
index b5222ad..aed1805 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/PostgresUnitDbAdapter.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/PostgresUnitDbAdapter.java
@@ -67,6 +67,11 @@
}
@Override
+ public boolean supportsJsonType() {
+ return true;
+ }
+
+ @Override
public boolean supportsGeneratedKeysDrop() {
return true;
}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java
index 87fa7bd..7122d4b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/UnitDbAdapter.java
@@ -222,6 +222,13 @@
return supportsLobs();
}
+ /**
+ * Returns true if the target database has native json data type.
+ */
+ public boolean supportsJsonType() {
+ return false;
+ }
+
public boolean supportsBinaryPK() {
return true;
}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
index ccb392e..f99577f 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/CayenneProjects.java
@@ -41,6 +41,7 @@
public static final String INHERITANCE_PROJECT = "cayenne-inheritance.xml";
public static final String INHERITANCE_SINGLE_TABLE1_PROJECT = "cayenne-inheritance-single-table1.xml";
public static final String INHERITANCE_VERTICAL_PROJECT = "cayenne-inheritance-vertical.xml";
+ public static final String JSON_PROJECT = "cayenne-json.xml";
public static final String LIFECYCLE_CALLBACKS_ORDER_PROJECT = "cayenne-lifecycle-callbacks-order.xml";
public static final String LIFECYCLES_PROJECT = "cayenne-lifecycles.xml";
public static final String LOB_PROJECT = "cayenne-lob.xml";
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
index bc154c6..d89054b 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/SchemaBuilder.java
@@ -51,11 +51,12 @@
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
/**
@@ -69,25 +70,28 @@
private static final String[] MAPS_REQUIRING_SCHEMA_SETUP = { "testmap.map.xml", "compound.map.xml",
"misc-types.map.xml", "things.map.xml", "numeric-types.map.xml", "binary-pk.map.xml", "no-pk.map.xml",
- "lob.map.xml", "date-time.map.xml", "enum.map.xml", "extended-type.map.xml", "generated.map.xml",
- "mixed-persistence-strategy.map.xml", "people.map.xml", "primitive.map.xml", "inheritance.map.xml",
- "locking.map.xml", "soft-delete.map.xml", "empty.map.xml", "relationships.map.xml",
+ "lob.map.xml", "date-time.map.xml", "enum.map.xml", "json.map.xml", "extended-type.map.xml",
+ "generated.map.xml", "mixed-persistence-strategy.map.xml", "people.map.xml", "primitive.map.xml",
+ "inheritance.map.xml", "locking.map.xml", "soft-delete.map.xml", "empty.map.xml", "relationships.map.xml",
"relationships-activity.map.xml", "relationships-delete-rules.map.xml",
"relationships-collection-to-many.map.xml", "relationships-child-master.map.xml",
- "relationships-clob.map.xml", "relationships-flattened.map.xml", "relationships-many-to-many-join.map.xml", "relationships-set-to-many.map.xml",
- "relationships-to-many-fk.map.xml", "relationships-to-one-fk.map.xml", "return-types.map.xml",
- "uuid.map.xml", "multi-tier.map.xml", "reflexive.map.xml", "delete-rules.map.xml",
- "lifecycle-callbacks-order.map.xml", "lifecycles.map.xml", "map-to-many.map.xml", "toone.map.xml", "meaningful-pk.map.xml",
- "table-primitives.map.xml", "generic.map.xml", "map-db1.map.xml", "map-db2.map.xml", "embeddable.map.xml",
- "qualified.map.xml", "quoted-identifiers.map.xml", "inheritance-single-table1.map.xml",
- "inheritance-vertical.map.xml", "oneway-rels.map.xml", "unsupported-distinct-types.map.xml",
- "array-type.map.xml", "cay-2032.map.xml", "weighted-sort.map.xml", "hybrid-data-object.map.xml",
- "java8.map.xml", "inheritance-with-enum.map.xml", "lazy-attributes.map.xml", "cay2666/datamap.map.xml", "cay2641/datamapLazy.map.xml",
- "annotation/datamapAnnotation.map.xml" };
+ "relationships-clob.map.xml", "relationships-flattened.map.xml", "relationships-many-to-many-join.map.xml",
+ "relationships-set-to-many.map.xml", "relationships-to-many-fk.map.xml", "relationships-to-one-fk.map.xml",
+ "return-types.map.xml", "uuid.map.xml", "multi-tier.map.xml", "reflexive.map.xml", "delete-rules.map.xml",
+ "lifecycle-callbacks-order.map.xml", "lifecycles.map.xml", "map-to-many.map.xml", "toone.map.xml",
+ "meaningful-pk.map.xml", "table-primitives.map.xml", "generic.map.xml", "map-db1.map.xml",
+ "map-db2.map.xml", "embeddable.map.xml", "qualified.map.xml", "quoted-identifiers.map.xml",
+ "inheritance-single-table1.map.xml", "inheritance-vertical.map.xml", "oneway-rels.map.xml",
+ "unsupported-distinct-types.map.xml", "array-type.map.xml", "cay-2032.map.xml",
+ "weighted-sort.map.xml", "hybrid-data-object.map.xml", "java8.map.xml", "inheritance-with-enum.map.xml",
+ "lazy-attributes.map.xml", "cay2666/datamap.map.xml", "cay2641/datamapLazy.map.xml",
+ "annotation/datamapAnnotation.map.xml" };
// hardcoded dependent entities that should be excluded
// if LOBs are not supported
- private static final String[] EXTRA_EXCLUDED_FOR_NO_LOB = new String[] { "CLOB_DETAIL" };
+ private static final Set<String> EXTRA_EXCLUDED_FOR_NO_LOB = Set.of("CLOB_DETAIL");
+
+ private static final Set<String> EXTRA_EXCLUDED_FOR_NO_NATIVE_JSON = Set.of("JSON_OTHER");
private ServerCaseDataSourceFactory dataSourceFactory;
private UnitDbAdapter unitDbAdapter;
@@ -242,8 +246,8 @@
private List<DbEntity> dbEntitiesInInsertOrder(DataMap map) {
TreeMap<String, DbEntity> dbEntityMap = new TreeMap<>(map.getDbEntityMap());
List<DbEntity> entities = new ArrayList<>(dbEntityMap.values());
-
- dbEntitiesFilter(entities);
+ List<DbEntity> excludedEntities = excludeEntities(entities);
+ entities.removeAll(excludedEntities);
domain.getEntitySorter().sortDbEntities(entities, false);
return entities;
@@ -253,70 +257,63 @@
DataMap map = domain.getDataMap(dataMap.getName());
Map<String, DbEntity> dbEntityMap = new TreeMap<>(map.getDbEntityMap());
List<DbEntity> entities = new ArrayList<>(dbEntityMap.values());
-
- dbEntitiesFilter(entities);
+ List<DbEntity> excludedEntities = excludeEntities(entities);
+ entities.removeAll(excludedEntities);
domain.getEntitySorter().sortDbEntities(entities, true);
return entities;
}
- // This seems actually unused for some time now (from 2014 to 2018), and caused no trouble
- private void dbEntitiesFilter(List<DbEntity> entities) {
- // filter various unsupported tests...
+ private List<DbEntity> excludeEntities(Collection<DbEntity> entities) {
+ // exclude various unsupported tests...
- // LOBs
boolean excludeLOB = !unitDbAdapter.supportsLobs();
- boolean excludeBinPK = !unitDbAdapter.supportsBinaryPK();
- if (excludeLOB || excludeBinPK) {
+ boolean excludeNativeJson = !unitDbAdapter.supportsJsonType();
+ boolean excludeBinaryPK = !unitDbAdapter.supportsBinaryPK();
+ if (!excludeLOB && !excludeNativeJson && !excludeBinaryPK) {
+ return Collections.emptyList();
+ }
- List<DbEntity> filtered = new ArrayList<>();
+ List<DbEntity> excludedEntities = new ArrayList<>();
+ for (DbEntity entity : entities) {
- for (DbEntity ent : entities) {
-
- // check for LOB attributes
- if (excludeLOB) {
- if (Arrays.binarySearch(EXTRA_EXCLUDED_FOR_NO_LOB, ent.getName()) >= 0) {
- continue;
- }
-
- boolean hasLob = false;
- for (final DbAttribute attr : ent.getAttributes()) {
- if (attr.getType() == Types.BLOB || attr.getType() == Types.CLOB) {
- hasLob = true;
- break;
- }
- }
-
- if (hasLob) {
- continue;
- }
+ // check for LOB attributes
+ if (excludeLOB) {
+ if (EXTRA_EXCLUDED_FOR_NO_LOB.contains(entity.getName())) {
+ excludedEntities.add(entity);
+ continue;
}
-
- // check for BIN PK
- if (excludeBinPK) {
- boolean skip = false;
- for (final DbAttribute attr : ent.getAttributes()) {
- // check for BIN PK or FK to BIN Pk
- if (attr.getType() == Types.BINARY || attr.getType() == Types.VARBINARY
- || attr.getType() == Types.LONGVARBINARY) {
-
- if (attr.isPrimaryKey() || attr.isForeignKey()) {
- skip = true;
- break;
- }
- }
- }
-
- if (skip) {
- continue;
- }
+ Set<Integer> lobTypes = Set.of(Types.BLOB, Types.CLOB, Types.NCLOB);
+ boolean hasLob = entity.getAttributes().stream()
+ .map(DbAttribute::getType)
+ .anyMatch(lobTypes::contains);
+ if (hasLob) {
+ excludedEntities.add(entity);
+ continue;
}
-
- filtered.add(ent);
}
- entities = filtered;
+ // check for native json type
+ if (excludeNativeJson) {
+ if (EXTRA_EXCLUDED_FOR_NO_NATIVE_JSON.contains(entity.getName())) {
+ excludedEntities.add(entity);
+ continue;
+ }
+ }
+
+ // check for BIN PK
+ if (excludeBinaryPK) {
+ Set<Integer> binaryTypes = Set.of(Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY);
+ boolean hasBinaryPK = entity.getAttributes().stream()
+ .filter(attribute -> attribute.isPrimaryKey() || attribute.isForeignKey())
+ .map(DbAttribute::getType)
+ .anyMatch(binaryTypes::contains);
+ if (hasBinaryPK) {
+ excludedEntities.add(entity);
+ }
+ }
}
+ return excludedEntities;
}
private void dropSchema(DataNode node, DataMap map) throws Exception {
@@ -396,18 +393,19 @@
*/
private Collection<String> tableCreateQueries(DataNode node, DataMap map) {
DbAdapter adapter = node.getAdapter();
- DbGenerator gen = new DbGenerator(adapter, map, null, domain, jdbcEventLogger);
- List<DbEntity> orderedEnts = dbEntitiesInInsertOrder(map);
+ List<DbEntity> orderedEntities = dbEntitiesInInsertOrder(map);
+ List<DbEntity> excludedEntities = excludeEntities(map.getDbEntities());
+ DbGenerator gen = new DbGenerator(adapter, map, excludedEntities, domain, jdbcEventLogger);
List<String> queries = new ArrayList<>();
// table definitions
- for (DbEntity ent : orderedEnts) {
+ for (DbEntity ent : orderedEntities) {
queries.add(adapter.createTable(ent));
}
// FK constraints
- for (DbEntity ent : orderedEnts) {
+ for (DbEntity ent : orderedEntities) {
if (!unitDbAdapter.supportsFKConstraints(ent)) {
continue;
}
@@ -418,5 +416,4 @@
return queries;
}
-
}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/testcontainers/OracleContainerProvider.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/testcontainers/OracleContainerProvider.java
index 6bdd2c4..4934c02 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/unit/testcontainers/OracleContainerProvider.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/testcontainers/OracleContainerProvider.java
@@ -31,25 +31,18 @@
@Override
public JdbcDatabaseContainer<?> startContainer(String version) {
JdbcDatabaseContainer<?> container = super.startContainer(version);
- // need to wait to ensure Oracle DB has started
- try {
- Thread.sleep(40000);
- } catch (InterruptedException ignored) {
- }
return container;
}
@Override
JdbcDatabaseContainer<?> createContainer(DockerImageName dockerImageName) {
return new OracleContainer(dockerImageName)
- .withStartupTimeout(Duration.ofMinutes(5))
- .withEnv("ORACLE_ALLOW_REMOTE", "true")
- .withEnv("ORACLE_DISABLE_ASYNCH_IO", "true");
+ .withStartupTimeout(Duration.ofMinutes(5));
}
@Override
String getDockerImage() {
- return "oracleinanutshell/oracle-xe-11g";
+ return "gvenzl/oracle-xe:18-slim-faststart";
}
@Override
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonTypeIT.java b/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonTypeIT.java
new file mode 100644
index 0000000..a733df4
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonTypeIT.java
@@ -0,0 +1,682 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.value.json;
+
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.query.SelectById;
+import org.apache.cayenne.testdo.json.JsonOther;
+import org.apache.cayenne.testdo.json.JsonVarchar;
+import org.apache.cayenne.unit.UnitDbAdapter;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.apache.cayenne.value.Json;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertEquals;
+
+@UseServerRuntime(CayenneProjects.JSON_PROJECT)
+public class JsonTypeIT extends ServerCase {
+
+ @Inject
+ private DataContext context;
+
+ @Inject
+ private UnitDbAdapter unitDbAdapter;
+
+ @Test
+ public void testJsonBasic() {
+ testJson("{\"id\": 1, \"property\": \"value\"}");
+ }
+
+ @Test
+ public void testJsonOver4k() {
+ testJson("[\n" +
+ " {\n" +
+ " \"_id\": \"63f151cd2df4280fe4258ef3\",\n" +
+ " \"index\": 0,\n" +
+ " \"guid\": \"2e05e933-7468-4573-aa76-e29a80810c57\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$3,282.00\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 20,\n" +
+ " \"eyeColor\": \"blue\",\n" +
+ " \"name\": \"Mathews Rutledge\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"FREAKIN\",\n" +
+ " \"email\": \"mathewsrutledge@freakin.com\",\n" +
+ " \"phone\": \"+1 (873) 411-3555\",\n" +
+ " \"address\": \"896 Lee Avenue, Fairhaven, New Jersey, 1031\",\n" +
+ " \"about\": \"nostrud cupidatat proident eu anim sint eu\",\n" +
+ " \"registered\": \"2021-10-10T11:59:50 -03:00\",\n" +
+ " \"latitude\": -18.854904,\n" +
+ " \"longitude\": -138.392089,\n" +
+ " \"tags\": [\n" +
+ " \"ad\",\n" +
+ " \"irure\",\n" +
+ " \"anim\",\n" +
+ " \"aliqua\",\n" +
+ " \"do\",\n" +
+ " \"eu\",\n" +
+ " \"excepteur\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Guzman Kemp\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Delgado Beasley\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Noelle Owen\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Mathews Rutledge! You have 4 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f151cd00a687261825c3d3\",\n" +
+ " \"index\": 1,\n" +
+ " \"guid\": \"7c6b8859-5a81-4654-980f-e31ae7c3a04d\",\n" +
+ " \"isActive\": false,\n" +
+ " \"balance\": \"$2,805.03\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 32,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Nieves Gallegos\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"SPACEWAX\",\n" +
+ " \"email\": \"nievesgallegos@spacewax.com\",\n" +
+ " \"phone\": \"+1 (839) 414-3310\",\n" +
+ " \"address\": \"446 Mill Avenue, Nicholson, Minnesota, 8852\",\n" +
+ " \"about\": \"sunt magna quis officia exercitation laboris officia\",\n" +
+ " \"registered\": \"2020-01-17T08:49:38 -03:00\",\n" +
+ " \"latitude\": 11.681513,\n" +
+ " \"longitude\": -129.960233,\n" +
+ " \"tags\": [\n" +
+ " \"labore\",\n" +
+ " \"fugiat\",\n" +
+ " \"cillum\",\n" +
+ " \"incididunt\",\n" +
+ " \"nostrud\",\n" +
+ " \"non\",\n" +
+ " \"et\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Perry Hunter\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Angelina Cooper\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Kendra Bonner\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Nieves Gallegos! You have 2 unread messages.\",\n" +
+ " \"favoriteFruit\": \"strawberry\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f151cd9d0e1b90e4150a10\",\n" +
+ " \"index\": 2,\n" +
+ " \"guid\": \"dfea2156-c940-43d3-a500-19b5b32719b3\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$2,684.11\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 38,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Virginia Watts\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"OPTIQUE\",\n" +
+ " \"email\": \"virginiawatts@optique.com\",\n" +
+ " \"phone\": \"+1 (864) 547-3451\",\n" +
+ " \"address\": \"518 Crooke Avenue, Advance, Arkansas, 7719\",\n" +
+ " \"about\": \"ullamco exercitation excepteur mollit ad labore do\",\n" +
+ " \"registered\": \"2018-11-30T07:01:17 -03:00\",\n" +
+ " \"latitude\": -77.530698,\n" +
+ " \"longitude\": 174.424542,\n" +
+ " \"tags\": [\n" +
+ " \"ex\",\n" +
+ " \"ad\",\n" +
+ " \"exercitation\",\n" +
+ " \"dolor\",\n" +
+ " \"aute\",\n" +
+ " \"ex\",\n" +
+ " \"Lorem\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Molly Blake\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Pearlie Dodson\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Montoya Watkins\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Virginia Watts! You have 4 unread messages.\",\n" +
+ " \"favoriteFruit\": \"apple\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f151cde376bf473f79cc97\",\n" +
+ " \"index\": 3,\n" +
+ " \"guid\": \"4f77bba3-531c-4450-b441-589bd19f2a57\",\n" +
+ " \"isActive\": false,\n" +
+ " \"balance\": \"$3,381.01\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 22,\n" +
+ " \"eyeColor\": \"green\",\n" +
+ " \"name\": \"Walter Patrick\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"PEARLESEX\",\n" +
+ " \"email\": \"walterpatrick@pearlesex.com\",\n" +
+ " \"phone\": \"+1 (954) 448-3420\",\n" +
+ " \"address\": \"387 Church Avenue, Geyserville, New Hampshire, 4849\",\n" +
+ " \"about\": \"cupidatat officia qui dolor veniam eu minim\",\n" +
+ " \"registered\": \"2016-12-04T05:12:01 -03:00\",\n" +
+ " \"latitude\": 83.816972,\n" +
+ " \"longitude\": -30.59895,\n" +
+ " \"tags\": [\n" +
+ " \"eu\",\n" +
+ " \"Lorem\",\n" +
+ " \"ad\",\n" +
+ " \"ea\",\n" +
+ " \"adipisicing\",\n" +
+ " \"velit\",\n" +
+ " \"ex\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Pate Sweet\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Stein Burns\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Candy Swanson\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Walter Patrick! You have 5 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f151cd64d59419599bd15f\",\n" +
+ " \"index\": 4,\n" +
+ " \"guid\": \"2da48623-9b34-47ec-962e-400d45c8620a\",\n" +
+ " \"isActive\": false,\n" +
+ " \"balance\": \"$2,891.52\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 37,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Ella Carey\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"PORTICO\",\n" +
+ " \"email\": \"ellacarey@portico.com\",\n" +
+ " \"phone\": \"+1 (906) 400-3097\",\n" +
+ " \"address\": \"381 Bowne Street, Rose, Palau, 7582\",\n" +
+ " \"about\": \"voluptate pariatur magna occaecat elit magna excepteur\",\n" +
+ " \"registered\": \"2015-08-07T10:22:10 -03:00\",\n" +
+ " \"latitude\": 80.548898,\n" +
+ " \"longitude\": 67.575077,\n" +
+ " \"tags\": [\n" +
+ " \"duis\",\n" +
+ " \"occaecat\",\n" +
+ " \"excepteur\",\n" +
+ " \"tempor\",\n" +
+ " \"excepteur\",\n" +
+ " \"Lorem\",\n" +
+ " \"proident\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Melendez Martin\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Haley Colon\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Emilia Schmidt\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Ella Carey! You have 8 unread messages.\",\n" +
+ " \"favoriteFruit\": \"strawberry\"\n" +
+ " }\n" +
+ "]");
+ }
+
+ @Test
+ public void testJsonOver16k() {
+ testJson("[\n" +
+ " {\n" +
+ " \"_id\": \"63f153352d42c0451f6f18a1\",\n" +
+ " \"index\": 0,\n" +
+ " \"guid\": \"4db9bc53-e652-47bd-8162-aad6b4280eb9\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$3,604.21\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 26,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Landry Malone\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"FROLIX\",\n" +
+ " \"email\": \"landrymalone@frolix.com\",\n" +
+ " \"phone\": \"+1 (898) 454-3351\",\n" +
+ " \"address\": \"881 Strauss Street, Troy, Utah, 4374\",\n" +
+ " \"about\": \"ea et consequat fugiat est laboris sint\",\n" +
+ " \"registered\": \"2016-06-14T05:08:16 -03:00\",\n" +
+ " \"latitude\": 49.131275,\n" +
+ " \"longitude\": -171.114829,\n" +
+ " \"tags\": [\n" +
+ " \"dolore\",\n" +
+ " \"elit\",\n" +
+ " \"excepteur\",\n" +
+ " \"in\",\n" +
+ " \"sint\",\n" +
+ " \"exercitation\",\n" +
+ " \"cillum\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Palmer Pittman\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Clarice Wolfe\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Clements Battle\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Landry Malone! You have 9 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f153355ae6023dbfb7c2f8\",\n" +
+ " \"index\": 1,\n" +
+ " \"guid\": \"b4fdfc88-e367-42ba-ae1d-2f9f6a538986\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$1,909.36\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 24,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Nicholson Dodson\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"BUNGA\",\n" +
+ " \"email\": \"nicholsondodson@bunga.com\",\n" +
+ " \"phone\": \"+1 (857) 550-2984\",\n" +
+ " \"address\": \"425 Thornton Street, Roosevelt, South Carolina, 4979\",\n" +
+ " \"about\": \"voluptate consequat consequat pariatur reprehenderit et exercitation\",\n" +
+ " \"registered\": \"2021-08-16T06:28:03 -03:00\",\n" +
+ " \"latitude\": -12.667348,\n" +
+ " \"longitude\": 84.401994,\n" +
+ " \"tags\": [\n" +
+ " \"est\",\n" +
+ " \"in\",\n" +
+ " \"mollit\",\n" +
+ " \"id\",\n" +
+ " \"proident\",\n" +
+ " \"incididunt\",\n" +
+ " \"qui\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Nelson Wolf\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Corina Fry\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Carlene Bean\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Nicholson Dodson! You have 8 unread messages.\",\n" +
+ " \"favoriteFruit\": \"strawberry\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f15335f03974b701b22feb\",\n" +
+ " \"index\": 2,\n" +
+ " \"guid\": \"bf249929-ce37-4702-9671-1935278a2ff8\",\n" +
+ " \"isActive\": false,\n" +
+ " \"balance\": \"$2,455.81\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 38,\n" +
+ " \"eyeColor\": \"blue\",\n" +
+ " \"name\": \"Strickland Hodges\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"MACRONAUT\",\n" +
+ " \"email\": \"stricklandhodges@macronaut.com\",\n" +
+ " \"phone\": \"+1 (806) 573-3642\",\n" +
+ " \"address\": \"929 Sutton Street, Caroleen, Delaware, 2273\",\n" +
+ " \"about\": \"culpa eiusmod commodo et officia aute exercitation\",\n" +
+ " \"registered\": \"2017-10-26T06:25:14 -03:00\",\n" +
+ " \"latitude\": 24.973892,\n" +
+ " \"longitude\": 50.218781,\n" +
+ " \"tags\": [\n" +
+ " \"sit\",\n" +
+ " \"exercitation\",\n" +
+ " \"Lorem\",\n" +
+ " \"qui\",\n" +
+ " \"reprehenderit\",\n" +
+ " \"incididunt\",\n" +
+ " \"cupidatat\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Trevino Howard\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Carol Frye\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Kara Parks\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Strickland Hodges! You have 7 unread messages.\",\n" +
+ " \"favoriteFruit\": \"apple\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f15335c8e74b04cc2cf3de\",\n" +
+ " \"index\": 3,\n" +
+ " \"guid\": \"450adca9-503b-41a2-b0a5-3ae7c9d68f81\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$3,895.80\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 30,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Judy Scott\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"ZENSOR\",\n" +
+ " \"email\": \"judyscott@zensor.com\",\n" +
+ " \"phone\": \"+1 (961) 568-2876\",\n" +
+ " \"address\": \"359 Williamsburg Street, Venice, Ohio, 6487\",\n" +
+ " \"about\": \"in nulla adipisicing non culpa quis do\",\n" +
+ " \"registered\": \"2014-01-08T07:06:47 -04:00\",\n" +
+ " \"latitude\": -66.571697,\n" +
+ " \"longitude\": 92.502775,\n" +
+ " \"tags\": [\n" +
+ " \"labore\",\n" +
+ " \"minim\",\n" +
+ " \"adipisicing\",\n" +
+ " \"nostrud\",\n" +
+ " \"elit\",\n" +
+ " \"deserunt\",\n" +
+ " \"cupidatat\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Lorna Hines\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Farrell Ryan\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Georgette Elliott\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Judy Scott! You have 8 unread messages.\",\n" +
+ " \"favoriteFruit\": \"strawberry\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f1533590ac45e8b03b433e\",\n" +
+ " \"index\": 4,\n" +
+ " \"guid\": \"88b4e813-d6dc-4902-b4f4-c28fca5d8b32\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$2,997.00\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 38,\n" +
+ " \"eyeColor\": \"blue\",\n" +
+ " \"name\": \"Briggs Shields\",\n" +
+ " \"gender\": \"male\",\n" +
+ " \"company\": \"XLEEN\",\n" +
+ " \"email\": \"briggsshields@xleen.com\",\n" +
+ " \"phone\": \"+1 (987) 435-3420\",\n" +
+ " \"address\": \"807 Vine Street, Callaghan, New Mexico, 7939\",\n" +
+ " \"about\": \"consectetur cupidatat anim pariatur adipisicing adipisicing irure\",\n" +
+ " \"registered\": \"2022-02-28T09:49:04 -03:00\",\n" +
+ " \"latitude\": 5.401627,\n" +
+ " \"longitude\": 64.076763,\n" +
+ " \"tags\": [\n" +
+ " \"irure\",\n" +
+ " \"sint\",\n" +
+ " \"aliqua\",\n" +
+ " \"officia\",\n" +
+ " \"consectetur\",\n" +
+ " \"qui\",\n" +
+ " \"eiusmod\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Roberts Weeks\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Justice Bullock\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Simone Jacobson\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Briggs Shields! You have 8 unread messages.\",\n" +
+ " \"favoriteFruit\": \"strawberry\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f153359ee33fe36670766f\",\n" +
+ " \"index\": 5,\n" +
+ " \"guid\": \"f87bfc03-46d5-4e8f-9f55-dafa25e124cb\",\n" +
+ " \"isActive\": false,\n" +
+ " \"balance\": \"$2,933.39\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 27,\n" +
+ " \"eyeColor\": \"green\",\n" +
+ " \"name\": \"Kendra Peterson\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"FUELWORKS\",\n" +
+ " \"email\": \"kendrapeterson@fuelworks.com\",\n" +
+ " \"phone\": \"+1 (951) 518-3222\",\n" +
+ " \"address\": \"155 Dewey Place, Westwood, Georgia, 1647\",\n" +
+ " \"about\": \"occaecat in ipsum non cillum proident officia\",\n" +
+ " \"registered\": \"2017-04-26T06:50:40 -03:00\",\n" +
+ " \"latitude\": -14.371127,\n" +
+ " \"longitude\": -0.400474,\n" +
+ " \"tags\": [\n" +
+ " \"ad\",\n" +
+ " \"ipsum\",\n" +
+ " \"eiusmod\",\n" +
+ " \"cillum\",\n" +
+ " \"et\",\n" +
+ " \"et\",\n" +
+ " \"ipsum\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Orr Stone\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Mavis Mccullough\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Lea Whitfield\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Kendra Peterson! You have 6 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f15335cb2b3032b85383bb\",\n" +
+ " \"index\": 6,\n" +
+ " \"guid\": \"f1df8765-ebcb-40b9-957e-a04d0b16f2c6\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$2,219.05\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 38,\n" +
+ " \"eyeColor\": \"brown\",\n" +
+ " \"name\": \"Carissa Hogan\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"SOPRANO\",\n" +
+ " \"email\": \"carissahogan@soprano.com\",\n" +
+ " \"phone\": \"+1 (919) 432-2299\",\n" +
+ " \"address\": \"555 Myrtle Avenue, Yonah, Arkansas, 4416\",\n" +
+ " \"about\": \"commodo exercitation ex adipisicing reprehenderit amet ut\",\n" +
+ " \"registered\": \"2019-04-02T12:22:13 -03:00\",\n" +
+ " \"latitude\": 26.396021,\n" +
+ " \"longitude\": -51.909653,\n" +
+ " \"tags\": [\n" +
+ " \"deserunt\",\n" +
+ " \"veniam\",\n" +
+ " \"ut\",\n" +
+ " \"velit\",\n" +
+ " \"elit\",\n" +
+ " \"proident\",\n" +
+ " \"reprehenderit\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Mcknight Walsh\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Dalton Mclean\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Crystal Poole\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Carissa Hogan! You have 7 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"_id\": \"63f15335754d0e8d9275a344\",\n" +
+ " \"index\": 7,\n" +
+ " \"guid\": \"4f7f213b-29b1-48e6-b586-c76b609340f0\",\n" +
+ " \"isActive\": true,\n" +
+ " \"balance\": \"$1,114.53\",\n" +
+ " \"picture\": \"http://placehold.it/32x32\",\n" +
+ " \"age\": 34,\n" +
+ " \"eyeColor\": \"green\",\n" +
+ " \"name\": \"Vonda Whitley\",\n" +
+ " \"gender\": \"female\",\n" +
+ " \"company\": \"APEXTRI\",\n" +
+ " \"email\": \"vondawhitley@apextri.com\",\n" +
+ " \"phone\": \"+1 (852) 464-2850\",\n" +
+ " \"address\": \"115 Rogers Avenue, Mahtowa, Northern Mariana Islands, 8529\",\n" +
+ " \"about\": \"cupidatat consequat excepteur consequat incididunt officia esse\",\n" +
+ " \"registered\": \"2014-08-15T07:32:32 -04:00\",\n" +
+ " \"latitude\": -11.275146,\n" +
+ " \"longitude\": 114.522759,\n" +
+ " \"tags\": [\n" +
+ " \"occaecat\",\n" +
+ " \"occaecat\",\n" +
+ " \"incididunt\",\n" +
+ " \"ea\",\n" +
+ " \"et\",\n" +
+ " \"id\",\n" +
+ " \"eiusmod\"\n" +
+ " ],\n" +
+ " \"friends\": [\n" +
+ " {\n" +
+ " \"id\": 0,\n" +
+ " \"name\": \"Tania Cunningham\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 1,\n" +
+ " \"name\": \"Boone Best\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"id\": 2,\n" +
+ " \"name\": \"Nanette Yates\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"greeting\": \"Hello, Vonda Whitley! You have 1 unread messages.\",\n" +
+ " \"favoriteFruit\": \"banana\"\n" +
+ " }\n" +
+ "]");
+ }
+
+ @Test
+ public void testJsonEmptyString() {
+ assertThrows(MalformedJsonException.class, () -> testJson(""));
+ }
+
+ @Test
+ public void testJsonBlankString() {
+ assertThrows(MalformedJsonException.class, () -> testJson(" "));
+ }
+
+ private void testJson(String jsonString) {
+ testJsonVarchar(jsonString);
+ if (unitDbAdapter.supportsJsonType()) {
+ testJsonOther(jsonString);
+ }
+ }
+
+ private void testJsonOther(String jsonString) {
+ JsonOther jsonInsert = context.newObject(JsonOther.class);
+ jsonInsert.setData(new Json(jsonString));
+ context.commitChanges();
+
+ JsonOther jsonSelect = context.selectOne(SelectById.query(JsonOther.class, jsonInsert.getObjectId()));
+ assertEquals(jsonInsert.getData(), jsonSelect.getData());
+ }
+
+ private void testJsonVarchar(String jsonString) {
+ JsonVarchar jsonInsert = context.newObject(JsonVarchar.class);
+ jsonInsert.setData(new Json(jsonString));
+ context.commitChanges();
+
+ JsonVarchar jsonSelect = context.selectOne(SelectById.query(JsonVarchar.class, jsonInsert.getObjectId()));
+ assertEquals(jsonInsert.getData(), jsonSelect.getData());
+ }
+}
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonUtilsTest.java b/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonUtilsTest.java
index d60c2a4..d790d58 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonUtilsTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/value/json/JsonUtilsTest.java
@@ -20,55 +20,215 @@
package org.apache.cayenne.value.json;
import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertThrows;
/**
* @since 4.2
*/
+@RunWith(Enclosed.class)
public class JsonUtilsTest {
- @Test
- public void compare() {
- assertTrue(JsonUtils.compare("[]", "[]"));
- assertTrue(JsonUtils.compare("{}", "{}"));
- assertFalse(JsonUtils.compare("[]", "{}"));
+ @RunWith(Parameterized.class)
+ public static class CompareTest {
- assertTrue(JsonUtils.compare("123", "123"));
- assertFalse(JsonUtils.compare("123", "124"));
+ @Parameterized.Parameters(name = " {0} eq {1} ")
+ public static Object[][] data() {
+ return new Object[][]{
+ {"[]", "[]", true},
+ {"{}", "{}", true},
+ {"[]", "{}", false},
- assertTrue(JsonUtils.compare("null", "null"));
- assertTrue(JsonUtils.compare("true", "true"));
- assertFalse(JsonUtils.compare("true", "false"));
+ {"123", "123", true},
+ {"123", "124", false},
- assertTrue(JsonUtils.compare("\"123\"", "\"123\""));
- assertFalse(JsonUtils.compare("123", "\"123\""));
+ {"null", "null", true},
+ {"true", "true", true},
+ {"true", "false", false},
- assertTrue(JsonUtils.compare("[1,2,3]", "[1, 2, 3]"));
- assertFalse(JsonUtils.compare("[1,2,3]", "[1,2,3,4]"));
- assertFalse(JsonUtils.compare("[1,2,3]", "[1,2]"));
- assertFalse(JsonUtils.compare("[1,2,3]", "[1,2,4]"));
+ {"\"123\"", "\"123\"", true},
+ {"123", "\"123\"", false},
- assertTrue(JsonUtils.compare("{\"abc\":123,\"def\":321}", " {\"def\" : 321 , \n\t\"abc\" :\t123 }"));
- assertFalse(JsonUtils.compare("{\"abc\":123}", " {\"abc\" : 124 }"));
+ {"[1,2,3]", "[1, 2, 3]", true},
+ {"[1,2,3]", "[1,2,3,4]", false},
+ {"[1,2,3]", "[1,2]", false},
+ {"[1,2,3]", "[1,2,4]", false},
+
+ {"{\"abc\":123,\"def\":321}", " {\"def\" : 321 , \n\t\"abc\" :\t123 }", true},
+ {"{\"abc\":123}", " {\"abc\" : 124 }", false}
+ };
+ }
+
+ @Parameterized.Parameter
+ public String jsonStringA;
+ @Parameterized.Parameter(1)
+ public String jsonStringB;
+ @Parameterized.Parameter(2)
+ public boolean areEquals;
+
+ @Test
+ public void compare() {
+ assertEquals(areEquals, JsonUtils.compare(jsonStringA, jsonStringB));
+ }
}
- @Test
- public void normalize() {
- assertEquals("[]", JsonUtils.normalize("[]"));
- assertEquals("{}", JsonUtils.normalize("{}"));
- assertEquals("true", JsonUtils.normalize("true"));
- assertEquals("null", JsonUtils.normalize("null"));
- assertEquals("false", JsonUtils.normalize("false"));
- assertEquals("123", JsonUtils.normalize("123"));
- assertEquals("-10.24e3", JsonUtils.normalize("-10.24e3"));
- assertEquals("\"abc\\\"def\"", JsonUtils.normalize("\"abc\\\"def\""));
+ @RunWith(Parameterized.class)
+ public static class NormalizeTest {
- assertEquals("[1, 2.0, -0.3e3, false, null, true]",
- JsonUtils.normalize("[1 , 2.0 ,-0.3e3, false,\nnull,\ttrue]"));
- assertEquals("{\"abc\": 321, \"def\": true, \"ghi\": \"jkl\"}",
- JsonUtils.normalize("{\"abc\":321,\n\"def\":true,\n\t\"ghi\":\"jkl\"}"));
+ @Parameterized.Parameters(name = " {0} ")
+ public static Object[][] data() {
+ return new Object[][]{
+ {"[]", "[]", null},
+ {"{}", "{}", null},
+ {"true", "true", null},
+ {"null", "null", null},
+ {"false", "false", null},
+ {"123", "123", null},
+ {"-10.24e3", "-10.24e3", null},
+ {"\"abc\\\"def\"", "\"abc\\\"def\"", null},
+
+ {
+ "[1, 2.0, -0.3e3, false, null, true]",
+ "[1 , 2.0 ,-0.3e3, false,\nnull,\ttrue]",
+ null
+ },
+ {
+ "{\"abc\": 321, \"def\": true, \"ghi\": \"jkl\"}",
+ "{\"abc\":321,\n\"def\":true,\n\t\"ghi\":\"jkl\"}",
+ null
+ },
+ {
+ "{\"tags\": [\"ad\", \"irure\", \"anim\"], \"age\": 20}",
+ "{\"tags\": [\"ad\",\n\"irure\", \"anim\"],\n\"age\": 20}",
+ null
+ },
+ {
+ "{\"objects\": [{\"id\": 1}, {\"id\": 2}]}",
+ "{\"objects\":\n[\n{\n\"id\": 1\n},\n{\n\"id\": 2\n}\n]}",
+ null
+ },
+ {
+ "["
+ + "{"
+ + "\"_id\": \"63f218c8ae709e45c7b32c5f\", "
+ + "\"index\": 0, "
+ + "\"guid\": \"b3c2b147-9031-40ee-b2a9-fabbd7f5da81\", "
+ + "\"isActive\": false, "
+ + "\"balance\": \"$2,836.15\", "
+ + "\"picture\": \"http://placehold.it/32x32\", "
+ + "\"age\": 21, "
+ + "\"eyeColor\": \"green\", "
+ + "\"name\": \"Ratliff Martin\", "
+ + "\"gender\": \"male\", "
+ + "\"company\": \"PLASMOSIS\", "
+ + "\"email\": \"ratliffmartin@plasmosis.com\", "
+ + "\"phone\": \"+1 (897) 415-2945\", "
+ + "\"address\": \"241 Foster Avenue, Outlook, New Jersey, 1479\", "
+ + "\"about\": \"pariatur irure qui consequat excepteur laborum nulla\", "
+ + "\"registered\": \"2018-05-18T08:04:15 -03:00\", "
+ + "\"latitude\": -51.195497, "
+ + "\"longitude\": 163.317807, "
+ + "\"tags\": ["
+ + "\"exercitation\", "
+ + "\"nulla\", "
+ + "\"labore\", "
+ + "\"enim\", "
+ + "\"ad\", "
+ + "\"anim\", "
+ + "\"excepteur\""
+ + "], "
+ + "\"friends\": ["
+ + "{"
+ + "\"id\": 0, "
+ + "\"name\": \"Rowena Benson\""
+ + "}, "
+ + "{"
+ + "\"id\": 1, "
+ + "\"name\": \"Bird Mclaughlin\""
+ + "}, "
+ + "{"
+ + "\"id\": 2, "
+ + "\"name\": \"Mabel James\""
+ + "}"
+ + "], "
+ + "\"greeting\": \"Hello, Ratliff Martin! You have 2 unread messages.\", "
+ + "\"favoriteFruit\": \"strawberry\""
+ + "}"
+ + "]",
+
+ "[\n"
+ + " {\n"
+ + " \"_id\": \"63f218c8ae709e45c7b32c5f\",\n"
+ + " \"index\": 0,\n"
+ + " \"guid\": \"b3c2b147-9031-40ee-b2a9-fabbd7f5da81\",\n"
+ + " \"isActive\": false,\n"
+ + " \"balance\": \"$2,836.15\",\n"
+ + " \"picture\": \"http://placehold.it/32x32\",\n"
+ + " \"age\": 21,\n"
+ + " \"eyeColor\": \"green\",\n"
+ + " \"name\": \"Ratliff Martin\",\n"
+ + " \"gender\": \"male\",\n"
+ + " \"company\": \"PLASMOSIS\",\n"
+ + " \"email\": \"ratliffmartin@plasmosis.com\",\n"
+ + " \"phone\": \"+1 (897) 415-2945\",\n"
+ + " \"address\": \"241 Foster Avenue, Outlook, New Jersey, 1479\",\n"
+ + " \"about\": \"pariatur irure qui consequat excepteur laborum nulla\",\n"
+ + " \"registered\": \"2018-05-18T08:04:15 -03:00\",\n"
+ + " \"latitude\": -51.195497,\n"
+ + " \"longitude\": 163.317807,\n"
+ + " \"tags\": [\n"
+ + " \"exercitation\",\n"
+ + " \"nulla\",\n"
+ + " \"labore\",\n"
+ + " \"enim\",\n"
+ + " \"ad\",\n"
+ + " \"anim\",\n"
+ + " \"excepteur\"\n"
+ + " ],\n"
+ + " \"friends\": [\n"
+ + " {\n"
+ + " \"id\": 0,\n"
+ + " \"name\": \"Rowena Benson\"\n"
+ + " },\n"
+ + " {\n"
+ + " \"id\": 1,\n"
+ + " \"name\": \"Bird Mclaughlin\"\n"
+ + " },\n"
+ + " {\n"
+ + " \"id\": 2,\n"
+ + " \"name\": \"Mabel James\"\n"
+ + " }\n"
+ + " ],\n"
+ + " \"greeting\": \"Hello, Ratliff Martin! You have 2 unread messages.\",\n"
+ + " \"favoriteFruit\": \"strawberry\"\n"
+ + " }\n"
+ + "]",
+
+ null
+ },
+
+ {"", "", MalformedJsonException.class},
+ };
+ }
+
+ @Parameterized.Parameter
+ public String expected;
+ @Parameterized.Parameter(1)
+ public String jsonString;
+ @Parameterized.Parameter(2)
+ public Class<? extends Throwable> throwable;
+
+ @Test
+ public void normalize() {
+ if (throwable == null) {
+ assertEquals(expected, JsonUtils.normalize(jsonString));
+ } else {
+ assertThrows(throwable, () -> JsonUtils.normalize(jsonString));
+ }
+ }
}
}
\ No newline at end of file
diff --git a/cayenne-server/src/test/resources/cayenne-json.xml b/cayenne-server/src/test/resources/cayenne-json.xml
new file mode 100644
index 0000000..a49827c
--- /dev/null
+++ b/cayenne-server/src/test/resources/cayenne-json.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<domain xmlns="http://cayenne.apache.org/schema/11/domain"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/11/domain https://cayenne.apache.org/schema/11/domain.xsd"
+ project-version="11">
+ <map name="json"/>
+</domain>
diff --git a/cayenne-server/src/test/resources/json.map.xml b/cayenne-server/src/test/resources/json.map.xml
new file mode 100644
index 0000000..cf237e0
--- /dev/null
+++ b/cayenne-server/src/test/resources/json.map.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ https://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<data-map xmlns="http://cayenne.apache.org/schema/11/modelMap"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://cayenne.apache.org/schema/11/modelMap https://cayenne.apache.org/schema/11/modelMap.xsd"
+ project-version="11">
+ <property name="defaultPackage" value="org.apache.cayenne.testdo.json"/>
+ <property name="defaultSuperclass" value="org.apache.cayenne.CayenneDataObject"/>
+ <db-entity name="JSON_OTHER">
+ <db-attribute name="DATA" type="OTHER" isMandatory="true"/>
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <db-entity name="JSON_VARCHAR">
+ <db-attribute name="DATA" type="LONGNVARCHAR" isMandatory="true"/>
+ <db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
+ </db-entity>
+ <obj-entity name="JsonOther" className="org.apache.cayenne.testdo.json.JsonOther" dbEntityName="JSON_OTHER">
+ <obj-attribute name="data" type="org.apache.cayenne.value.Json" db-attribute-path="DATA"/>
+ </obj-entity>
+ <obj-entity name="JsonVarchar" className="org.apache.cayenne.testdo.json.JsonVarchar" dbEntityName="JSON_VARCHAR">
+ <obj-attribute name="data" type="org.apache.cayenne.value.Json" db-attribute-path="DATA"/>
+ </obj-entity>
+</data-map>
diff --git a/cayenne-server/src/test/resources/relationships-flattened.map.xml b/cayenne-server/src/test/resources/relationships-flattened.map.xml
index a9163c2..e1f3938 100644
--- a/cayenne-server/src/test/resources/relationships-flattened.map.xml
+++ b/cayenne-server/src/test/resources/relationships-flattened.map.xml
@@ -19,11 +19,11 @@
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
<db-entity name="ENTITY2">
- <db-attribute name="ENTITY1_ID" type="INTEGER"/>
+ <db-attribute name="ENTITY1_ID" type="INTEGER" isMandatory="true"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
<db-entity name="ENTITY3">
- <db-attribute name="ENTITY2_ID" type="INTEGER"/>
+ <db-attribute name="ENTITY2_ID" type="INTEGER" isMandatory="true"/>
<db-attribute name="ID" type="INTEGER" isPrimaryKey="true" isMandatory="true"/>
</db-entity>
<db-entity name="FLATTENED_CIRCULAR">
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
index 16ea152..2bd56fa 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/ObjAttributeTableModel.java
@@ -22,6 +22,7 @@
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.configuration.DataChannelDescriptor;
import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.di.DIRuntimeException;
import org.apache.cayenne.map.DbAttribute;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EmbeddedAttribute;
@@ -83,8 +84,8 @@
}
private static List<ObjAttributeWrapper> wrapObjAttributes(Collection<ObjAttribute> attributes) {
- List<ObjAttributeWrapper> wrappedAttributes = new ArrayList<>();
- for(ObjAttribute attr : attributes) {
+ List<ObjAttributeWrapper> wrappedAttributes = new ArrayList<>();
+ for (ObjAttribute attr : attributes) {
wrappedAttributes.add(new ObjAttributeWrapper(attr));
}
return wrappedAttributes;
@@ -122,7 +123,9 @@
: null;
}
- /** Refreshes DbEntity to current db entity within ObjEntity. */
+ /**
+ * Refreshes DbEntity to current db entity within ObjEntity.
+ */
public void resetDbEntity() {
if (dbEntity == entity.getDbEntity()) {
return;
@@ -196,12 +199,10 @@
if (dbAttribute == null) {
if (!attribute.isInherited() && attribute.getEntity().isAbstract()) {
return attribute.getDbAttributePath();
- }
- else {
+ } else {
return null;
}
- }
- else if (attribute.getDbAttributePath() != null && attribute.getDbAttributePath().contains(".")) {
+ } else if (attribute.getDbAttributePath() != null && attribute.getDbAttributePath().contains(".")) {
return attribute.getDbAttributePath();
}
return dbAttribute.getName();
@@ -213,20 +214,15 @@
if (!(attribute.getValue() instanceof EmbeddedAttribute)) {
try {
type = TypesMapping.getSqlTypeByJava(attribute.getJavaClass());
- // have to catch the exception here to make sure that
- // exceptional situations
- // (class doesn't exist, for example) don't prevent the gui
- // from properly updating.
- }
- catch (CayenneRuntimeException cre) {
+ // have to catch the exception here to make sure that exceptional situations
+ // (class doesn't exist, for example) don't prevent the gui from properly updating.
+ } catch (CayenneRuntimeException | DIRuntimeException cre) {
return null;
}
- }
- else {
+ } else {
return null;
}
- }
- else {
+ } else {
type = dbAttribute.getType();
}
return TypesMapping.getSqlNameByType(type);
@@ -251,7 +247,7 @@
*/
@Override
public void resetModel() {
- for(ObjAttributeWrapper attribute : objectList) {
+ for (ObjAttributeWrapper attribute : objectList) {
attribute.resetEdits();
}
}
@@ -261,7 +257,7 @@
*/
@Override
public boolean isValid() {
- for(ObjAttributeWrapper attribute : getObjectList()) {
+ for (ObjAttributeWrapper attribute : getObjectList()) {
if (!attribute.isValid()) {
return false;
}
@@ -348,7 +344,7 @@
// If db attribute exist, associate it with obj attribute
if (value != null) {
- if (ProjectUtil.isDbAttributePathCorrect(dbEntity,value.toString())) {
+ if (ProjectUtil.isDbAttributePathCorrect(dbEntity, value.toString())) {
attribute.setDbAttributePath(value.toString());
} else {
attribute.setDbAttributePath(null);
@@ -452,7 +448,7 @@
}
}
- private class ObjAttributeTableComparator implements Comparator<ObjAttributeWrapper>{
+ private class ObjAttributeTableComparator implements Comparator<ObjAttributeWrapper> {
private final int sortCol;
diff --git a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
index 6aa2295..c08c3da 100644
--- a/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
+++ b/modeler/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
@@ -31,6 +31,8 @@
import org.apache.cayenne.query.ObjectSelect;
import org.apache.cayenne.query.PrefetchTreeNode;
import org.apache.cayenne.query.SortOrder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
@@ -248,6 +250,7 @@
private static final String OBJ_C = ":"; // Objective-C syntax addition.
private static Map<String, Integer> selectorToExpressionBridge;
+ private static final Logger logger = LoggerFactory.getLogger(EOFetchSpecificationParser.class);
/**
* selectorToExpressionBridge is just a mapping of EOModeler's selector
@@ -473,7 +476,7 @@
try {
keyExp = entity.translateToDbPath(keyExp);
} catch (Exception dbpathEx) {
- return null;
+ logger.warn("Couldn't find " + keyExp + " in " + entity.getName() + " in EOModel");
}
}
@@ -484,6 +487,7 @@
exp.setOperand(1, comparisonValue);
return exp;
} catch (ExpressionException e) {
+ logger.warn(e.getUnlabeledMessage());
return null;
}
}
diff --git a/pom.xml b/pom.xml
index 3ac9188..18c971a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1075,7 +1075,7 @@
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc-bom</artifactId>
- <version>21.6.0.0.1</version>
+ <version>21.8.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1084,7 +1084,7 @@
<dependencies>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
- <artifactId>ojdbc8</artifactId>
+ <artifactId>ojdbc11</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
@@ -1102,7 +1102,7 @@
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc-bom</artifactId>
- <version>21.6.0.0.1</version>
+ <version>21.8.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
@@ -1111,7 +1111,7 @@
<dependencies>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
- <artifactId>ojdbc8</artifactId>
+ <artifactId>ojdbc11</artifactId>
<scope>test</scope>
</dependency>
</dependencies>