Refactored the SQL ES to not depend on JOOQ doing the right thing in regards to java.lang.String type for MariaDb and MySQL.
Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/5354d838 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/5354d838 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/5354d838 Branch: refs/heads/Migrate_Junit5 Commit: 5354d838032f44bb2dc4aa9822aefe6ed3dc7917 Parents: ee29552 Author: niclas <[email protected]> Authored: Thu Apr 19 10:07:57 2018 +0800 Committer: niclas <[email protected]> Committed: Thu Apr 19 10:07:57 2018 +0800 ---------------------------------------------------------------------- .../polygene/api/common/QualifiedName.java | 5 + .../test/entity/AbstractEntityStoreTest.java | 4 +- extensions/entitystore-sql/build.gradle | 1 + .../polygene/entitystore/sql/EntitiesTable.java | 117 +++++++++++++------ .../polygene/entitystore/sql/MixinTable.java | 55 +++++---- .../sql/SqlEntityStoreConfiguration.java | 22 ++++ .../entitystore/sql/SqlEntityStoreMixin.java | 9 +- .../polygene/entitystore/sql/SqlTable.java | 26 +---- .../polygene/entitystore/sql/SqlType.java | 57 +++++++-- .../polygene/entitystore/sql/TableFields.java | 45 ------- .../polygene/entitystore/sql/TypesTable.java | 89 ++++++++++---- .../entitystore/sql/MariaDbEntityStoreTest.java | 37 +++--- .../sql/MariaDbEntityStoreTestSuite.java | 43 ++++--- .../entitystore/sql/MySQLEntityStoreTest.java | 40 +++++-- .../sql/MySQLEntityStoreTestSuite.java | 40 +++++-- 15 files changed, 370 insertions(+), 220 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java ---------------------------------------------------------------------- diff --git a/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java b/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java index 657b6de..badbd3b 100644 --- a/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java +++ b/core/api/src/main/java/org/apache/polygene/api/common/QualifiedName.java @@ -258,4 +258,9 @@ public final class QualifiedName } return name.compareTo( other.name ); } + + public boolean isOriginatingFrom( Class<?> mixinType ) + { + return typeName.isClass( mixinType ); + } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java index 49623cb..0b67ded 100644 --- a/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java +++ b/core/testsupport/src/main/java/org/apache/polygene/test/entity/AbstractEntityStoreTest.java @@ -185,11 +185,11 @@ public abstract class AbstractEntityStoreTest assertThat( "property 'doubleValue' has incorrect value", instance.doubleValue().get(), - equalTo( 42D ) ); + equalTo( 42.0 ) ); assertThat( "property 'floatValue' has incorrect value", instance.floatValue().get(), - equalTo( 42F ) ); + equalTo( 42f ) ); assertThat( "property 'booleanValue' has incorrect value", instance.booleanValue().get(), http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/build.gradle ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/build.gradle b/extensions/entitystore-sql/build.gradle index e3388ac..5437409 100644 --- a/extensions/entitystore-sql/build.gradle +++ b/extensions/entitystore-sql/build.gradle @@ -27,6 +27,7 @@ jar { manifest { name = "Apache Polygene⢠Extension - EntityStore - ORM" } } dependencies { api polygene.core.bootstrap api polygene.library( 'sql' ) + api polygene.library( 'constraints' ) api libraries.jooq runtimeOnly polygene.core.runtime http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/EntitiesTable.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/EntitiesTable.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/EntitiesTable.java index acd4532..e18f1b5 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/EntitiesTable.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/EntitiesTable.java @@ -53,48 +53,75 @@ import org.jooq.Field; import org.jooq.Record; import org.jooq.RecordType; import org.jooq.Result; +import org.jooq.SQLDialect; import org.jooq.SelectJoinStep; import org.jooq.SelectQuery; import org.jooq.Table; import org.jooq.impl.DSL; +import static org.apache.polygene.entitystore.sql.MixinTable.INDEX_COLUMN_NAME; +import static org.apache.polygene.entitystore.sql.MixinTable.NAME_COLUMN_NAME; +import static org.apache.polygene.entitystore.sql.MixinTable.REFERENCE_COLUMN_NAME; +import static org.apache.polygene.entitystore.sql.SqlType.makeField; + /** * This class handles all the dealing with the main table, called the Entities Table. * <p> - * This is the table that holds the {@link BaseEntity} rows, and joins with the different so called - * {@link MixinTable}, which handles one table per Mixin type. + * This is the table that holds the {@link BaseEntity} rows, and joins with the different so called + * {@link MixinTable}, which handles one table per Mixin type. * </p> */ @SuppressWarnings( "WeakerAccess" ) public class EntitiesTable - implements TableFields { + private static final String VALUEID_COLUMN_NAME = "_value_id"; + private static final String TYPE_COLUMN_NAME = "_type"; + private static final String VERSION_COLUMN_NAME = "_version"; + private static final String APPLICATIONVERSION_COLUMN_NAME = "_app_version"; + private static final Predicate<? super Class<?>> NOT_COMPOSITE = type -> !( type.equals( Composite.class ) || type.equals( EntityComposite.class ) ); private static final Predicate<? super Class<?>> NOT_HASIDENTITY = type -> !( type.equals( HasIdentity.class ) ); + private final SQLDialect dialect; private Map<EntityCompositeType, Set<Class<?>>> mixinTypeCache = new ConcurrentHashMap<>(); private Map<Class<?>, MixinTable> mixinTablesCache = new ConcurrentHashMap<>(); private final Table<Record> entitiesTable; - private JooqDslContext dsl; + + private Field<String> valueIdentityColumn; + private Field<String> typeNameColumn; + private Field<String> versionColumn; + private Field<String> applicationVersionColumn; + + private final JooqDslContext dsl; private final TypesTable types; - private String applicationVersion; - private Serialization serialization; + private final String applicationVersion; + private final Serialization serialization; private boolean replacementStrategy = false; // Figure out later if we should support both and if so, how. - EntitiesTable( JooqDslContext dsl, TypesTable types, String applicationVersion, String entitiesTableName, Serialization serialization ) + EntitiesTable( JooqDslContext dsl, + SQLDialect dialect, + TypesTable types, + String applicationVersion, + String entitiesTableName, + Serialization serialization ) { this.dsl = dsl; + this.dialect = dialect; this.types = types; this.applicationVersion = applicationVersion; this.serialization = serialization; entitiesTable = dsl.tableOf( entitiesTableName ); + valueIdentityColumn = makeField( VALUEID_COLUMN_NAME, String.class, dialect ); + typeNameColumn = makeField( TYPE_COLUMN_NAME, String.class, dialect ); + versionColumn = makeField( VERSION_COLUMN_NAME, String.class, dialect ); + applicationVersionColumn = makeField( APPLICATIONVERSION_COLUMN_NAME, String.class, dialect ); } public BaseEntity fetchEntity( EntityReference reference, ModuleDescriptor module ) { Result<Record> baseEntityResult = dsl .selectFrom( entitiesTable ) - .where( identityColumn.eq( reference.identity().toString() ) ) + .where( types.identityColumn().eq( reference.identity().toString() ) ) .fetch(); if( baseEntityResult.isEmpty() ) @@ -112,10 +139,10 @@ public class EntitiesTable result.type = findEntityDescriptor( typeName, module ); result.version = row.field( versionColumn ).get( row ); result.applicationVersion = row.field( applicationVersionColumn ).get( row ); - result.identity = StringIdentity.identityOf( row.field( identityColumn ).get( row ) ); + result.identity = StringIdentity.identityOf( row.field( types.identityColumn() ).get( row ) ); result.currentValueIdentity = EntityReference.parseEntityReference( row.field( valueIdentityColumn ).get( row ) ).identity(); - result.modifedAt = Instant.ofEpochMilli( row.field( modifiedColumn ).get( row ).getTime() ); - result.createdAt = Instant.ofEpochMilli( row.field( createdColumn ).get( row ).getTime() ); + result.modifedAt = Instant.ofEpochMilli( row.field( types.modifiedColumn() ).get( row ).getTime() ); + result.createdAt = Instant.ofEpochMilli( row.field( types.createdColumn() ).get( row ).getTime() ); return result; } @@ -172,7 +199,7 @@ public class EntitiesTable private MixinTable findMixinTable( Class<?> type, EntityDescriptor entityDescriptor ) { - return mixinTablesCache.computeIfAbsent( type, t -> new MixinTable( dsl, types, type, entityDescriptor, serialization ) ); + return mixinTablesCache.computeIfAbsent( type, t -> new MixinTable( dsl, dialect, types, type, entityDescriptor, serialization ) ); } private Set<Class<?>> mixinsOf( Stream<? extends AssociationDescriptor> stream ) @@ -216,9 +243,9 @@ public class EntitiesTable String typeName = descriptor.primaryType().getName(); Instant currentTime = uow.currentTime(); dsl.insertInto( entitiesTable ) - .set( identityColumn, reference.identity().toString() ) - .set( createdColumn, new Timestamp( currentTime.toEpochMilli() )) - .set( modifiedColumn, new Timestamp( currentTime.toEpochMilli()) ) + .set( types.identityColumn(), reference.identity().toString() ) + .set( types.createdColumn(), new Timestamp( currentTime.toEpochMilli() ) ) + .set( types.modifiedColumn(), new Timestamp( currentTime.toEpochMilli() ) ) .set( valueIdentityColumn, valueIdentity ) .set( typeNameColumn, typeName ) .set( versionColumn, "1" ) @@ -243,11 +270,11 @@ public class EntitiesTable entity.currentValueIdentity = StringIdentity.identityOf( UUID.randomUUID().toString() ); } dsl.update( entitiesTable ) - .set( modifiedColumn, new Timestamp( uow.currentTime().toEpochMilli() ) ) + .set( types.modifiedColumn(), new Timestamp( uow.currentTime().toEpochMilli() ) ) .set( valueIdentityColumn, entity.currentValueIdentity.toString() ) .set( versionColumn, entity.version ) .set( applicationVersionColumn, applicationVersion ) - .where( identityColumn.eq( entity.identity.toString() ) ) + .where( types.identityColumn().eq( entity.identity.toString() ) ) .execute(); } @@ -321,32 +348,32 @@ public class EntitiesTable SelectQuery<Record> query = from.where( identityColumnOf( entitiesTable ).eq( reference ) ).getQuery(); Result<Record> result = query.fetch(); RecordType<Record> recordType = result.recordType(); - result.forEach( record -> - { - AssociationValue value = new AssociationValue(); - if( recordType.indexOf( referenceColumn ) >= 0 ) - { - // some many-to-many association found. - if( recordType.indexOf( nameColumn ) >= 0 ) - { - // NamedAssociations found. - value.name = QualifiedName.fromClass( entityDescriptor.primaryType(), record.getValue( nameColumn ) ); - } - if( recordType.indexOf( indexColumn ) >= 0 ) - { - // ManyAssociations found. - value.position = record.getValue( indexColumn ); - } - value.reference = record.getValue( referenceColumn ); - } - consume.accept( value ); - } ); + result.forEach( record -> { + AssociationValue value = new AssociationValue(); + if( recordType.indexOf( MixinTable.REFERENCE_COLUMN_NAME ) >= 0 ) + { + // some many-to-many association found. + if( recordType.indexOf( NAME_COLUMN_NAME ) >= 0 ) + { + // NamedAssociations found. + value.name = QualifiedName.fromClass( entityDescriptor.primaryType(), (String) record.get( NAME_COLUMN_NAME ) ); + EntityCompositeType valueType = entityDescriptor.valueType(); + } + if( recordType.indexOf( INDEX_COLUMN_NAME ) >= 0 ) + { + // ManyAssociations found. + value.position = (String) record.get( INDEX_COLUMN_NAME ); + } + value.reference = (String) record.get( REFERENCE_COLUMN_NAME ); + consume.accept( value ); + } + } ); } private Field<String> identityColumnOf( Table<Record> joinedTable ) { String name = joinedTable.getName(); - String identity = identityColumn.getName(); + String identity = types.identityColumn().getName(); return DSL.field( DSL.name( name, identity ), String.class ); } @@ -395,4 +422,18 @@ public class EntitiesTable assocTables.forEach( table -> dsl.delete( table ).where( identityColumnOf( table ).eq( valueId ) ).execute() ); } } + + void create() + { + dsl.createTableIfNotExists( entitiesTable ) + .column( types.identityColumn() ) + .column( types.createdColumn() ) + .column( typeNameColumn ) + .column( applicationVersionColumn ) + .column( versionColumn ) + .column( types.modifiedColumn() ) + .column( valueIdentityColumn ) + .constraint( DSL.primaryKey( types.identityColumn() ) ) + .execute(); + } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/MixinTable.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/MixinTable.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/MixinTable.java index cf0968c..cb548b3 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/MixinTable.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/MixinTable.java @@ -32,7 +32,6 @@ import org.apache.polygene.api.entity.EntityReference; import org.apache.polygene.api.property.PropertyDescriptor; import org.apache.polygene.api.serialization.Serialization; import org.apache.polygene.api.type.ValueType; -import org.apache.polygene.spi.PolygeneSPI; import org.apache.polygene.spi.entity.ManyAssociationState; import org.apache.polygene.spi.entity.NamedAssociationState; import org.apache.polygene.spi.entitystore.helpers.DefaultEntityState; @@ -40,6 +39,7 @@ import org.jooq.Field; import org.jooq.InsertSetMoreStep; import org.jooq.InsertSetStep; import org.jooq.Record; +import org.jooq.SQLDialect; import org.jooq.Table; import org.jooq.UpdateSetMoreStep; import org.jooq.impl.DSL; @@ -48,19 +48,26 @@ import org.jooq.impl.DSL; * MixinTable is a class that handles the creation of the queries into the Mixin tables, both for insertions/updates * as well as retrieval. * <p> - * Note that these tables are only queried as part of a SQL {@code JOIN} statement and never directly. + * Note that these tables are only queried as part of a SQL {@code JOIN} statement and never directly. * </p> * <p> - * Creation of the actual Mixin tables happens in {@link TypesTable}. + * Creation of the actual Mixin tables happens in {@link TypesTable}. * </p> */ class MixinTable - implements TableFields { + static final String NAME_COLUMN_NAME = "_name"; + static final String INDEX_COLUMN_NAME = "_index"; // either index in ManyAssociation or name in NamedAssociation + static final String REFERENCE_COLUMN_NAME = "_reference"; + private static final String ASSOCS_TABLE_POSTFIX = "_ASSOCS"; private final Table<Record> mixinTable; private final Table<Record> mixinAssocsTable; + private Field<String> nameColumn; + private Field<String> referenceColumn; + private Field<String> indexColumn; + private final JooqDslContext dsl; private final Map<QualifiedName, Field<Object>> properties = new ConcurrentHashMap<>(); private final Map<QualifiedName, Field<String>> associations = new ConcurrentHashMap<>(); @@ -68,16 +75,20 @@ class MixinTable private final List<QualifiedName> namedAssociations = new CopyOnWriteArrayList<>(); private final Class<?> mixinType; + private final TypesTable types; private Serialization serialization; - PolygeneSPI spi; - - MixinTable( JooqDslContext dsl, TypesTable types, Class<?> mixinType, + MixinTable( JooqDslContext dsl, SQLDialect dialect, TypesTable types, Class<?> mixinType, EntityDescriptor descriptor, Serialization serialization ) { + this.types = types; this.dsl = dsl; this.mixinType = mixinType; this.serialization = serialization; + nameColumn = SqlType.makeField( NAME_COLUMN_NAME, String.class, dialect); + referenceColumn = SqlType.makeField( REFERENCE_COLUMN_NAME, String.class, dialect ); + indexColumn = SqlType.makeField( INDEX_COLUMN_NAME, String.class, dialect ); + mixinTable = types.tableFor( mixinType, descriptor ); mixinAssocsTable = getAssocsTable( descriptor ); @@ -114,8 +125,8 @@ class MixinTable { InsertSetMoreStep<Record> primaryTable = dsl.insertInto( mixinTable ) - .set( identityColumn, valueIdentity ) - .set( createdColumn, new Timestamp( System.currentTimeMillis() ) ); + .set( types.identityColumn(), valueIdentity ) + .set( types.createdColumn(), new Timestamp( System.currentTimeMillis() ) ); properties .entrySet() @@ -142,8 +153,8 @@ class MixinTable int counter = 0; for( EntityReference ref : entityReferences ) { - InsertSetMoreStep<Record> set = assocsTable.set( identityColumn, valueIdentity ) - .set( createdColumn, new Timestamp( System.currentTimeMillis() ) ) + InsertSetMoreStep<Record> set = assocsTable.set( types.identityColumn(), valueIdentity ) + .set( types.createdColumn(), new Timestamp( System.currentTimeMillis() ) ) .set( nameColumn, assocName.name() ) .set( indexColumn, "" + counter++ ) .set( referenceColumn, ref == null ? null : ref.identity().toString() ); @@ -169,8 +180,8 @@ class MixinTable for( String name : entityReferences ) { EntityReference ref = entityReferences.get( name ); - InsertSetMoreStep<Record> set = assocsTable.set( identityColumn, valueIdentity ) - .set( createdColumn, new Timestamp( System.currentTimeMillis() ) ) + InsertSetMoreStep<Record> set = assocsTable.set( types.identityColumn(), valueIdentity ) + .set( types.createdColumn(), new Timestamp( System.currentTimeMillis() ) ) .set( nameColumn, assocName.name() ) .set( indexColumn, name ) .set( referenceColumn, ref.identity().toString() ); @@ -243,7 +254,7 @@ class MixinTable { // Need to remove existing records. dsl.delete( mixinAssocsTable ) - .where( identityColumn.eq( valueId ) ) + .where( types.identityColumn().eq( valueId ) ) .execute(); insertManyAndNamedAssociations( state, valueId ); } @@ -255,15 +266,15 @@ class MixinTable || descriptor.state().namedAssociations().count() > 0 ) { Table<Record> table = dsl.tableOf( mixinTable.getName() + ASSOCS_TABLE_POSTFIX ); - int result2 = dsl.createTableIfNotExists( table ) - .column( identityColumn ) - .column( createdColumn ) - .column( nameColumn ) - .column( indexColumn ) - .column( referenceColumn ) - .execute(); + int result = dsl.createTableIfNotExists( table ) + .column( types.identityColumn() ) + .column( types.createdColumn() ) + .column( nameColumn ) + .column( indexColumn ) + .column( referenceColumn ) + .execute(); dsl.createIndex( DSL.name( "IDX_" + table.getName() ) ) - .on( table, identityColumn ) + .on( table, types.identityColumn() ) .execute(); return table; } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java index f5a6929..87e481e 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreConfiguration.java @@ -17,8 +17,10 @@ */ package org.apache.polygene.entitystore.sql; +import org.apache.polygene.api.common.Optional; import org.apache.polygene.api.common.UseDefaults; import org.apache.polygene.api.property.Property; +import org.apache.polygene.library.constraints.annotation.MaxLength; import org.apache.polygene.library.sql.common.SQLConfiguration; /** @@ -64,5 +66,25 @@ public interface SqlEntityStoreConfiguration */ @UseDefaults( "" ) Property<String> dialect(); + + /** Length of Identity strings. + * + * MariaDb and MySQL dialects will not allow unspecified VARCHAR lengths for storing Strings. + * <p/> + * Default: 100 + */ + @Optional + Property<Integer> identityLength(); + + /** Length of Identity strings. + * + * MariaDb and MySQL dialects will not allow unspecified VARCHAR lengths for storing Strings. This configuration + * value defines what value x in VARCHAR(x) should be used for each String property, unless otherwise specified + * as a {@link MaxLength} annotation on the property. + * <p/> + * Default: 1000 + */ + @Optional + Property<Integer> stringLength(); } // END SNIPPET: config http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreMixin.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreMixin.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreMixin.java index c1e7985..213c7c5 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreMixin.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlEntityStoreMixin.java @@ -142,13 +142,20 @@ public class SqlEntityStoreMixin { return value; } + if( type.equals( ValueType.FLOAT ) ) + { + if( value instanceof Double ) // MariaDB/MySQL returns a Double + { + return new Float( (Double) value ); + } + return value; + } if( type.equals( ValueType.STRING ) || type.equals( ValueType.INTEGER ) || type.equals( ValueType.BOOLEAN ) || type.equals( ValueType.DOUBLE ) || type.equals( ValueType.IDENTITY ) || type.equals( ValueType.LONG ) - || type.equals( ValueType.FLOAT ) || type.equals( ValueType.BYTE ) || type.equals( ValueType.CHARACTER ) || type.equals( ValueType.SHORT ) http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlTable.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlTable.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlTable.java index 0600d06..f34d920 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlTable.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlTable.java @@ -39,7 +39,6 @@ import org.jooq.Record; import org.jooq.SQLDialect; import org.jooq.SelectQuery; import org.jooq.conf.Settings; -import org.jooq.impl.DSL; /** * This class handles all the Jooq interactions. @@ -189,7 +188,6 @@ public interface SqlTable extends ServiceActivation @Override public void activateService() - throws Exception { SqlEntityStoreConfiguration config = this.configuration.get(); SQLDialect dialect = getSqlDialect( config ); @@ -201,37 +199,19 @@ public interface SqlTable extends ServiceActivation dsl = tbf.newTransient( JooqDslContext.class, settings, dialect ); types = new TypesTable( dsl, dialect, typesTableName, config ); - entitiesTable = new EntitiesTable( dsl, types, application.version(), entitiesTableName, serialization ); + entitiesTable = new EntitiesTable( dsl, dialect, types, application.version(), entitiesTableName, serialization ); if( config.createIfMissing().get() ) { dsl.transaction( t -> { - - dsl.createTableIfNotExists( dsl.tableNameOf( typesTableName ) ) - .column( identityColumn ) - .column( tableNameColumn ) - .column( createdColumn ) - .column( modifiedColumn ) - .constraint( DSL.primaryKey( identityColumn ) ) - .execute(); - - dsl.createTableIfNotExists( dsl.tableNameOf( entitiesTableName ) ) - .column( identityColumn ) - .column( createdColumn ) - .column( typeNameColumn ) - .column( applicationVersionColumn ) - .column( versionColumn ) - .column( modifiedColumn ) - .column( valueIdentityColumn ) - .constraint( DSL.primaryKey( identityColumn ) ) - .execute(); + types.create(); + entitiesTable.create(); } ); } } @Override public void passivateService() - throws Exception { } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlType.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlType.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlType.java index be98bdb..d072afd 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlType.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/SqlType.java @@ -19,6 +19,7 @@ package org.apache.polygene.entitystore.sql; import java.math.BigDecimal; import java.math.BigInteger; +import java.sql.Timestamp; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; @@ -27,6 +28,10 @@ import java.time.OffsetDateTime; import java.time.Period; import java.time.ZonedDateTime; import org.jooq.DataType; +import org.jooq.Field; +import org.jooq.SQLDialect; +import org.jooq.impl.DSL; +import org.jooq.impl.DefaultDataType; import org.jooq.impl.SQLDataType; import org.jooq.types.Interval; @@ -35,17 +40,31 @@ import org.jooq.types.Interval; */ class SqlType { + static <T> Field<T> makeField( String columnName, Class<T> type, SQLDialect dialect, boolean reference ) + { + return DSL.field( DSL.name( columnName ), getSqlDataTypeFor( dialect, type, reference ) ); + } + + public static <T> Field<T> makeField( String columnName, Class<T> type, SQLDialect dialect ) + { + return makeField( columnName, type, dialect, true ); + } + @SuppressWarnings( "unchecked" ) - static <T> DataType<T> getSqlDataTypeFor( Class<?> propertyType ) + static <T> DataType<T> getSqlDataTypeFor( SQLDialect dialect, Class<T> propertyType, boolean reference ) { if( String.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( Integer.class.isAssignableFrom( propertyType ) ) { return (DataType<T>) SQLDataType.INTEGER; } + if( Timestamp.class.isAssignableFrom( propertyType ) ) + { + return (DataType<T>) SQLDataType.TIMESTAMP; + } if( Long.class.isAssignableFrom( propertyType ) ) { return (DataType<T>) SQLDataType.BIGINT; @@ -64,35 +83,35 @@ class SqlType } if( Instant.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( Interval.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( Period.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( LocalDate.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( LocalTime.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( LocalDateTime.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( ZonedDateTime.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( OffsetDateTime.class.isAssignableFrom( propertyType ) ) { - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); } if( Character.class.isAssignableFrom( propertyType ) ) { @@ -153,6 +172,22 @@ class SqlType return (DataType<T>) SQLDataType.INTEGER; } } - return (DataType<T>) SQLDataType.VARCHAR; + return (DataType<T>) varCharType( dialect, reference ); + } + + private static DataType<String> varCharType( SQLDialect dialect, boolean reference ) + { + if( dialect == SQLDialect.MYSQL || dialect == SQLDialect.MARIADB ) + { + if( reference ) + { + return SQLDataType.VARCHAR.length(1000).nullable(false); + } + else + { + return new DefaultDataType<>( null, String.class, "MEDIUMTEXT" ); + } + } + return SQLDataType.VARCHAR; } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TableFields.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TableFields.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TableFields.java index 11f0acf..ed24905 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TableFields.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TableFields.java @@ -17,11 +17,6 @@ */ package org.apache.polygene.entitystore.sql; -import java.sql.Timestamp; -import org.jooq.Field; - -import static org.apache.polygene.entitystore.sql.TypesTable.makeField; - /** * SQL field names and definitions. * <p> @@ -31,46 +26,6 @@ import static org.apache.polygene.entitystore.sql.TypesTable.makeField; */ public interface TableFields { - // Common in all tables - String IDENTITY_COLUMN_NAME = "_identity"; - String CREATED_COLUMN_NAME = "_created_at"; - String LASTMODIFIED_COLUMN_NAME = "_modified_at"; - - // Types Table - String TABLENAME_COLUMN_NAME = "_table_name"; - - // Entities Table - String VALUEID_COLUMN_NAME = "_value_id"; - String TYPE_COLUMN_NAME = "_type"; - String VERSION_COLUMN_NAME = "_version"; - String APPLICATIONVERSION_COLUMN_NAME = "_app_version"; - - // Mixin Tables - String NAME_COLUMN_NAME = "_name"; - String INDEX_COLUMN_NAME = "_index"; // either index in ManyAssociation or name in NamedAssociation - String REFERENCE_COLUMN_NAME = "_reference"; - String ASSOCS_TABLE_POSTFIX = "_ASSOCS"; - - - // Common Fields - Field<String> identityColumn = makeField( IDENTITY_COLUMN_NAME, String.class ); - Field<Timestamp> createdColumn = makeField( CREATED_COLUMN_NAME, Timestamp.class ); - Field<Timestamp> modifiedColumn = makeField( LASTMODIFIED_COLUMN_NAME, Timestamp.class ); - - // Types Table - Field<String> tableNameColumn = makeField( TABLENAME_COLUMN_NAME, String.class ); - - // Entities Table - Field<String> valueIdentityColumn = makeField( VALUEID_COLUMN_NAME, String.class ); - Field<String> typeNameColumn = makeField( TYPE_COLUMN_NAME, String.class ); - Field<String> versionColumn = makeField( VERSION_COLUMN_NAME, String.class ); - Field<String> applicationVersionColumn = makeField( APPLICATIONVERSION_COLUMN_NAME, String.class ); - - // Mixin Tables - // The _ASSOCS table - Field<String> nameColumn = makeField( NAME_COLUMN_NAME, String.class ); - Field<String> referenceColumn = makeField( REFERENCE_COLUMN_NAME, String.class ); - Field<String> indexColumn = makeField( INDEX_COLUMN_NAME, String.class ); } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TypesTable.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TypesTable.java b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TypesTable.java index 0513768..c75ae57 100644 --- a/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TypesTable.java +++ b/extensions/entitystore-sql/src/main/java/org/apache/polygene/entitystore/sql/TypesTable.java @@ -17,7 +17,6 @@ */ package org.apache.polygene.entitystore.sql; -import java.lang.reflect.Method; import java.lang.reflect.Type; import java.sql.Timestamp; import java.util.Map; @@ -25,9 +24,9 @@ import java.util.concurrent.ConcurrentHashMap; import org.apache.polygene.api.association.AssociationDescriptor; import org.apache.polygene.api.common.QualifiedName; import org.apache.polygene.api.entity.EntityDescriptor; -import org.apache.polygene.api.property.Property; import org.apache.polygene.api.property.PropertyDescriptor; import org.apache.polygene.api.util.Classes; +import org.jooq.Constraint; import org.jooq.CreateTableColumnStep; import org.jooq.DataType; import org.jooq.Field; @@ -40,11 +39,25 @@ import org.jooq.impl.DSL; /** * This class is effectively the manager of the {@link MixinTable} instances. */ -public class TypesTable - implements TableFields +class TypesTable { + // Common in all tables + private static final String IDENTITY_COLUMN_NAME = "_identity"; + private static final String CREATED_COLUMN_NAME = "_created_at"; + private static final String LASTMODIFIED_COLUMN_NAME = "_modified_at"; + + // Types Table + private static final String TABLENAME_COLUMN_NAME = "_table_name"; + + // Common Fields + private Field<String> identityColumn; + private Field<Timestamp> createdColumn; + private Field<Timestamp> modifiedColumn; + + // Types Table + private Field<String> tableNameColumn; + private final Map<Class<?>, Table<Record>> mixinTablesCache = new ConcurrentHashMap<>(); - private final Map<Class<?>, Table<Record>> mixinAssocsTablesCache = new ConcurrentHashMap<>(); private final Table<Record> typesTable; private final SQLDialect dialect; @@ -62,14 +75,14 @@ public class TypesTable this.config = config; typesTable = dsl.tableOf( typesTablesName ); this.dsl = dsl; + Integer idMaxLength = config.identityLength().get(); + identityColumn = SqlType.makeField( IDENTITY_COLUMN_NAME, String.class, dialect ); + createdColumn = SqlType.makeField( CREATED_COLUMN_NAME, Timestamp.class, dialect ); + modifiedColumn = SqlType.makeField( LASTMODIFIED_COLUMN_NAME, Timestamp.class, dialect ); + tableNameColumn = SqlType.makeField( TABLENAME_COLUMN_NAME, String.class, dialect ); } - static <T> Field<T> makeField( String columnName, Class<T> type ) - { - return DSL.field( DSL.name( columnName ), type ); - } - - String tableNameOf( Class<?> mixinType ) + private String tableNameOf( Class<?> mixinType ) { Result<Record> typeInfo = fetchTypeInfoFromTable( mixinType ); if( typeInfo.isEmpty() ) @@ -143,7 +156,7 @@ public class TypesTable String typeName = mixinType.getSimpleName(); String postFix = ""; int counter = 1; - boolean found = false; + boolean found; do { found = checkForTableNamed( typeName + postFix ); @@ -154,7 +167,7 @@ public class TypesTable private boolean checkForTableNamed( String tableName ) { - if( tableName.equalsIgnoreCase( config.entitiesTableName().get() ) || tableName.equalsIgnoreCase( config.typesTableName().get() )) + if( tableName.equalsIgnoreCase( config.entitiesTableName().get() ) || tableName.equalsIgnoreCase( config.typesTableName().get() ) ) { return true; } @@ -164,11 +177,6 @@ public class TypesTable .fetch().size() > 0; } - private boolean isProperty( Method method ) - { - return Property.class.isAssignableFrom( method.getReturnType() ) && method.getParameterCount() == 0; - } - Field<Object> fieldOf( PropertyDescriptor descriptor ) { String propertyName = descriptor.qualifiedName().name(); @@ -178,13 +186,52 @@ public class TypesTable Field<String> fieldOf( AssociationDescriptor descriptor ) { String propertyName = descriptor.qualifiedName().name(); - return DSL.field( DSL.name( propertyName ), DSL.getDataType( String.class ) ); + return DSL.field( DSL.name( propertyName ), dataTypeOf( descriptor ) ); } private <T> DataType<T> dataTypeOf( PropertyDescriptor property ) { Type type = property.type(); - Class<?> rawType = Classes.RAW_CLASS.apply( type ); - return SqlType.getSqlDataTypeFor( rawType ); + + @SuppressWarnings( "unchecked" ) + Class<T> rawType = (Class<T>) Classes.RAW_CLASS.apply( type ); + + return SqlType.getSqlDataTypeFor( dialect, rawType, false ); + } + + private <T> DataType<T> dataTypeOf( AssociationDescriptor property ) + { + Type type = property.type(); + + @SuppressWarnings( "unchecked" ) + Class<T> rawType = (Class<T>) Classes.RAW_CLASS.apply( type ); + + return SqlType.getSqlDataTypeFor( dialect, rawType, false ); + } + + Field<String> identityColumn() + { + return identityColumn; + } + + Field<Timestamp> modifiedColumn() + { + return modifiedColumn; + } + + Field<Timestamp> createdColumn() + { + return createdColumn; + } + + void create() + { + dsl.createTableIfNotExists( typesTable ) + .column( identityColumn ) + .column( tableNameColumn ) + .column( createdColumn ) + .column( modifiedColumn ) + .constraint( DSL.primaryKey( identityColumn ) ) + .execute(); } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTest.java index 259bdf9..663aeec 100644 --- a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTest.java +++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTest.java @@ -23,6 +23,7 @@ import com.github.junit5docker.Docker; import com.github.junit5docker.Environment; import com.github.junit5docker.Port; import com.github.junit5docker.WaitFor; +import java.lang.reflect.UndeclaredThrowableException; import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; @@ -34,9 +35,8 @@ import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.entity.AbstractEntityStoreTest; import org.jooq.SQLDialect; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; -@Disabled( "Waiting response from JOOQ to fix SQL generation. VARCHAR instead of CHAR") @Docker( image = "mariadb", ports = @Port( exposed = 8801, inner = 3306 ), environments = { @@ -44,20 +44,31 @@ import org.junit.jupiter.api.Disabled; @Environment( key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes" ), @Environment( key = "MYSQL_DATABASE", value = "jdbc_test_db" ) }, - waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 30000 ), + waitFor = @WaitFor( value = "mariadb.org binary distribution", timeoutInMillis = 30000 ), newForEachCase = false ) -public class MariaDbEntityStoreTest - extends AbstractEntityStoreTest +public class MariaDbEntityStoreTest extends AbstractEntityStoreTest { + @BeforeAll + public static void waitForDockerToSettle() + { + try + { + Thread.sleep( 5000 ); + } + catch( InterruptedException e ) + { + throw new UndeclaredThrowableException( e ); + } + } + @Override // START SNIPPET: assembly public void assemble( ModuleAssembly module ) throws AssemblyException { // END SNIPPET: assembly - sleep(); super.assemble( module ); ModuleAssembly config = module.layer().module( "config" ); new EntityTestAssembler().defaultServicesVisibleIn( Visibility.layer ).assemble( config ); @@ -92,24 +103,12 @@ public class MariaDbEntityStoreTest + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); defaults.driver().set( "com.mysql.jdbc.Driver" ); defaults.enabled().set( true ); - defaults.username().set("root"); + defaults.username().set( "root" ); defaults.password().set( "" ); // START SNIPPET: assembly } // END SNIPPET: assembly - static void sleep() - { - try - { - Thread.sleep( 11500 ); - } - catch( InterruptedException e ) - { - e.printStackTrace(); - } - } - @AfterEach public void cleanUpData() { http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTestSuite.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTestSuite.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTestSuite.java index e180fa4..44eeafa 100644 --- a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTestSuite.java +++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MariaDbEntityStoreTestSuite.java @@ -23,6 +23,7 @@ import com.github.junit5docker.Docker; import com.github.junit5docker.Environment; import com.github.junit5docker.Port; import com.github.junit5docker.WaitFor; +import java.lang.reflect.UndeclaredThrowableException; import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.sql.assembly.MySQLEntityStoreAssembler; @@ -32,27 +33,36 @@ import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler; import org.apache.polygene.test.entity.model.EntityStoreTestSuite; import org.jooq.SQLDialect; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; -@Disabled( "Waiting response from JOOQ to fix SQL generation. VARCHAR instead of CHAR") -@Docker( image = "org.apache.polygene:org.apache.polygene.internal.docker-mariadb", - ports = @Port( exposed = 8801, inner = 3306), +@Docker( image = "mariadb", + ports = @Port( exposed = 8801, inner = 3306 ), environments = { - @Environment( key = "MYSQL_ROOT_PASSWORD", value = ""), - @Environment(key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes"), - @Environment(key = "MYSQL_DATABASE", value = "jdbc_test_db"), - @Environment( key = "MYSQL_ROOT_HOST", value = "172.17.0.1"), + @Environment( key = "MYSQL_ROOT_PASSWORD", value = "" ), + @Environment( key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes" ), + @Environment( key = "MYSQL_DATABASE", value = "jdbc_test_db" ) }, - waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 30000), + waitFor = @WaitFor( value = "mariadb.org binary distribution", timeoutInMillis = 30000 ), newForEachCase = false ) public class MariaDbEntityStoreTestSuite extends EntityStoreTestSuite { + @BeforeAll + static void waitForDockerToSettle() + { + try + { + Thread.sleep( 5000 ); + } + catch( InterruptedException e ) + { + throw new UndeclaredThrowableException( e ); + } + } @Override protected void defineStorageModule( ModuleAssembly module ) { - MariaDbEntityStoreTest.sleep(); module.defaultServices(); // DataSourceService new DBCPDataSourceServiceAssembler() @@ -77,10 +87,15 @@ public class MariaDbEntityStoreTestSuite extends EntityStoreTestSuite String mysqlHost = "localhost"; int mysqlPort = 8801; - configModule.forMixin( DataSourceConfiguration.class ).declareDefaults() - .url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort - + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" - + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + DataSourceConfiguration defaults = configModule.forMixin( DataSourceConfiguration.class ).declareDefaults(); + defaults + .url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" + + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + defaults.driver().set( "com.mysql.jdbc.Driver" ); + defaults.enabled().set( true ); + defaults.username().set( "root" ); + defaults.password().set( "" ); } @AfterEach http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java index 73fa5f7..1a76c4b 100644 --- a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java +++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTest.java @@ -23,6 +23,7 @@ import com.github.junit5docker.Docker; import com.github.junit5docker.Environment; import com.github.junit5docker.Port; import com.github.junit5docker.WaitFor; +import java.lang.reflect.UndeclaredThrowableException; import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.AssemblyException; import org.apache.polygene.bootstrap.ModuleAssembly; @@ -34,22 +35,33 @@ import org.apache.polygene.test.EntityTestAssembler; import org.apache.polygene.test.entity.AbstractEntityStoreTest; import org.jooq.SQLDialect; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; -@Disabled( "Waiting response from JOOQ to fix SQL generation. VARCHAR instead of CHAR") -@Docker( image = "mysql", ports = @Port( exposed = 8801, inner = 3306), +@Docker( image = "mysql", ports = @Port( exposed = 8801, inner = 3306 ), environments = { - @Environment( key = "MYSQL_ROOT_PASSWORD", value = ""), - @Environment(key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes"), - @Environment(key = "MYSQL_DATABASE", value = "jdbc_test_db"), - @Environment( key = "MYSQL_ROOT_HOST", value = "172.17.0.1"), + @Environment( key = "MYSQL_ROOT_PASSWORD", value = "" ), + @Environment( key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes" ), + @Environment( key = "MYSQL_DATABASE", value = "jdbc_test_db" ) }, - waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 30000), + waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 40000 ), newForEachCase = false ) public class MySQLEntityStoreTest extends AbstractEntityStoreTest { + @BeforeAll + public static void waitForDockerToSettle() + { + try + { + Thread.sleep( 10000 ); + } + catch( InterruptedException e ) + { + throw new UndeclaredThrowableException( e ); + } + } + @Override // START SNIPPET: assembly public void assemble( ModuleAssembly module ) @@ -84,10 +96,14 @@ public class MySQLEntityStoreTest // END SNIPPET: assembly String mysqlHost = "localhost"; int mysqlPort = 8801; - config.forMixin( DataSourceConfiguration.class ).declareDefaults() - .url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort - + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" - + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + DataSourceConfiguration defaults = config.forMixin( DataSourceConfiguration.class ).declareDefaults(); + defaults.url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" + + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + defaults.driver().set( "com.mysql.jdbc.Driver" ); + defaults.enabled().set( true ); + defaults.username().set( "root" ); + defaults.password().set( "" ); // START SNIPPET: assembly } // END SNIPPET: assembly http://git-wip-us.apache.org/repos/asf/polygene-java/blob/5354d838/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTestSuite.java ---------------------------------------------------------------------- diff --git a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTestSuite.java b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTestSuite.java index f062eb8..3426126 100644 --- a/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTestSuite.java +++ b/extensions/entitystore-sql/src/test/java/org/apache/polygene/entitystore/sql/MySQLEntityStoreTestSuite.java @@ -23,6 +23,7 @@ import com.github.junit5docker.Docker; import com.github.junit5docker.Environment; import com.github.junit5docker.Port; import com.github.junit5docker.WaitFor; +import java.lang.reflect.UndeclaredThrowableException; import org.apache.polygene.api.common.Visibility; import org.apache.polygene.bootstrap.ModuleAssembly; import org.apache.polygene.entitystore.sql.assembly.MySQLEntityStoreAssembler; @@ -32,21 +33,32 @@ import org.apache.polygene.library.sql.dbcp.DBCPDataSourceServiceAssembler; import org.apache.polygene.test.entity.model.EntityStoreTestSuite; import org.jooq.SQLDialect; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.BeforeAll; -@Disabled( "Waiting response from JOOQ to fix SQL generation. VARCHAR instead of CHAR") -@Docker( image = "mysql", ports = @Port( exposed = 8801, inner = 3306), +@Docker( image = "mysql", ports = @Port( exposed = 8801, inner = 3306 ), environments = { - @Environment( key = "MYSQL_ROOT_PASSWORD", value = ""), - @Environment(key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes"), - @Environment(key = "MYSQL_DATABASE", value = "jdbc_test_db"), - @Environment( key = "MYSQL_ROOT_HOST", value = "172.17.0.1"), + @Environment( key = "MYSQL_ROOT_PASSWORD", value = "" ), + @Environment( key = "MYSQL_ALLOW_EMPTY_PASSWORD", value = "yes" ), + @Environment( key = "MYSQL_DATABASE", value = "jdbc_test_db" ) }, - waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 30000), + waitFor = @WaitFor( value = "mysqld: ready for connections", timeoutInMillis = 40000 ), newForEachCase = false ) public class MySQLEntityStoreTestSuite extends EntityStoreTestSuite { + @BeforeAll + public static void waitForDockerToSettle() + { + try + { + Thread.sleep( 12000 ); + } + catch( InterruptedException e ) + { + throw new UndeclaredThrowableException( e ); + } + } + @Override protected void defineStorageModule( ModuleAssembly module ) { @@ -74,10 +86,14 @@ public class MySQLEntityStoreTestSuite extends EntityStoreTestSuite String mysqlHost = "localhost"; int mysqlPort = 8801; - configModule.forMixin( DataSourceConfiguration.class ).declareDefaults() - .url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort - + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" - + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + DataSourceConfiguration defaults = configModule.forMixin( DataSourceConfiguration.class ).declareDefaults(); + defaults.url().set( "jdbc:mysql://" + mysqlHost + ":" + mysqlPort + + "/jdbc_test_db?profileSQL=false&useLegacyDatetimeCode=false&serverTimezone=UTC" + + "&nullCatalogMeansCurrent=true&nullNamePatternMatchesAll=true" ); + defaults.driver().set( "com.mysql.jdbc.Driver" ); + defaults.enabled().set( true ); + defaults.username().set( "root" ); + defaults.password().set( "" ); } @AfterEach
