From ac0ba7c38c2b6de6c50fa4dbd30e1e8ab0512afb Mon Sep 17 00:00:00 2001 From: Oleg Khodokevich Date: Fri, 7 Jan 2022 09:34:55 +0300 Subject: [PATCH 1/5] CAY-2639 DBImport and DB name case sensitivity. Added quoted identifier and test for case-sensitive naming. Added a button for using case-sensitive naming in modeler. The useCaseSensitive parameter allows to have in database case sensitive naming and convey its initial state. Added asciidoc. --- .../apache/cayenne/tools/DbImporterTask.java | 8 + .../cayenne/gen/ClassGenerationAction.java | 12 +- .../gen/ClassGenerationActionTest.java | 27 +++ .../cayenne/dbsync/merge/AbstractMerger.java | 21 +- .../cayenne/dbsync/merge/ChainMerger.java | 3 +- .../cayenne/dbsync/merge/DataMapMerger.java | 22 +- .../dbsync/merge/DbAttributeMerger.java | 9 +- .../cayenne/dbsync/merge/DbEntityMerger.java | 24 +- .../dbsync/merge/DbRelationshipMerger.java | 20 +- .../dbsync/merge/MergerDictionary.java | 5 +- .../dbsync/merge/MergerDictionaryDiff.java | 14 +- .../cayenne/dbsync/merge/ProcedureMerger.java | 6 +- .../merge/context/EntityMergeSupport.java | 47 ++-- .../factory/DefaultMergerTokenFactory.java | 12 +- .../merge/factory/H2MergerTokenFactory.java | 5 +- .../merge/factory/HSQLMergerTokenFactory.java | 5 +- .../merge/factory/MergerTokenFactory.java | 7 +- .../factory/MySQLMergerTokenFactory.java | 7 +- .../merge/token/db/DropRelationshipToDb.java | 3 +- .../merge/token/db/SetPrimaryKeyToDb.java | 13 +- .../merge/token/model/CreateTableToModel.java | 6 +- .../token/model/SetPrimaryKeyToModel.java | 14 +- .../dbsync/naming/DeduplicationVisitor.java | 11 +- .../dbimport/DbImportConfiguration.java | 15 ++ .../dbimport/DefaultDbImportAction.java | 12 +- .../reverse/dbimport/ReverseEngineering.java | 26 +- .../reverse/dbload/DbLoadDataStore.java | 11 +- .../dbsync/reverse/dbload/DbLoader.java | 8 +- .../reverse/filters/FiltersConfigBuilder.java | 5 +- .../reverse/filters/IncludeTableFilter.java | 15 +- .../dbsync/reverse/filters/PatternFilter.java | 18 +- .../dbsync/reverse/filters/TableFilter.java | 9 +- .../cayenne/dbsync/xml/ConfigHandler.java | 18 ++ .../cayenne/dbsync/merge/CheckTypeTest.java | 6 +- .../dbsync/merge/DataMapMergerTest.java | 213 ++++++++++++++++- .../dbsync/merge/DbEntityMergerIT.java | 156 ++++++++++++ .../dbsync/merge/EntityMergeSupportIT.java | 179 ++++++++++++++ .../cayenne/dbsync/merge/MergeCase.java | 47 +++- .../cayenne/dbsync/merge/MergerFactoryIT.java | 128 ++++++++++ .../dbsync/merge/token/TokensReverseTest.java | 8 +- .../merge/token/db/SetPrimaryKeyToDbIT.java | 38 +++ .../merge/token/model/AddColumnToModelIT.java | 72 ++++++ .../token/model/CreateTableToModelIT.java | 190 +++++++++++++++ .../model/DropRelationshipToModelIT.java | 224 ++++++++++++++++++ .../dbsync/naming/NameBuilderTest.java | 20 ++ .../dbimport/DefaultDbImportActionTest.java | 6 +- .../dbsync/reverse/dbload/BaseLoaderIT.java | 2 +- .../dbsync/reverse/dbload/DbLoaderIT.java | 2 +- .../filters/FiltersConfigBuilderTest.java | 17 ++ .../reverse/filters/FiltersConfigTest.java | 6 +- .../reverse/filters/PatternFilterTest.java | 48 +++- .../reverse/filters/TableFilterTest.java | 88 ++++++- .../apache/cayenne/tools/DbImportTask.java | 1 + .../cayenne/tools/model/DbImportConfig.java | 28 +++ .../org/apache/cayenne/schema/10/dbimport.xsd | 1 + .../_cayenne-guide/part4/revEngineering.adoc | 2 + .../_cayenne-guide/part6/gradle-plugin.adoc | 1 + .../_cayenne-guide/part6/maven-plugin.adoc | 5 + .../apache/cayenne/tools/DbImporterMojo.java | 1 + .../DbImporterMojoConfigurationTest.java | 4 +- .../cayenne/tools/DbImporterMojoTest.java | 37 ++- .../testConfigFromDataMap.map.xml-result | 1 + ...ImportAddColumnCaseSensitiveNaming-pom.xml | 47 ++++ ...ImportAddColumnCaseSensitiveNaming.map.xml | 33 +++ ...ddColumnCaseSensitiveNaming.map.xml-result | 42 ++++ ...testImportAddColumnCaseSensitiveNaming.sql | 33 +++ ...tImportAddTableCaseSensitiveNaming-pom.xml | 47 ++++ ...tImportAddTableCaseSensitiveNaming.map.xml | 33 +++ ...AddTableCaseSensitiveNaming.map.xml-result | 42 ++++ .../testImportAddTableCaseSensitiveNaming.sql | 33 +++ ...NewRelationshipCaseSensitiveNaming-pom.xml | 50 ++++ ...NewRelationshipCaseSensitiveNaming.map.xml | 32 +++ ...tionshipCaseSensitiveNaming.map.xml-result | 64 +++++ ...portNewRelationshipCaseSensitiveNaming.sql | 41 ++++ ...ImportProcedureCaseSensitiveNaming-pom.xml | 51 ++++ ...ImportProcedureCaseSensitiveNaming.map.xml | 31 +++ ...rocedureCaseSensitiveNaming.map.xml-result | 35 +++ ...testImportProcedureCaseSensitiveNaming.sql | 29 +++ .../dbimport/testTableTypesMap.map.xml-result | 1 + .../dialog/db/load/DbLoaderContext.java | 2 + .../dialog/db/merge/MergerOptions.java | 5 +- .../editor/cgen/CodeGeneratorController.java | 26 +- .../modeler/editor/cgen/SelectionModel.java | 14 ++ .../modeler/editor/dbimport/DbImportView.java | 7 + .../ReverseEngineeringConfigPanel.java | 18 ++ 85 files changed, 2522 insertions(+), 163 deletions(-) create mode 100644 cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming-pom.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml-result create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.sql create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming-pom.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml-result create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.sql create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming-pom.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml-result create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.sql create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming-pom.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml-result create mode 100644 maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.sql diff --git a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java index e331f23623..ffab7b5a02 100644 --- a/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java +++ b/cayenne-ant/src/main/java/org/apache/cayenne/tools/DbImporterTask.java @@ -60,6 +60,7 @@ public class DbImporterTask extends Task { public DbImporterTask() { this.config = new DbImportConfiguration(); this.config.setUsePrimitives(true); + this.config.setUseCaseSensitiveNaming(false); this.config.setUseJava7Types(false); this.config.setNamingStrategy(DefaultObjectNameGenerator.class.getName()); @@ -247,6 +248,13 @@ public void setUsePrimitives(boolean flag) { config.setUsePrimitives(flag); } + /** + * @since 4.2 + */ + public void setUseCaseSensitiveNaming(boolean flag) { + config.setUseCaseSensitiveNaming(flag); + } + /** * @since 4.0 */ diff --git a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java index caeaaeec1e..a66dea15a6 100644 --- a/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java +++ b/cayenne-cgen/src/main/java/org/apache/cayenne/gen/ClassGenerationAction.java @@ -364,14 +364,20 @@ private void validateAttributes() { * the "encoding" property. */ protected Writer openWriter(TemplateType templateType) throws Exception { - - File outFile = (templateType.isSuperclass()) ? fileForSuperclass() : fileForClass(); + boolean isSuperclass = templateType.isSuperclass(); + File outFile = (isSuperclass) ? fileForSuperclass() : fileForClass(); if (outFile == null) { return null; } + if (isSuperclass && outFile.exists() && fileNeedUpdate(outFile, cgenConfiguration.getSuperTemplate())) { + if (!outFile.delete()) { + logger.warn("File " + outFile.getAbsolutePath() + " can't be deleted."); + } + } + if (logger != null) { - String label = templateType.isSuperclass() ? "superclass" : "class"; + String label = isSuperclass ? "superclass" : "class"; logger.info("Generating " + label + " file: " + outFile.getCanonicalPath()); } diff --git a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java index ef9d5e60d0..aa42c0cfcf 100644 --- a/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java +++ b/cayenne-cgen/src/test/java/org/apache/cayenne/gen/ClassGenerationActionTest.java @@ -20,6 +20,7 @@ package org.apache.cayenne.gen; import java.io.*; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -333,4 +334,30 @@ public void testFileForClass() throws Exception { cgenConfiguration.setOverwrite(true); assertNull(action.openWriter(templateType)); } + + @Test + public void testDeleteFileIfChanged() throws Exception { + + TemplateType templateType = TemplateType.DATAMAP_SUPERCLASS; + String rootFolder = tempFolder.getRoot().getAbsolutePath(); + + File outFile = new File(rootFolder + "/_TestCLASS2.java"); + assertTrue(outFile.createNewFile()); + + cgenConfiguration.setSuperTemplate(outFile.getAbsolutePath()); + cgenConfiguration.setRootPath(Paths.get(rootFolder)); + cgenConfiguration.setRelPath("."); + action = new ClassGenerationAction(cgenConfiguration); + ObjEntity testEntity1 = new ObjEntity("TEST"); + testEntity1.setSuperClassName("_TestClass2"); + + action.context.put(Artifact.SUPER_PACKAGE_KEY, ""); + action.context.put(Artifact.SUPER_CLASS_KEY, "_TestClass2"); + try (Writer out = action.openWriter(templateType);){ + assertNotNull(out); + } + outFile = new File(rootFolder + "/_TestClass2.java"); + assertTrue(outFile.exists()); + assertEquals(outFile.getAbsolutePath(), rootFolder + File.separator + "_TestClass2.java"); + } } \ No newline at end of file diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractMerger.java index 0bc77db503..f54cdc780a 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/AbstractMerger.java @@ -21,20 +21,37 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.MergerToken; -import org.apache.cayenne.map.DataMap; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.function.Function; abstract class AbstractMerger implements Merger { private MergerDictionaryDiff diff; private MergerTokenFactory tokenFactory; private DbEntityDictionary originalDictionary; + private Function nameConverter; - AbstractMerger(MergerTokenFactory tokenFactory) { + AbstractMerger(MergerTokenFactory tokenFactory, Function nameConverter) { this.tokenFactory = tokenFactory; + this.nameConverter = nameConverter; + } + + /** + * @since 4.2 + * Sets function for converting string for naming. + */ + public void setNameConverter(Function nameConverter) { + this.nameConverter = nameConverter; + } + + /** + * @since 4.2 + */ + public Function getNameConverter() { + return nameConverter; } @Override diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ChainMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ChainMerger.java index 69d7b56a58..60d440b069 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ChainMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ChainMerger.java @@ -24,7 +24,6 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.MergerToken; -import org.apache.cayenne.map.DataMap; class ChainMerger extends AbstractMerger { @@ -33,7 +32,7 @@ class ChainMerger extends AbstractMerger { private final AbstractMerger parentMerger; ChainMerger(MergerTokenFactory tokenFactory, AbstractMerger merger, AbstractMerger parentMerger) { - super(tokenFactory); + super(tokenFactory, merger.getNameConverter()); this.merger = merger; this.parentMerger = parentMerger; } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DataMapMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DataMapMerger.java index bc2c8f5ce8..94583fe4ad 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DataMapMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DataMapMerger.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.EmptyValueForNullProvider; @@ -48,6 +49,7 @@ public class DataMapMerger implements Merger { private FiltersConfig filters; private DbEntityMerger dbEntityMerger; private List> mergerList = new ArrayList<>(); + private Function nameConverter; private DataMapMerger() { } @@ -81,14 +83,14 @@ private List createTokens() { } private void createDbEntityMerger(DataMap original, DataMap imported) { - dbEntityMerger = new DbEntityMerger(tokenFactory, original, imported, filters, skipPKTokens); + dbEntityMerger = new DbEntityMerger(tokenFactory, original, imported, filters, skipPKTokens, nameConverter); mergerList.add(dbEntityMerger); } private void createAttributeMerger() { ChainMerger dbAttributeMerger = new ChainMerger<>( tokenFactory, - new DbAttributeMerger(tokenFactory, valueForNull), + new DbAttributeMerger(tokenFactory, valueForNull, nameConverter), dbEntityMerger ); mergerList.add(dbAttributeMerger); @@ -97,14 +99,14 @@ private void createAttributeMerger() { private void createRelationshipMerger() { ChainMerger dbRelationshipMerger = new ChainMerger<>( tokenFactory, - new DbRelationshipMerger(tokenFactory, skipRelationshipsTokens, filters), + new DbRelationshipMerger(tokenFactory, skipRelationshipsTokens, filters, nameConverter), dbEntityMerger ); mergerList.add(dbRelationshipMerger); } private void createProcedureMerger(DataMap original, DataMap imported) { - ProcedureMerger procedureMerger = new ProcedureMerger(tokenFactory, original, imported, filters); + ProcedureMerger procedureMerger = new ProcedureMerger(tokenFactory, original, imported, filters, nameConverter); mergerList.add(procedureMerger); } @@ -112,10 +114,6 @@ public static Builder builder(MergerTokenFactory tokenFactory) { return new Builder(tokenFactory); } - public static DataMapMerger build(MergerTokenFactory tokenFactory) { - return builder(tokenFactory).build(); - } - public static class Builder { private DataMapMerger merger; @@ -157,5 +155,13 @@ public Builder filters(FiltersConfig filters) { merger.filters = Objects.requireNonNull(filters); return this; } + + /** + * @since 4.2 + */ + public Builder nameConverter(Function nameConverter) { + merger.nameConverter = Objects.requireNonNull(nameConverter); + return this; + } } } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbAttributeMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbAttributeMerger.java index 81c7f33683..7374724927 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbAttributeMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbAttributeMerger.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.token.ValueForNullProvider; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; @@ -43,8 +44,8 @@ class DbAttributeMerger extends AbstractMerger { private final ValueForNullProvider valueForNull; - DbAttributeMerger(MergerTokenFactory tokenFactory, ValueForNullProvider valueForNull) { - super(tokenFactory); + DbAttributeMerger(MergerTokenFactory tokenFactory, ValueForNullProvider valueForNull, Function nameConverter) { + super(tokenFactory, nameConverter); this.valueForNull = valueForNull; } @@ -53,6 +54,7 @@ MergerDictionaryDiff createDiff(DbEntity original, DbEntity importe return new MergerDictionaryDiff.Builder() .originalDictionary(new DbAttributeDictionary(original)) .importedDictionary(new DbAttributeDictionary(imported)) + .nameConverter(getNameConverter()) .build(); } @@ -89,7 +91,8 @@ Collection createTokensForMissingImported(DbAttribute original) { */ @Override Collection createTokensForMissingOriginal(DbAttribute imported) { - DbEntity originalDbEntity = getOriginalDictionary().getByName(imported.getEntity().getName().toUpperCase()); + String name = getNameConverter().apply(imported.getEntity().getName()); + DbEntity originalDbEntity = getOriginalDictionary().getByName(name); return Collections.singleton(getTokenFactory().createDropColumnToDb(originalDbEntity, imported)); } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbEntityMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbEntityMerger.java index 114e8e1d66..76e09f1c40 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbEntityMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbEntityMerger.java @@ -19,12 +19,14 @@ package org.apache.cayenne.dbsync.merge; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.MergerToken; @@ -44,8 +46,8 @@ class DbEntityMerger extends AbstractMerger { private DataMap importedDataMap; DbEntityMerger(MergerTokenFactory tokenFactory, DataMap original, DataMap imported, - FiltersConfig filtersConfig, boolean skipPKTokens) { - super(tokenFactory); + FiltersConfig filtersConfig, boolean skipPKTokens, Function nameConverter) { + super(tokenFactory, nameConverter); this.filtersConfig = filtersConfig; this.skipPKTokens = skipPKTokens; originalDataMap = original; @@ -63,6 +65,7 @@ MergerDictionaryDiff createDiff(DataMap original, DataMap imported) { MergerDictionaryDiff diff = new MergerDictionaryDiff.Builder() .originalDictionary(dictionary) .importedDictionary(new DbEntityDictionary(imported, null)) + .nameConverter(getNameConverter()) .build(); setOriginalDictionary(dictionary); return diff; @@ -70,11 +73,18 @@ MergerDictionaryDiff createDiff(DataMap original, DataMap imported) { /** * Generate Drop Table in DB token + * The creating entity divides into two parts because of the necessity for creating relationships after entity. + * This is caused by an unknown name the target objEntity for the relationship before all entities were created. * @param imported DbEntity not found in model but found in DB */ @Override Collection createTokensForMissingOriginal(DbEntity imported) { - return Collections.singleton(getTokenFactory().createDropTableToDb(imported)); + Collection tokens = new ArrayList<>(); + tokens.add(getTokenFactory().createDropTableToDb(imported)); + for (DbRelationship rel : imported.getRelationships()) { + tokens.add(getTokenFactory().createDropRelationshipToDb(imported, rel)); + } + return tokens; } /** @@ -118,21 +128,21 @@ private Collection checkPrimaryKeyChange(DbEntity original, DbEntit primaryKeyName = ((DetectedDbEntity) imported).getPrimaryKeyName(); } - if (upperCaseEntityNames(primaryKeyOriginal).equals(upperCaseEntityNames(primaryKeyNew))) { + if (convertNames(primaryKeyOriginal).equals(convertNames(primaryKeyNew))) { return null; } return Collections.singleton( getTokenFactory().createSetPrimaryKeyToDb( - original, primaryKeyOriginal, primaryKeyNew, primaryKeyName + original, primaryKeyOriginal, primaryKeyNew, primaryKeyName, getNameConverter() ) ); } - private Set upperCaseEntityNames(Collection attributes) { + private Set convertNames(Collection attributes) { Set names = new HashSet<>(); for (Attribute attr : attributes) { - names.add(attr.getName().toUpperCase()); + names.add(getNameConverter().apply(attr.getName())); } return names; } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbRelationshipMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbRelationshipMerger.java index f573ccf6dc..77886bcb8f 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbRelationshipMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/DbRelationshipMerger.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.MergerToken; @@ -40,8 +41,8 @@ public class DbRelationshipMerger extends AbstractMerger nameConverter) { + super(tokenFactory, nameConverter); this.skipRelationshipsTokens = skipRelationshipsTokens; this.filtersConfig = filtersConfig; } @@ -51,15 +52,18 @@ MergerDictionaryDiff createDiff(DbEntity original, DbEntity impo return new MergerDictionaryDiff.Builder() .originalDictionary(new DbRelationshipDictionary(original, filtersConfig)) .importedDictionary(new DbRelationshipDictionary(imported, filtersConfig)) + .nameConverter(getNameConverter()) .build(); } private DbEntity getOriginalSourceDbEntity(DbRelationship relationship) { - return getOriginalDictionary().getByName(relationship.getSourceEntity().getName().toUpperCase()); + String name = getNameConverter().apply(relationship.getSourceEntity().getName()); + return getOriginalDictionary().getByName(name); } private DbEntity getOriginalTargetDbEntity(DbRelationship relationship) { - return getOriginalDictionary().getByName(relationship.getTargetEntityName().toUpperCase()); + String name = getNameConverter().apply(relationship.getTargetEntity().getName()); + return getOriginalDictionary().getByName(name); } /** @@ -121,19 +125,23 @@ Collection createTokensForSame(MergerDiffPair same) * case insensitive search for a {@link DbAttribute} in a {@link DbEntity} * by name */ - private DbAttribute findDbAttribute(DbEntity entity, String caseInsensitiveName) { + private DbAttribute findDbAttribute(DbEntity entity, String name) { if (entity == null) { return null; } for (DbAttribute a : entity.getAttributes()) { - if (a.getName().equalsIgnoreCase(caseInsensitiveName)) { + if (equalsConvertedNames(a.getName(), name)) { return a; } } return null; } + private boolean equalsConvertedNames(String name1, String name2) { + return getNameConverter().apply(name1).equals(getNameConverter().apply(name2)); + } + @Override public List createMergeTokens() { throw new UnsupportedOperationException(); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionary.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionary.java index 5280c18ddf..f420b76cf0 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionary.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionary.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.function.Function; abstract class MergerDictionary { @@ -30,9 +31,9 @@ abstract class MergerDictionary { MergerDictionary() { } - void init() { + void init(Function nameConverter) { for(T entity : getAll()) { - String name = getName(entity).toUpperCase(); + String name = nameConverter.apply(getName(entity)); dictionary.put(name, entity); } } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionaryDiff.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionaryDiff.java index bfef806de7..c526192f5f 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionaryDiff.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/MergerDictionaryDiff.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; class MergerDictionaryDiff { @@ -51,6 +52,7 @@ static class Builder { private MergerDictionary originalDictionary; private MergerDictionary importedDictionary; private Set sameNames = new HashSet<>(); + private Function nameConverter; Builder() { diff = new MergerDictionaryDiff<>(); @@ -66,13 +68,21 @@ Builder importedDictionary(MergerDictionary dictionary) { return this; } + /** + * @since 4.2 + */ + Builder nameConverter(Function nameConverter) { + this.nameConverter = nameConverter; + return this; + } + MergerDictionaryDiff build() { if(originalDictionary == null || importedDictionary == null) { throw new IllegalArgumentException("Dictionaries not set"); } - originalDictionary.init(); - importedDictionary.init(); + originalDictionary.init(nameConverter); + importedDictionary.init(nameConverter); diff.same = buildSame(); diff.missing = buildMissing(); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProcedureMerger.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProcedureMerger.java index 7bc53627e1..9885a2d44c 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProcedureMerger.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/ProcedureMerger.java @@ -23,6 +23,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; import org.apache.cayenne.dbsync.merge.token.MergerToken; @@ -41,8 +42,8 @@ public class ProcedureMerger extends AbstractMerger { private DataMap importedDataMap; ProcedureMerger(MergerTokenFactory tokenFactory, DataMap original, DataMap imported, - FiltersConfig filtersConfig) { - super(tokenFactory); + FiltersConfig filtersConfig, Function nameConverter) { + super(tokenFactory, nameConverter); this.filtersConfig = filtersConfig; originalDataMap = original; importedDataMap = imported; @@ -58,6 +59,7 @@ MergerDictionaryDiff createDiff(DataMap original, DataMap imported) { return new MergerDictionaryDiff.Builder() .originalDictionary(new ProcedureDictionary(original, filtersConfig)) .importedDictionary(new ProcedureDictionary(imported, filtersConfig)) + .nameConverter(getNameConverter()) .build(); } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/context/EntityMergeSupport.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/context/EntityMergeSupport.java index 46be314e08..28a1bd1dbf 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/context/EntityMergeSupport.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/context/EntityMergeSupport.java @@ -31,7 +31,6 @@ import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.DbJoin; import org.apache.cayenne.map.DbRelationship; -import org.apache.cayenne.map.Entity; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.map.ObjRelationship; @@ -133,12 +132,16 @@ public boolean synchronizeWithDbEntities(Iterable objEntities) { } /** - * Updates ObjEntity attributes and relationships based on the current state - * of its DbEntity. + * @since 4.2 + * + * Updates ObjEntity attributes and relationships(if @param synchronizeRelationship is true) based on the current + * state of its DbEntity. + * + * @param synchronizeRelationship is boolean. If it's true then relationship will be added. * * @return true if the ObjEntity has changed as a result of synchronization. */ - public boolean synchronizeWithDbEntity(ObjEntity entity) { + public boolean synchronizeWithDbEntity(ObjEntity entity, boolean synchronizeRelationship) { if (entity == null) { return false; @@ -156,11 +159,24 @@ public boolean synchronizeWithDbEntity(ObjEntity entity) { } changed |= addMissingAttributes(entity); - changed |= addMissingRelationships(entity); + if (synchronizeRelationship) { + changed |= addMissingRelationships(entity); + } return changed; } + /** + * Updates ObjEntity attributes based on the current state + * of its DbEntity. + * Method synchronizes objEntity entirely with relationships. + * + * @return true if the ObjEntity has changed as a result of synchronization. + */ + public boolean synchronizeWithDbEntity(ObjEntity entity) { + return synchronizeWithDbEntity(entity, true); + } + /** * @since 4.0 */ @@ -254,6 +270,8 @@ private boolean addMissingAttributes(ObjEntity entity) { return changed; } + // When method creates relationships all entities already exist. + // Token for creating relationships execute after creating entity. private void addMissingRelationship(ObjEntity entity, DbRelationship dbRelationship) { // getting DataMap from DbRelationship's source entity. This is the only object in our arguments that @@ -262,22 +280,13 @@ private void addMissingRelationship(ObjEntity entity, DbRelationship dbRelations DbEntity targetEntity = dbRelationship.getTargetEntity(); Collection mappedObjEntities = dataMap.getMappedEntities(targetEntity); - if (mappedObjEntities.isEmpty()) { - if (targetEntity == null) { - targetEntity = new DbEntity(dbRelationship.getTargetEntityName()); - } - - if (dbRelationship.getTargetEntityName() != null) { - boolean needGeneratedEntity = createObjRelationship(entity, dbRelationship, nameGenerator.objEntityName(targetEntity)); - if (needGeneratedEntity) { - LOGGER.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName()); - LOGGER.warn("Db Relationship (" + dbRelationship + ") will have GUESSED Obj Relationship reflection. "); - } - } - } else { - for (Entity mappedTarget : mappedObjEntities) { + if (!mappedObjEntities.isEmpty()) { + for (ObjEntity mappedTarget : mappedObjEntities) { createObjRelationship(entity, dbRelationship, mappedTarget.getName()); } + } else { + LOGGER.warn("Can't find ObjEntity for " + dbRelationship.getTargetEntityName()); + LOGGER.warn("Db Relationship (" + dbRelationship + ") can't be created. "); } } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java index b3b6e13170..046d3d67cd 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java @@ -19,6 +19,7 @@ package org.apache.cayenne.dbsync.merge.factory; import java.util.Collection; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.token.MergerToken; import org.apache.cayenne.dbsync.merge.token.ValueForNullProvider; @@ -185,12 +186,14 @@ public MergerToken createSetPrimaryKeyToDb( DbEntity entity, Collection primaryKeyOriginal, Collection primaryKeyNew, - String detectedPrimaryKeyName) { + String detectedPrimaryKeyName, + Function nameConverter) { return new SetPrimaryKeyToDb( entity, primaryKeyOriginal, primaryKeyNew, - detectedPrimaryKeyName); + detectedPrimaryKeyName, + nameConverter); } @Override @@ -198,12 +201,13 @@ public MergerToken createSetPrimaryKeyToModel( DbEntity entity, Collection primaryKeyOriginal, Collection primaryKeyNew, - String detectedPrimaryKeyName) { + String detectedPrimaryKeyName, Function nameConverter) { return new SetPrimaryKeyToModel( entity, primaryKeyOriginal, primaryKeyNew, - detectedPrimaryKeyName); + detectedPrimaryKeyName, + nameConverter); } @Override diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java index 3b0b85bc10..8920617086 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java @@ -32,6 +32,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; /** * @since 3.0 @@ -69,8 +70,8 @@ public List createSql(DbAdapter adapter) { @Override public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection primaryKeyOriginal, - Collection primaryKeyNew, String detectedPrimaryKeyName) { - return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) { + Collection primaryKeyNew, String detectedPrimaryKeyName, Function nameConverter) { + return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName, nameConverter) { @Override protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List sqls) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java index a482f055a1..6472753f96 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java @@ -31,6 +31,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; public class HSQLMergerTokenFactory extends DefaultMergerTokenFactory { @@ -68,8 +69,8 @@ public List createSql(DbAdapter adapter) { @Override public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection primaryKeyOriginal, - Collection primaryKeyNew, String detectedPrimaryKeyName) { - return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) { + Collection primaryKeyNew, String detectedPrimaryKeyName, Function nameConverter) { + return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName, nameConverter) { @Override protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List sqls) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java index 757711a0af..1e908d8e47 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java @@ -19,6 +19,7 @@ package org.apache.cayenne.dbsync.merge.factory; import java.util.Collection; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.token.MergerToken; import org.apache.cayenne.dbsync.merge.token.ValueForNullProvider; @@ -87,13 +88,15 @@ MergerToken createSetPrimaryKeyToDb( DbEntity entity, Collection primaryKeyOriginal, Collection primaryKeyNew, - String detectedPrimaryKeyName); + String detectedPrimaryKeyName, + Function nameConverter); MergerToken createSetPrimaryKeyToModel( DbEntity entity, Collection primaryKeyOriginal, Collection primaryKeyNew, - String detectedPrimaryKeyName); + String detectedPrimaryKeyName, + Function nameConverter); MergerToken createSetGeneratedFlagToDb(DbEntity entity, DbAttribute column, boolean isGenerated); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java index 82b5d76416..c9482a65c8 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java @@ -35,6 +35,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Function; public class MySQLMergerTokenFactory extends DefaultMergerTokenFactory { @@ -136,12 +137,14 @@ public MergerToken createSetPrimaryKeyToDb( DbEntity entity, Collection primaryKeyOriginal, Collection primaryKeyNew, - String detectedPrimaryKeyName) { + String detectedPrimaryKeyName, + Function nameConverter) { return new SetPrimaryKeyToDb( entity, primaryKeyOriginal, primaryKeyNew, - detectedPrimaryKeyName) { + detectedPrimaryKeyName, + nameConverter) { @Override protected void appendDropOriginalPrimaryKeySQL( diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/DropRelationshipToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/DropRelationshipToDb.java index dd91db46e4..3c03324e95 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/DropRelationshipToDb.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/DropRelationshipToDb.java @@ -54,7 +54,8 @@ public List createSql(DbAdapter adapter) { QuotingStrategy context = adapter.getQuotingStrategy(); return Collections.singletonList( - "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + getFkName()); + "ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + " DROP CONSTRAINT " + + context.quotedIdentifier(getEntity().getDataMap(), getFkName())); } public MergerToken createReverse(MergerTokenFactory factory) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDb.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDb.java index addb9b4f85..8f9779aaca 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDb.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDb.java @@ -30,20 +30,23 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; +import java.util.function.Function; public class SetPrimaryKeyToDb extends AbstractToDbToken.Entity { private Collection primaryKeyOriginal; private Collection primaryKeyNew; private String detectedPrimaryKeyName; + private Function nameConverter; public SetPrimaryKeyToDb(DbEntity entity, Collection primaryKeyOriginal, - Collection primaryKeyNew, String detectedPrimaryKeyName) { + Collection primaryKeyNew, String detectedPrimaryKeyName, Function nameConverter) { super("Set Primary Key", 100, entity); this.primaryKeyOriginal = primaryKeyOriginal; this.primaryKeyNew = primaryKeyNew; this.detectedPrimaryKeyName = detectedPrimaryKeyName; + this.nameConverter = nameConverter; } @Override @@ -60,8 +63,10 @@ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List s if (detectedPrimaryKeyName == null) { return; } - sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()) - + " DROP CONSTRAINT " + detectedPrimaryKeyName); + + QuotingStrategy context = adapter.getQuotingStrategy(); + sqls.add("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity()) + + " DROP CONSTRAINT " + context.quotedIdentifier(getEntity().getDataMap(), detectedPrimaryKeyName)); } protected void appendAddNewPrimaryKeySQL(DbAdapter adapter, List sqls) { @@ -84,6 +89,6 @@ protected void appendAddNewPrimaryKeySQL(DbAdapter adapter, List sqls) { @Override public MergerToken createReverse(MergerTokenFactory factory) { return factory.createSetPrimaryKeyToModel(getEntity(), primaryKeyNew, primaryKeyOriginal, - detectedPrimaryKeyName); + detectedPrimaryKeyName, nameConverter); } } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModel.java index 154d90d919..30564ced6f 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModel.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModel.java @@ -28,7 +28,8 @@ import org.apache.cayenne.map.ObjEntity; /** - * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap} + * A {@link MergerToken} to add a {@link DbEntity} to a {@link DataMap}. + * Token creates a entity without relationships. */ public class CreateTableToModel extends AbstractToModelToken.Entity { @@ -88,7 +89,8 @@ public void execute(MergerContext context) { map.addObjEntity(objEntity); // presumably there are no other ObjEntities pointing to this DbEntity, so syncing just this one... - context.getEntityMergeSupport().synchronizeWithDbEntity(objEntity); + // ObjEntity is synchronized without relationships it will be created with token AddRelationshipToModel + context.getEntityMergeSupport().synchronizeWithDbEntity(objEntity, false); context.getDelegate().dbEntityAdded(getEntity()); context.getDelegate().objEntityAdded(objEntity); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/SetPrimaryKeyToModel.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/SetPrimaryKeyToModel.java index ea47bf09b8..80bbea5aa6 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/SetPrimaryKeyToModel.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/token/model/SetPrimaryKeyToModel.java @@ -29,6 +29,7 @@ import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.function.Function; public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity { @@ -36,18 +37,20 @@ public class SetPrimaryKeyToModel extends AbstractToModelToken.Entity { private Collection primaryKeyNew; private String detectedPrimaryKeyName; private Set primaryKeyNewAttributeNames = new HashSet<>(); + private Function nameConverter; public SetPrimaryKeyToModel(DbEntity entity, Collection primaryKeyOriginal, - Collection primaryKeyNew, String detectedPrimaryKeyName) { + Collection primaryKeyNew, String detectedPrimaryKeyName, Function nameConverter) { super("Set Primary Key", 105, entity); this.primaryKeyOriginal = primaryKeyOriginal; this.primaryKeyNew = primaryKeyNew; this.detectedPrimaryKeyName = detectedPrimaryKeyName; + this.nameConverter = nameConverter; for (DbAttribute attr : primaryKeyNew) { - primaryKeyNewAttributeNames.add(attr.getName().toUpperCase()); + primaryKeyNewAttributeNames.add(this.nameConverter.apply(attr.getName())); } } @@ -57,7 +60,8 @@ public MergerToken createReverse(MergerTokenFactory factory) { getEntity(), primaryKeyNew, primaryKeyOriginal, - detectedPrimaryKeyName); + detectedPrimaryKeyName, + nameConverter); } @Override @@ -67,9 +71,7 @@ public void execute(MergerContext mergerContext) { for (DbAttribute attr : e.getAttributes()) { boolean wasPrimaryKey = attr.isPrimaryKey(); - boolean willBePrimaryKey = primaryKeyNewAttributeNames.contains(attr - .getName() - .toUpperCase()); + boolean willBePrimaryKey = primaryKeyNewAttributeNames.contains(nameConverter.apply(attr.getName())); if (wasPrimaryKey != willBePrimaryKey) { attr.setPrimaryKey(willBePrimaryKey); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java index 6138898e97..3ddb1001f3 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/naming/DeduplicationVisitor.java @@ -36,6 +36,7 @@ import org.apache.cayenne.map.QueryDescriptor; import java.util.Objects; +import java.util.Set; import java.util.function.Predicate; /** @@ -92,7 +93,15 @@ public String visitDataMap(DataMap dataMap) { @Override public String visitObjEntity(ObjEntity entity) { - return resolve(name -> ((DataMap) parent).getObjEntity(name) != null); + return resolve(name -> { + Set keys= ((DataMap) parent).getObjEntityMap().keySet(); + for(String key: keys){ + if (name.equalsIgnoreCase(key)){ + return true; + } + } + return false; + }); } @Override diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java index 6f142a97e4..d51a5d35e9 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DbImportConfiguration.java @@ -55,6 +55,7 @@ public class DbImportConfiguration { private String meaningfulPkTables; private String adapter; private boolean usePrimitives; + private boolean useCaseSensitiveNaming; private boolean useJava7Types; private Logger logger; private String namingStrategy; @@ -148,6 +149,20 @@ public void setUsePrimitives(boolean usePrimitives) { this.usePrimitives = usePrimitives; } + /** + * @since 4.2 + */ + public boolean isUseCaseSensitiveNaming() { + return useCaseSensitiveNaming; + } + + /** + * @since 4.2 + */ + public void setUseCaseSensitiveNaming(boolean useCaseSensitiveNaming) { + this.useCaseSensitiveNaming = useCaseSensitiveNaming; + } + public boolean isUseJava7Types() { return useJava7Types; } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java index 2192b54435..d1cfdd684d 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportAction.java @@ -29,6 +29,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.configuration.ConfigurationNode; @@ -222,6 +223,7 @@ protected DataMap loadDataMap(DbImportConfiguration config) throws Exception { .filters(loaderConfig.getFiltersConfig()) .skipPKTokens(loaderConfig.isSkipPrimaryKeyLoading()) .skipRelationshipsTokens(loaderConfig.isSkipRelationshipsLoading()) + .nameConverter(createNameConverter(config.isUseCaseSensitiveNaming())) .build() .createMergeTokens(targetDataMap, sourceDataMap); tokens = log(sort(reverse(mergerTokenFactory, tokens))); @@ -250,6 +252,7 @@ private void putReverseEngineeringToConfig(ReverseEngineering reverseEngineering config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema()); config.setDefaultPackage(reverseEngineering.getDefaultPackage()); config.setUsePrimitives(reverseEngineering.isUsePrimitives()); + config.setUseCaseSensitiveNaming(reverseEngineering.isUseCaseSensitiveNaming()); config.setUseJava7Types(reverseEngineering.isUseJava7Types()); } @@ -514,6 +517,13 @@ protected DbLoader createDbLoader(DbAdapter adapter, Connection connection, DbIm return new DbLoader(adapter, connection, config.getDbLoaderConfig(), config.createLoaderDelegate(), - config.createNameGenerator()); + config.createNameGenerator(), + createNameConverter(config.isUseCaseSensitiveNaming())); + } + + private Function createNameConverter(boolean useCaseSensitiveNaming) { + return useCaseSensitiveNaming + ? Function.identity() + : (String::toUpperCase); } } \ No newline at end of file diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java index e1eb23c5dc..95dd41c8cb 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbimport/ReverseEngineering.java @@ -103,6 +103,12 @@ public class ReverseEngineering extends SchemaContainer implements Serializable, */ private boolean usePrimitives = true; + /** + *

If true, would use case sensitive naming.

+ *

Default is "false", i.e. case insensitive naming will be used.

+ */ + private boolean useCaseSensitiveNaming = false; + /** * Use old Java 7 date types */ @@ -138,6 +144,7 @@ public ReverseEngineering(ReverseEngineering original) { this.setForceDataMapCatalog(original.isForceDataMapCatalog()); this.setUseJava7Types(original.isUseJava7Types()); this.setUsePrimitives(original.isUsePrimitives()); + this.setUseCaseSensitiveNaming(original.isUseCaseSensitiveNaming()); this.setTableTypes(Arrays.asList(original.getTableTypes())); this.setName(original.getName()); for (Catalog catalog : original.getCatalogs()) { @@ -223,6 +230,9 @@ public String toString() { if (usePrimitives) { res.append("\n Use primitives"); } + if (useCaseSensitiveNaming) { + res.append("\n Use case sensitive naming"); + } if (useJava7Types) { res.append("\n Use Java 7 types"); } @@ -257,6 +267,13 @@ public boolean isUsePrimitives() { return usePrimitives; } + /** + * @since 4.2 + */ + public boolean isUseCaseSensitiveNaming() { + return useCaseSensitiveNaming; + } + public boolean isUseJava7Types() { return useJava7Types; } @@ -289,6 +306,13 @@ public void setUsePrimitives(boolean usePrimitives) { this.usePrimitives = usePrimitives; } + /** + * @since 4.2 + */ + public void setUseCaseSensitiveNaming(boolean useCaseSensitiveNaming) { + this.useCaseSensitiveNaming = useCaseSensitiveNaming; + } + public void setUseJava7Types(boolean useJava7Types) { this.useJava7Types = useJava7Types; } @@ -323,7 +347,7 @@ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) { .simpleTag("stripFromTableNames", this.getStripFromTableNames()) .simpleTag("useJava7Types", Boolean.toString(this.isUseJava7Types())) .simpleTag("usePrimitives", Boolean.toString(this.isUsePrimitives())) + .simpleTag("useCaseSensitiveNaming", Boolean.toString(this.isUseCaseSensitiveNaming())) .end(); } - } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoadDataStore.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoadDataStore.java index c6513d7b10..4f0692a8a9 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoadDataStore.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoadDataStore.java @@ -23,6 +23,7 @@ import java.util.Map; import java.util.Set; import java.util.TreeSet; +import java.util.function.Function; import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbEntity; @@ -43,15 +44,17 @@ public class DbLoadDataStore extends DataMap { private Map> exportedKeys = new HashMap<>(); - private Map upperCaseNames = new HashMap<>(); + private Map names = new HashMap<>(); + private Function nameConverter; - DbLoadDataStore() { + DbLoadDataStore(Function nameConverter) { super("__generated_by_dbloader__"); + this.nameConverter = nameConverter; } @Override public DbEntity getDbEntity(String dbEntityName) { - return upperCaseNames.get(dbEntityName.toUpperCase()); + return names.get(nameConverter.apply(dbEntityName)); } @Override @@ -60,7 +63,7 @@ public void addDbEntity(DbEntity entity) { throw new IllegalArgumentException("Only DetectedDbEntity can be inserted in this map"); } super.addDbEntity(entity); - upperCaseNames.put(entity.getName().toUpperCase(), entity); + names.put(nameConverter.apply(entity.getName()), entity); } DbEntity addDbEntitySafe(DbEntity entity) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java index 2ce236079e..551f2dc171 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoader.java @@ -29,6 +29,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.function.Function; /** * Loads DB schema into a DataMap, creating DbEntities and Procedures. Consists of a list of specialized loaders that @@ -46,15 +47,16 @@ public class DbLoader { private final DbLoaderConfiguration config; private final DbLoaderDelegate delegate; private final ObjectNameGenerator nameGenerator; + private final Function nameConverter; public DbLoader(DbAdapter adapter, Connection connection, DbLoaderConfiguration config, - DbLoaderDelegate delegate, ObjectNameGenerator nameGenerator) { + DbLoaderDelegate delegate, ObjectNameGenerator nameGenerator, Function nameConverter) { this.adapter = Objects.requireNonNull(adapter); this.connection = Objects.requireNonNull(connection); this.config = Objects.requireNonNull(config); this.nameGenerator = Objects.requireNonNull(nameGenerator); this.delegate = delegate == null ? new DefaultDbLoaderDelegate() : delegate; - + this.nameConverter = Objects.requireNonNull(nameConverter); createLoaders(); } @@ -75,7 +77,7 @@ private void createLoaders() { * @return new DataMap with data loaded from DB */ public DataMap load() throws SQLException { - DbLoadDataStore loadedData = new DbLoadDataStore(); + DbLoadDataStore loadedData = new DbLoadDataStore(nameConverter); DatabaseMetaData metaData = connection.getMetaData(); for(AbstractLoader loader : loaders) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java index aca90baf3f..f9b91fa11c 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilder.java @@ -159,7 +159,7 @@ private SchemaFilter[] transformSchemas(Collection schemas) { private SortedSet transformExcludeTable(Collection excludeTables) { SortedSet res = new TreeSet<>(PatternFilter.PATTERN_COMPARATOR); for (ExcludeTable exclude : excludeTables) { - res.add(PatternFilter.pattern(exclude.getPattern())); + res.add(PatternFilter.pattern(exclude.getPattern(), engineering.isUseCaseSensitiveNaming())); } return res; } @@ -170,6 +170,7 @@ private SortedSet transformIncludeTable(Collection transformIncludeTable(Collection include, Collection exclude) { - PatternFilter filter = new PatternFilter(); + PatternFilter filter = new PatternFilter(engineering.isUseCaseSensitiveNaming()); for (PatternParam patternParam : include) { filter.include(patternParam.getPattern()); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java index 35d504f5ba..7e62ea696c 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/IncludeTableFilter.java @@ -28,26 +28,29 @@ public class IncludeTableFilter implements Comparable { public final PatternFilter columnsFilter; + public final boolean useCaseSensitiveNaming; + /** * @since 4.1 */ public final PatternFilter relationshipFilter; - public IncludeTableFilter(String pattern) { - this(pattern, PatternFilter.INCLUDE_EVERYTHING, PatternFilter.INCLUDE_EVERYTHING); + public IncludeTableFilter(String pattern, boolean useCaseSensitiveNaming) { + this(pattern, PatternFilter.INCLUDE_EVERYTHING, PatternFilter.INCLUDE_EVERYTHING, useCaseSensitiveNaming); } - public IncludeTableFilter(String pattern, PatternFilter columnsFilter) { - this(pattern, columnsFilter, PatternFilter.INCLUDE_EVERYTHING); + public IncludeTableFilter(String pattern, PatternFilter columnsFilter, boolean useCaseSensitiveNaming) { + this(pattern, columnsFilter, PatternFilter.INCLUDE_EVERYTHING, useCaseSensitiveNaming); } /** * @since 4.1 */ - public IncludeTableFilter(String pattern, PatternFilter columnsFilter, PatternFilter relationshipFilter) { - this.pattern = PatternFilter.pattern(pattern); + public IncludeTableFilter(String pattern, PatternFilter columnsFilter, PatternFilter relationshipFilter, boolean useCaseSensitiveNaming) { + this.pattern = PatternFilter.pattern(pattern, useCaseSensitiveNaming); this.columnsFilter = columnsFilter; this.relationshipFilter = relationshipFilter; + this.useCaseSensitiveNaming = useCaseSensitiveNaming; } public boolean isIncludeColumn (String name) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java index c06861903a..8ac59cb6d2 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilter.java @@ -30,7 +30,7 @@ */ public class PatternFilter { - public static final PatternFilter INCLUDE_EVERYTHING = new PatternFilter() { + public static final PatternFilter INCLUDE_EVERYTHING = new PatternFilter(true) { @Override public boolean isIncluded(String obj) { @@ -43,7 +43,7 @@ protected StringBuilder toString(StringBuilder res) { } }; - public static final PatternFilter INCLUDE_NOTHING = new PatternFilter() { + public static final PatternFilter INCLUDE_NOTHING = new PatternFilter(true) { @Override public boolean isIncluded(String obj) { return false; @@ -65,10 +65,12 @@ protected StringBuilder toString(StringBuilder res) { private final SortedSet includes; private final SortedSet excludes; + private boolean useCaseSensitiveNaming; - public PatternFilter() { + public PatternFilter(boolean useCaseSensitiveNaming) { this.includes = new TreeSet<>(PATTERN_COMPARATOR); this.excludes = new TreeSet<>(PATTERN_COMPARATOR); + this.useCaseSensitiveNaming = useCaseSensitiveNaming; } public SortedSet getIncludes() { @@ -87,19 +89,21 @@ public PatternFilter exclude(Pattern p) { return this; } - public static Pattern pattern(String pattern) { + public static Pattern pattern(String pattern, boolean useCaseSensitiveNaming) { if (pattern == null) { return null; } - return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); + return useCaseSensitiveNaming + ? Pattern.compile(pattern) + : Pattern.compile(pattern, Pattern.CASE_INSENSITIVE); } public PatternFilter include(String p) { - return include(pattern(p)); + return include(pattern(p, useCaseSensitiveNaming)); } public PatternFilter exclude(String p) { - return exclude(pattern(p)); + return exclude(pattern(p, useCaseSensitiveNaming)); } public boolean isIncluded(String obj) { diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java index c403ba0ef0..c26f125873 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/filters/TableFilter.java @@ -93,16 +93,19 @@ public SortedSet getIncludes() { return includes; } - public static TableFilter include(String tablePattern) { + public static TableFilter include(String tablePattern, boolean useCaseSensitiveNaming) { TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter(tablePattern == null ? null : tablePattern.replaceAll("%", ".*"))); + includes.add(new IncludeTableFilter(tablePattern == null ? null : tablePattern.replaceAll("%", ".*"), useCaseSensitiveNaming)); return new TableFilter(includes, new TreeSet<>()); } + /** + * useCaseSensitiveNaming always is true because method creates filter that includes everything. + */ public static TableFilter everything() { TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter(null)); + includes.add(new IncludeTableFilter(null, true)); return new TableFilter(includes, new TreeSet<>()); } diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java index e9921b5158..58757bba03 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/xml/ConfigHandler.java @@ -52,6 +52,7 @@ class ConfigHandler extends NamespaceAwareNestedTagHandler { private static final String STRIP_FROM_TABLE_NAMES_TAG = "stripFromTableNames"; private static final String USE_JAVA7_TYPES_TAG = "useJava7Types"; private static final String USE_PRIMITIVES_TAG = "usePrimitives"; + private static final String USE_CASE_SENSITIVE_NAMING_TAG = "useCaseSensitiveNaming"; private static final String INCLUDE_TABLE_TAG = "includeTable"; private static final String EXCLUDE_TABLE_TAG = "excludeTable"; private static final String INCLUDE_COLUMN_TAG = "includeColumn"; @@ -135,6 +136,9 @@ protected void processCharData(String localName, String data) { case USE_PRIMITIVES_TAG: createUsePrimitives(data); break; + case USE_CASE_SENSITIVE_NAMING_TAG: + createUseCaseSensitiveNaming(data); + break; case EXCLUDE_TABLE_TAG: createExcludeTable(data); break; @@ -217,6 +221,20 @@ private void createUsePrimitives(String usePrimitives) { } } + private void createUseCaseSensitiveNaming(String useCaseSesitiveNaming) { + if (useCaseSesitiveNaming.trim().length() == 0) { + return; + } + + if (configuration != null) { + if (useCaseSesitiveNaming.equals(TRUE)) { + configuration.setUseCaseSensitiveNaming(true); + } else { + configuration.setUseCaseSensitiveNaming(false); + } + } + } + private void createUseJava7Types(String useJava7Types) { if (useJava7Types.trim().length() == 0) { return; diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CheckTypeTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CheckTypeTest.java index 387d2ab1b6..b407ac4d6b 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CheckTypeTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/CheckTypeTest.java @@ -59,7 +59,7 @@ public void setUp(){ mergerTokenFactory = new MySQLMergerTokenFactory(); diffPair = new MergerDiffPair<>(original, imported); - dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null); + dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null, String::toUpperCase); } @Test @@ -104,7 +104,7 @@ public void testCheckBooleanBitTypePostgres() { mergerTokenFactory = new PostgresMergerTokenFactory(); - dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null); + dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null, String::toUpperCase); Collection mergerTokens = dbAttributeMerger.createTokensForSame(diffPair); assertEquals(1, mergerTokens.size()); @@ -189,7 +189,7 @@ public void testCheckTypeWithoutChanges() { diffPair = new MergerDiffPair<>(original, imported); - dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null); + dbAttributeMerger = new DbAttributeMerger(mergerTokenFactory, null, String::toUpperCase); Collection mergerTokens = dbAttributeMerger.createTokensForSame(diffPair); assertEquals(0, mergerTokens.size()); } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DataMapMergerTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DataMapMergerTest.java index 4f14d81433..af19a8cb40 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DataMapMergerTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DataMapMergerTest.java @@ -18,7 +18,10 @@ ****************************************************************/ package org.apache.cayenne.dbsync.merge; +import java.util.HashSet; import java.util.List; +import java.util.Set; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.builders.DbEntityBuilder; import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory; @@ -27,6 +30,7 @@ import org.apache.cayenne.dbsync.reverse.filters.FiltersConfig; import org.apache.cayenne.dbsync.reverse.filters.PatternFilter; import org.apache.cayenne.map.DataMap; +import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.ProcedureParameter; import org.junit.Test; @@ -64,6 +68,30 @@ public void testAddTable() throws Exception { tokens.get(0).getTokenValue()); } + @Test + public void testAddTableWithSameNameInDifferentCapitalization() throws Exception { + DbEntityBuilder dbEntity = + dbEntity("table1").attributes( + dbAttr("attr01").typeInt() + ); + + DbEntityBuilder dbEntity1 = + dbEntity("Table1").attributes( + dbAttr("attr01").typeInt() + ); + + DataMap existing = dataMap().with(dbEntity,dbEntity1).build(); + DataMap db = dataMap().build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(2, tokens.size()); + assertEquals(factory().createCreateTableToDb(dbEntity.build()).getTokenValue(), + tokens.get(0).getTokenValue()); + assertEquals(factory().createCreateTableToDb(dbEntity1.build()).getTokenValue(), + tokens.get(1).getTokenValue()); + } + @Test public void testRemoveTable() throws Exception { DataMap existing = dataMap().build(); @@ -79,6 +107,32 @@ public void testRemoveTable() throws Exception { tokens.get(0).getTokenValue()); } + @Test + public void testRemoveTableWithSameNameInDifferentCapitalization() throws Exception { + DataMap existing = dataMap().build(); + + DbEntityBuilder dbEntity = + dbEntity("table1").attributes( + dbAttr("attr01").typeInt() + ); + + DbEntityBuilder dbEntity1 = + dbEntity("Table1").attributes( + dbAttr("attr01").typeInt() + ); + + DataMap db = dataMap().with( + dbEntity, dbEntity1).build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(2, tokens.size()); + assertEquals(factory().createDropTableToDb(db.getDbEntity("table1")).getTokenValue(), + tokens.get(0).getTokenValue()); + assertEquals(factory().createDropTableToDb(db.getDbEntity("Table1")).getTokenValue(), + tokens.get(1).getTokenValue()); + } + @Test public void testAddColumn() throws Exception { DataMap existing = dataMap().with( @@ -101,6 +155,33 @@ public void testAddColumn() throws Exception { tokens.get(0).getTokenValue()); } + @Test + public void testChangeColumnNameWithSameNameInDifferentCapitalization() throws Exception { + DataMap existing = dataMap().with( + dbEntity("table1").attributes( + dbAttr("Attr01").typeInt(), + dbAttr("attr02").typeInt() + )).build(); + + DataMap db = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt() + )).build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(3, tokens.size()); + + DbEntity entity = existing.getDbEntity("table1"); + DbEntity entity1 = db.getDbEntity("table1"); + assertEquals(factory().createDropColumnToDb(entity, entity1.getAttribute("attr01")).getTokenValue(), + tokens.get(0).getTokenValue()); + assertEquals(factory().createAddColumnToDb(entity, entity.getAttribute("Attr01")).getTokenValue(), + tokens.get(1).getTokenValue()); + assertEquals(factory().createAddColumnToDb(entity, entity.getAttribute("attr02")).getTokenValue(), + tokens.get(2).getTokenValue()); + } + @Test public void testChangeColumnTypeSimple() throws Exception { DataMap existing = dataMap().with( @@ -376,6 +457,79 @@ public void testAttributeNameUppercaseRelationship() throws Exception { assertEquals(0, tokens.size()); } + @Test + public void testAttributeNameCaseSensitiveNaming() throws Exception { + DataMap existing = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt(), + dbAttr("attr02").typeInt()), + + dbEntity("table2").attributes( + dbAttr("attr01").typeInt().primaryKey(), + dbAttr("attr02").typeInt().primaryKey()) + ).build(); + + DataMap db = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt(), + dbAttr("attr02").typeInt()), + + dbEntity("table2").attributes( + dbAttr("attr01").typeInt(), + dbAttr("attr02").typeInt(), + dbAttr("Attr01").typeInt().primaryKey()) + ).build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(2, tokens.size()); + + DbEntity entity = existing.getDbEntity("table2"); + assertEquals(factory().createAddColumnToDb(entity, dbAttr("Attr01").typeInt().primaryKey().build()).getTokenValue(), + tokens.get(0).getTokenValue()); + Set newPkAttribute = new HashSet<>(); + newPkAttribute.add(dbAttr("Attr01").typeInt().primaryKey().build()); + assertEquals(factory().createSetPrimaryKeyToDb(entity, new HashSet<>(), newPkAttribute, "Attr01", Function.identity()).getTokenValue(), + tokens.get(1).getTokenValue()); + } + + @Test + public void testAttributeNameUppercaseRelationshipCaseSensitiveNaming() throws Exception { + DataMap existing = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt(), + dbAttr("attr02").typeInt()), + + dbEntity("table2").attributes( + dbAttr("attr01").typeInt().primaryKey(), + dbAttr("Attr01").typeInt().primaryKey()) + ).join("rel", "table1.attr01", "table2.attr01") + .build(); + + DataMap db = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt(), + dbAttr("attr02").typeInt()), + + dbEntity("table2").attributes( + dbAttr("attr01").typeInt().primaryKey(), + dbAttr("Attr01").typeInt().primaryKey()) + ).join("rel", "table1.attr01", "table2.Attr01") + .build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(2, tokens.size()); + + DbEntity entity = existing.getDbEntity("table1"); + assertEquals(factory().createDropRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(), + tokens.get(0).getTokenValue()); + + entity = db.getDbEntity("table1"); + assertEquals(factory().createAddRelationshipToDb(entity, entity.getRelationship("rel")).getTokenValue(), + tokens.get(0).getTokenValue()); + } + @Test public void testRemoveRelationship() throws Exception { DataMap existing = dataMap().with( @@ -432,6 +586,28 @@ public void testRemoveColumn() throws Exception { tokens.get(0).getTokenValue()); } + @Test + public void testRemoveColumnCaseSensitiveNaming() throws Exception { + DataMap existing = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt() + )).build(); + + DataMap db = dataMap().with( + dbEntity("table1").attributes( + dbAttr("attr01").typeInt(), + dbAttr("Attr01").typeInt() + )).build(); + + List tokens = dbMerger(Function.identity()).createMergeTokens(existing, db); + + assertEquals(1, tokens.size()); + + DbEntity entity = db.getDbEntity("table1"); + assertEquals(factory().createDropColumnToModel(entity, entity.getAttribute("Attr01")).getTokenValue(), + tokens.get(0).getTokenValue()); + } + @Test public void testChangeGeneratedStatus() { DataMap existing = dataMap().with( @@ -477,19 +653,50 @@ public void testProcedures() { DataMap dataMap2 = dataMap().build(); - PatternFilter patternFilter = new PatternFilter(); - patternFilter.include("proc1"); + PatternFilter patternFilter = new PatternFilter(false); + patternFilter.include(PatternFilter.pattern("proc1", false)); + FiltersConfig filtersConfig = FiltersConfig + .create(null, null, null, patternFilter); + DataMapMerger merger = DataMapMerger + .builder(factory()) + .filters(filtersConfig) + .nameConverter(String::toUpperCase) + .build(); + assertEquals(1, merger.createMergeTokens(dataMap1, dataMap2).size()); + } + + @Test + public void testProceduresCaseSensitiveNaming() { + DataMap dataMap1 = dataMap().with( + procedure("proc1") + .callParameters(new ProcedureParameter("test")), + procedure("Proc1") + .callParameters(new ProcedureParameter("Test")) + ).build(); + + DataMap dataMap2 = dataMap().with( + procedure("proc1") + .callParameters(new ProcedureParameter("test")) + ).build(); + + PatternFilter patternFilter = new PatternFilter(true); + patternFilter.include(PatternFilter.pattern("[Pp]roc1", true)); FiltersConfig filtersConfig = FiltersConfig .create(null, null, null, patternFilter); DataMapMerger merger = DataMapMerger .builder(factory()) .filters(filtersConfig) + .nameConverter(Function.identity()) .build(); assertEquals(1, merger.createMergeTokens(dataMap1, dataMap2).size()); } private DataMapMerger dbMerger() { - return DataMapMerger.build(factory()); + return DataMapMerger.builder(factory()).nameConverter(String::toUpperCase).build(); + } + + private DataMapMerger dbMerger(Function nameConverter) { + return DataMapMerger.builder(factory()).nameConverter(nameConverter).build(); } private HSQLMergerTokenFactory factory() { diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java new file mode 100644 index 0000000000..b2b335f4e3 --- /dev/null +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java @@ -0,0 +1,156 @@ +/***************************************************************** + * 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.dbsync.merge; + +import org.apache.cayenne.access.DataContext; +import org.apache.cayenne.dbsync.merge.token.MergerToken; +import org.apache.cayenne.dbsync.merge.token.db.DropRelationshipToDb; +import org.apache.cayenne.dbsync.merge.token.db.DropTableToDb; +import org.apache.cayenne.di.Inject; +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbJoin; +import org.apache.cayenne.map.DbRelationship; +import org.apache.cayenne.map.ObjEntity; +import org.apache.cayenne.map.ObjRelationship; +import org.junit.Test; + +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class DbEntityMergerIT extends MergeCase { + + @Inject + private DataContext context; + + @Test + public void testCreateTokensForMissingImported() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_TABLE2"); + assertTokensAndExecute(0, 0); + + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + column1.setMandatory(true); + column1.setPrimaryKey(true); + dbEntity1.addAttribute(column1); + + DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1); + column2.setMaxLength(10); + column2.setMandatory(false); + column2.setPrimaryKey(false); + dbEntity1.addAttribute(column2); + + + DbEntity dbEntity2 = new DbEntity("NEW_TABLE2"); + + DbAttribute column3 = new DbAttribute("ID", Types.INTEGER, dbEntity2); + column3.setMandatory(false); + column3.setPrimaryKey(false); + dbEntity2.addAttribute(column3); + + DbAttribute column4 = new DbAttribute("NUMBER", Types.INTEGER, dbEntity2); + column3.setMandatory(false); + column3.setPrimaryKey(false); + column4.setMaxLength(10); + dbEntity2.addAttribute(column4); + + // create db relationships + DbRelationship rel1To2 = new DbRelationship("rel1To2"); + rel1To2.setSourceEntity(dbEntity1); + rel1To2.setTargetEntityName(dbEntity2); + rel1To2.setToMany(true); + rel1To2.addJoin(new DbJoin(rel1To2, column1.getName(), column3.getName())); + dbEntity1.addRelationship(rel1To2); + + DbRelationship rel2To1 = new DbRelationship("rel2To1"); + rel2To1.setSourceEntity(dbEntity2); + rel2To1.setTargetEntityName(dbEntity1); + rel2To1.setToMany(false); + rel2To1.addJoin(new DbJoin(rel2To1, column3.getName(), column1.getName())); + dbEntity2.addRelationship(rel2To1); + + // for the new entity to the db + map.addDbEntity(dbEntity1); + map.addDbEntity(dbEntity2); + execute(mergerFactory().createCreateTableToDb(dbEntity1)); + execute(mergerFactory().createCreateTableToDb(dbEntity2)); + execute(mergerFactory().createDropRelationshipToModel(dbEntity1, rel1To2).createReverse(mergerFactory())); + execute(mergerFactory().createDropRelationshipToModel(dbEntity2, rel2To1).createReverse(mergerFactory())); + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + + List tokens = createMergeTokensWithoutEmptyFilter(false); + List reverseTokens = new ArrayList<>(); + for (MergerToken token : tokens) { + if (token instanceof DropRelationshipToDb || token instanceof DropTableToDb) { + reverseTokens.add(token.createReverse(mergerFactory())); + } + } + + Collections.sort(reverseTokens); + assertEquals(4, reverseTokens.size()); + execute(reverseTokens); + + ObjEntity objEntity1 = null; + ObjEntity objEntity2 = null; + for (ObjEntity candidate : map.getObjEntities()) { + if (dbEntity1.getName().equals(candidate.getDbEntityName())) { + objEntity1 = candidate; + continue; + } + if (dbEntity2.getName().equals(candidate.getDbEntityName())) { + objEntity2 = candidate; + } + } + + assertNotNull(objEntity1); + assertNotNull(objEntity2); + Iterator iterator1 = objEntity1.getRelationships().iterator(); + Iterator iterator2 = objEntity2.getRelationships().iterator(); + assertTrue(iterator2.hasNext()); + ObjRelationship objRelationship2 = iterator2.next(); + assertFalse(objRelationship2.isToMany()); + assertTrue(iterator1.hasNext()); + ObjRelationship objRelationship1 = iterator1.next(); + assertTrue(objRelationship1.isToMany()); + + //clear entity + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + map.removeObjEntity(objEntity1.getName(), true); + map.removeObjEntity(objEntity2.getName(), true); + dropTableIfPresent("NEW_TABLE2"); + dropTableIfPresent("NEW_TABLE"); + + assertTokensAndExecute(0, 0, true); + + map.setQuotingSQLIdentifiers(false); + } +} diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java index 68d15c016f..e8c4c52a14 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/EntityMergeSupportIT.java @@ -109,4 +109,183 @@ public void testMerging() { map.removeDbEntity(dbEntity2.getName()); map.removeDbEntity(dbEntity1.getName()); } + + @Test + public void testMergingTableWithSameNameInDifferentCapitalization() { + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + e1col1.setMandatory(true); + e1col1.setPrimaryKey(true); + dbEntity1.addAttribute(e1col1); + + DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1); + e1col2.setMaxLength(10); + e1col2.setMandatory(false); + dbEntity1.addAttribute(e1col2); + + map.addDbEntity(dbEntity1); + + DbEntity dbEntity2 = new DbEntity("NEW_TABLE2"); + DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2); + e2col1.setMandatory(true); + e2col1.setPrimaryKey(true); + dbEntity2.addAttribute(e2col1); + DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2); + dbEntity2.addAttribute(e2col2); + + map.addDbEntity(dbEntity2); + + DbEntity dbEntity3 = new DbEntity("NEW_table"); + DbAttribute e3col1 = new DbAttribute("Id", Types.INTEGER, dbEntity3); + e3col1.setMandatory(true); + e3col1.setPrimaryKey(true); + dbEntity3.addAttribute(e3col1); + + DbAttribute e3col2 = new DbAttribute("FK", Types.INTEGER, dbEntity3); + dbEntity3.addAttribute(e3col2); + + map.addDbEntity(dbEntity3); + + // create db relationships + DbRelationship rel1To2 = new DbRelationship("rel1To2"); + rel1To2.setSourceEntity(dbEntity1); + rel1To2.setTargetEntityName(dbEntity2); + rel1To2.setToMany(true); + rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName())); + dbEntity1.addRelationship(rel1To2); + DbRelationship rel2To1 = new DbRelationship("rel2To1"); + rel2To1.setSourceEntity(dbEntity2); + rel2To1.setTargetEntityName(dbEntity1); + rel2To1.setToMany(false); + rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName())); + dbEntity2.addRelationship(rel2To1); + assertSame(rel1To2, rel2To1.getReverseRelationship()); + assertSame(rel2To1, rel1To2.getReverseRelationship()); + + // create db relationships + DbRelationship rel3To2 = new DbRelationship("rel3To2"); + rel3To2.setSourceEntity(dbEntity3); + rel3To2.setTargetEntityName(dbEntity2); + rel3To2.setToMany(true); + rel3To2.addJoin(new DbJoin(rel3To2, e1col1.getName(), e2col2.getName())); + dbEntity3.addRelationship(rel3To2); + DbRelationship rel2To3 = new DbRelationship("rel2To3"); + rel2To3.setSourceEntity(dbEntity2); + rel2To3.setTargetEntityName(dbEntity3); + rel2To3.setToMany(false); + rel2To3.addJoin(new DbJoin(rel2To3, e2col2.getName(), e1col1.getName())); + dbEntity2.addRelationship(rel2To3); + assertSame(rel3To2, rel2To3.getReverseRelationship()); + assertSame(rel2To3, rel3To2.getReverseRelationship()); + + ObjEntity objEntity1 = new ObjEntity("NewTable"); + objEntity1.setDbEntity(dbEntity1); + map.addObjEntity(objEntity1); + + ObjEntity objEntity2 = new ObjEntity("NewTable2"); + objEntity2.setDbEntity(dbEntity2); + map.addObjEntity(objEntity2); + + + ObjEntity objEntity3 = new ObjEntity("NewTable3"); + objEntity3.setDbEntity(dbEntity3); + map.addObjEntity(objEntity3); + + EntityMergeSupport entityMergeSupport = new EntityMergeSupport( + new DefaultObjectNameGenerator(NoStemStemmer.getInstance()), + NamePatternMatcher.EXCLUDE_ALL, + true, + true, + false); + assertTrue(entityMergeSupport.synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2, objEntity3))); + assertNotNull(objEntity1.getAttribute("name")); + assertNotNull(objEntity1.getRelationship("newTable2s")); + assertNotNull(objEntity2.getRelationship("newTable")); + assertNotNull(objEntity2.getRelationship("newTable1")); + assertNotNull(objEntity3.getAttribute("fk")); + assertNotNull(objEntity3.getRelationship("newTable2s")); + + assertEquals(objEntity1.getRelationship("newTable2s").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY); + assertEquals(objEntity2.getRelationship("newTable").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE); + assertEquals(objEntity3.getRelationship("newTable2s").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY); + assertEquals(objEntity2.getRelationship("newTable1").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE); + + map.removeObjEntity(objEntity2.getName()); + map.removeObjEntity(objEntity1.getName()); + map.removeObjEntity(objEntity3.getName()); + map.removeDbEntity(dbEntity2.getName()); + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity3.getName()); + } + + @Test + public void testMergingTableWithSameNameInDifferentCapitalization1() { + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + e1col1.setMandatory(true); + e1col1.setPrimaryKey(true); + dbEntity1.addAttribute(e1col1); + + DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1); + e1col2.setMaxLength(10); + e1col2.setMandatory(false); + dbEntity1.addAttribute(e1col2); + + map.addDbEntity(dbEntity1); + + DbEntity dbEntity2 = new DbEntity("NEW_table"); + DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2); + e2col1.setMandatory(true); + e2col1.setPrimaryKey(true); + dbEntity2.addAttribute(e2col1); + DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2); + dbEntity2.addAttribute(e2col2); + + map.addDbEntity(dbEntity2); + + // create db relationships + DbRelationship rel1To2 = new DbRelationship("rel1To2"); + rel1To2.setSourceEntity(dbEntity1); + rel1To2.setTargetEntityName(dbEntity2); + rel1To2.setToMany(true); + rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName())); + dbEntity1.addRelationship(rel1To2); + DbRelationship rel2To1 = new DbRelationship("rel2To1"); + rel2To1.setSourceEntity(dbEntity2); + rel2To1.setTargetEntityName(dbEntity1); + rel2To1.setToMany(false); + rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName())); + dbEntity2.addRelationship(rel2To1); + assertSame(rel1To2, rel2To1.getReverseRelationship()); + assertSame(rel2To1, rel1To2.getReverseRelationship()); + + ObjEntity objEntity1 = new ObjEntity("NewTable"); + objEntity1.setDbEntity(dbEntity1); + map.addObjEntity(objEntity1); + + ObjEntity objEntity2 = new ObjEntity("NewTable2"); + objEntity2.setDbEntity(dbEntity2); + map.addObjEntity(objEntity2); + + EntityMergeSupport entityMergeSupport = new EntityMergeSupport( + new DefaultObjectNameGenerator(NoStemStemmer.getInstance()), + NamePatternMatcher.EXCLUDE_ALL, + true, + true, + false); + assertTrue(entityMergeSupport.synchronizeWithDbEntities(Arrays.asList(objEntity1, objEntity2))); + assertNotNull(objEntity1.getAttribute("name")); + assertNotNull(objEntity1.getRelationship("newTables")); + assertNotNull(objEntity2.getRelationship("newTable")); + + assertEquals(objEntity1.getRelationship("newTables").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_MANY); + assertEquals(objEntity2.getRelationship("newTable").getDeleteRule(), DeleteRule.DEFAULT_DELETE_RULE_TO_ONE); + + map.removeObjEntity(objEntity2.getName()); + map.removeObjEntity(objEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + map.removeDbEntity(dbEntity1.getName()); + } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java index a2d606758c..f4472893e1 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java @@ -58,6 +58,7 @@ import java.sql.Types; import java.util.ArrayList; import java.util.List; +import java.util.function.Function; import static org.junit.Assert.assertEquals; @@ -92,49 +93,65 @@ public void setUp() throws Exception { // container // on every test map = runtime.getDataDomain().getDataMap("testmap"); + map.setQuotingSQLIdentifiers(true); filterDataMap(); - List tokens = createMergeTokens(); + List tokens = createMergeTokens(true); + execute(tokens); - assertTokensAndExecute(0, 0); + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(false); } protected DataMapMerger.Builder merger() { - return DataMapMerger.builder(mergerFactory()); + return DataMapMerger.builder(mergerFactory()).nameConverter(String::toUpperCase); } + // useCaseSensitiveNaming is false by default protected List createMergeTokens() { - return createMergeTokens("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"); + return createMergeTokens(false); + } + + protected List createMergeTokens(boolean useCaseSensitiveNaming) { + return filterEmpty(createMergeTokensWithoutEmptyFilter(useCaseSensitiveNaming)); + } + + protected List createMergeTokensWithoutEmptyFilter(boolean useCaseSensitiveNaming) { + return createMergeTokens("ARTIST|GALLERY|PAINTING|NEW_table|NEW_TABLE2?", useCaseSensitiveNaming); } - protected List createMergeTokens(String tableFilterInclude) { + private List createMergeTokens(String tableFilterInclude, boolean useCaseSensitiveNaming) { FiltersConfig filters = FiltersConfig.create(null, null, - TableFilter.include(tableFilterInclude), PatternFilter.INCLUDE_NOTHING); + TableFilter.include(tableFilterInclude, useCaseSensitiveNaming), PatternFilter.INCLUDE_NOTHING); DbLoaderConfiguration loaderConfiguration = new DbLoaderConfiguration(); loaderConfiguration.setFiltersConfig(filters); + Function nameConverter = useCaseSensitiveNaming + ? Function.identity() + : String::toUpperCase; DataMap dbImport; try (Connection conn = node.getDataSource().getConnection();) { dbImport = new DbLoader(node.getAdapter(), conn, loaderConfiguration, new LoggingDbLoaderDelegate(LoggerFactory.getLogger(DbLoader.class)), - new DefaultObjectNameGenerator(NoStemStemmer.getInstance())) + new DefaultObjectNameGenerator(NoStemStemmer.getInstance()), + nameConverter) .load(); } catch (SQLException e) { throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e); } - List tokens = merger().filters(filters).build().createMergeTokens(map, dbImport); + List tokens = merger().filters(filters).nameConverter(nameConverter).build().createMergeTokens(map, dbImport); return filter(tokens); } private List filter(List tokens) { - return filterEmptyTypeChange(filterEmpty(tokens)); + return filterEmptyTypeChange(tokens); } /** @@ -172,7 +189,7 @@ private static boolean isDateTimeType(int type) { return type == Types.DATE || type == Types.TIME || type == Types.TIMESTAMP; } - private List filterEmpty(List tokens) { + protected List filterEmpty(List tokens) { List tokensOut = new ArrayList<>(); for(MergerToken token : tokens) { if(!token.isEmpty()) { @@ -253,7 +270,12 @@ protected void assertTokens(List tokens, int expectedToDb, int expe } protected void assertTokensAndExecute(int expectedToDb, int expectedToModel) { - List tokens = createMergeTokens(); + assertTokensAndExecute(expectedToDb, expectedToModel, false); + } + + protected void assertTokensAndExecute(int expectedToDb, int expectedToModel, boolean useCaseSensitiveNaming) { + List tokens = createMergeTokens(useCaseSensitiveNaming); + tokens = filterEmpty(tokens); assertTokens(tokens, expectedToDb, expectedToModel); execute(tokens); } @@ -267,6 +289,8 @@ protected void dropTableIfPresent(String tableName) throws Exception { // must have a dummy datamap for the dummy table for the downstream code // to work DataMap map = new DataMap("dummy"); + map.setQuotingSQLIdentifiers(true); + map.setQuotingSQLIdentifiers(map.isQuotingSQLIdentifiers()); DbEntity entity = new DbEntity(tableName); map.addDbEntity(entity); @@ -281,5 +305,6 @@ protected void dropTableIfPresent(String tableName) throws Exception { logger.info("Exception dropping table " + tableName + ", probably abscent.."); } } + map.setQuotingSQLIdentifiers(false); } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java index 4d420d41a2..1813b5f395 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java @@ -299,6 +299,134 @@ public void testAddForeignKeyAfterTable() throws Exception { assertTokensAndExecute(0, 0); } + @Test + public void testAddTableWithSameNameInDifferentCapitalization() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_table"); + + assertTokensAndExecute(0, 0,true); + + DbEntity dbEntity = new DbEntity("NEW_TABLE"); + attr(dbEntity, "ID", Types.INTEGER, true, true); + attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10); + attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false); + + map.addDbEntity(dbEntity); + + DbEntity artistDbEntity = map.getDbEntity("ARTIST"); + assertNotNull(artistDbEntity); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + // relation from new_table to artist + DbRelationship r1 = new DbRelationship("toArtistR1"); + r1.setSourceEntity(dbEntity); + r1.setTargetEntityName(artistDbEntity); + r1.setToMany(false); + r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID")); + dbEntity.addRelationship(r1); + + // relation from artist to new_table + DbRelationship r2 = new DbRelationship("toNewTableR2"); + r2.setSourceEntity(artistDbEntity); + r2.setTargetEntityName(dbEntity); + r2.setToMany(true); + r2.addJoin(new DbJoin(r2, "ARTIST_ID", "ARTIST_ID")); + artistDbEntity.addRelationship(r2); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + DbEntity dbEntity1 = new DbEntity("NEW_table"); + attr(dbEntity1, "ID", Types.INTEGER, true, true); + attr(dbEntity1, "NAME", Types.VARCHAR, false, false).setMaxLength(10); + attr(dbEntity1, "ARTIST_ID", Types.BIGINT, false, false); + + map.addDbEntity(dbEntity1); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + // relation from new_table to artist + DbRelationship r3 = new DbRelationship("toArtistR3"); + r3.setSourceEntity(dbEntity1); + r3.setTargetEntityName(artistDbEntity); + r3.setToMany(false); + r3.addJoin(new DbJoin(r3, "ARTIST_ID", "ARTIST_ID")); + dbEntity1.addRelationship(r3); + + // relation from artist to new_table + DbRelationship r4 = new DbRelationship("toNewTableR4"); + r4.setSourceEntity(artistDbEntity); + r4.setTargetEntityName(dbEntity1); + r4.setToMany(true); + r4.addJoin(new DbJoin(r4, "ARTIST_ID", "ARTIST_ID")); + artistDbEntity.addRelationship(r4); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + // remove relationships + dbEntity.removeRelationship(r1.getName()); + artistDbEntity.removeRelationship(r2.getName()); + dbEntity1.removeRelationship(r3.getName()); + artistDbEntity.removeRelationship(r4.getName()); + resolver.refreshMappingCache(); + /* + * Add Relationship ARTIST->NEW_TABLE To Model -- Not generated any more + * Drop Relationship NEW_TABLE->ARTIST To DB + * */ + assertTokensAndExecute(2, 0,true); + assertTokensAndExecute(0, 0,true); + + // clear up + // map.removeObjEntity(objEntity.getName(), true); + map.removeDbEntity(dbEntity.getName(), true); + map.removeDbEntity(dbEntity1.getName(), true); + resolver.refreshMappingCache(); + // assertNull(map.getObjEntity(objEntity.getName())); + assertNull(map.getDbEntity(dbEntity.getName())); + assertNull(map.getDbEntity(dbEntity1.getName())); + assertFalse(map.getDbEntities().contains(dbEntity)); + assertFalse(map.getDbEntities().contains(dbEntity1)); + + assertTokensAndExecute(2, 0,true); + assertTokensAndExecute(0, 0,true); + + map.setQuotingSQLIdentifiers(false); + } + + + @Test + public void testAddAttrWithSameNameInDifferentCapitalization() throws Exception { + dropTableIfPresent("NEW_TABLE"); + + assertTokensAndExecute(0, 0,true); + + DbEntity dbEntity = new DbEntity("NEW_TABLE"); + attr(dbEntity, "ID", Types.INTEGER, true, true); + attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10); + attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false); + + map.setQuotingSQLIdentifiers(true); + map.addDbEntity(dbEntity); + + DbEntity artistDbEntity = map.getDbEntity("ARTIST"); + assertNotNull(artistDbEntity); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + attr(dbEntity,"id", Types.INTEGER, false, false); + + assertTokensAndExecute(1, 0,true); + assertTokensAndExecute(0, 0,true); + + map.setQuotingSQLIdentifiers(false); + } + private static DbAttribute attr(DbEntity dbEntity, String name, int type, boolean mandatory, boolean primaryKey) { DbAttribute column1 = new DbAttribute(name, type, dbEntity); column1.setMandatory(mandatory); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/TokensReverseTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/TokensReverseTest.java index 31d992bbcf..26c4761595 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/TokensReverseTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/TokensReverseTest.java @@ -20,6 +20,7 @@ package org.apache.cayenne.dbsync.merge.token; import java.util.Collections; +import java.util.function.Function; import org.apache.cayenne.dbsync.merge.factory.HSQLMergerTokenFactory; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactory; @@ -72,8 +73,11 @@ public void testReverses() { testOneToOneReverse(factory().createSetColumnTypeToDb(entity, attr, attr2)); testOneToOneReverse(factory().createSetColumnTypeToModel(entity, attr, attr2)); - testOneToOneReverse(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK")); - testOneToOneReverse(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK")); + testOneToOneReverse(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK", String::toUpperCase)); + testOneToOneReverse(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK", String::toUpperCase)); + + testOneToOneReverse(factory().createSetPrimaryKeyToDb(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK", Function.identity())); + testOneToOneReverse(factory().createSetPrimaryKeyToModel(entity, Collections.singleton(attr), Collections.singleton(attr2), "PK", Function.identity())); testOneToOneReverse(factory().createSetValueForNullToDb(entity, attr, new DefaultValueForNullProvider())); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java index 7c05ca716c..453eeb3a48 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java @@ -57,4 +57,42 @@ public void test() throws Exception { assertTokensAndExecute(1, 0); assertTokensAndExecute(0, 0); } + + @Test + public void testCaseSensitiveNaming() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + assertTokensAndExecute(0, 0, true); + + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute e1col1 = new DbAttribute("ID1", Types.INTEGER, dbEntity1); + e1col1.setMandatory(true); + e1col1.setPrimaryKey(true); + dbEntity1.addAttribute(e1col1); + map.addDbEntity(dbEntity1); + + assertTokensAndExecute(1, 0, true); + assertTokensAndExecute(0, 0, true); + + DbAttribute e1col2 = new DbAttribute("id1", Types.INTEGER, dbEntity1); + e1col2.setMandatory(true); + dbEntity1.addAttribute(e1col2); + + assertTokensAndExecute(2, 0, true); + assertTokensAndExecute(0, 0, true); + + e1col1.setPrimaryKey(false); + e1col2.setPrimaryKey(true); + + assertTokensAndExecute(1, 0, true); + assertTokensAndExecute(0, 0, true); + + //clear entity + map.removeDbEntity(dbEntity1.getName()); + dropTableIfPresent("NEW_TABLE"); + + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(false); + } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java index e6d7125a18..d2ef981862 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import java.sql.Types; @@ -98,4 +99,75 @@ public void testAddColumn() throws Exception { assertTokensAndExecute(0, 0); } + @Test + public void testAddColumnCaseSensitiveNaming() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + assertTokensAndExecute(0, 0); + + DbEntity dbEntity = new DbEntity("NEW_TABLE"); + + DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity); + column1.setMandatory(true); + column1.setPrimaryKey(true); + dbEntity.addAttribute(column1); + + DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity); + column2.setMaxLength(10); + column2.setMandatory(false); + dbEntity.addAttribute(column2); + + DbAttribute column3 = new DbAttribute("name", Types.VARCHAR, dbEntity); + column3.setMaxLength(10); + column3.setMandatory(false); + dbEntity.addAttribute(column3); + map.addDbEntity(dbEntity); + + assertTokensAndExecute(1, 0); + assertTokensAndExecute(0, 0); + + ObjEntity objEntity = new ObjEntity("NewTable"); + objEntity.setDbEntity(dbEntity); + ObjAttribute oatr1 = new ObjAttribute("name"); + oatr1.setDbAttributePath(column2.getName()); + oatr1.setType("java.lang.String"); + objEntity.addAttribute(oatr1); + + ObjAttribute oatr2 = new ObjAttribute("name1"); + oatr2.setDbAttributePath(column3.getName()); + oatr2.setType("java.lang.String"); + objEntity.addAttribute(oatr2); + map.addObjEntity(objEntity); + + // remove name column + objEntity.removeAttribute(oatr2.getName()); + dbEntity.removeAttribute(column3.getName()); + assertNull(objEntity.getAttribute(oatr2.getName())); + assertEquals(1, objEntity.getAttributes().size()); + assertNull(dbEntity.getAttribute(column3.getName())); + assertSame(column2, dbEntity.getAttribute(column2.getName())); + + List tokens = createMergeTokens(true); + assertEquals(1, tokens.size()); + MergerToken token = tokens.get(0); + if (token.getDirection().isToDb()) { + token = token.createReverse(mergerFactory()); + } + assertTrue(token instanceof AddColumnToModel); + execute(token); + assertEquals(2, objEntity.getAttributes().size()); + + // clear up + map.removeObjEntity(objEntity.getName(), true); + map.removeDbEntity(dbEntity.getName(), true); + resolver.refreshMappingCache(); + assertNull(map.getObjEntity(objEntity.getName())); + assertNull(map.getDbEntity(dbEntity.getName())); + assertFalse(map.getDbEntities().contains(dbEntity)); + + assertTokensAndExecute(1, 0); + assertTokensAndExecute(0, 0); + map.setQuotingSQLIdentifiers(false); + } + } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java index 0d72f9a48f..739ad3e989 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java @@ -26,12 +26,15 @@ import static org.junit.Assert.assertTrue; import java.sql.Types; +import java.util.ArrayList; import java.util.List; import org.apache.cayenne.dbsync.merge.MergeCase; import org.apache.cayenne.dbsync.merge.token.MergerToken; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbJoin; +import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.ObjEntity; import org.junit.Test; @@ -97,4 +100,191 @@ public void testAddTable() throws Exception { assertTokensAndExecute(1, 0); assertTokensAndExecute(0, 0); } + + @Test + public void testAddTableCaseSensitive() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_table"); + assertTokensAndExecute(0, 0); + + DbEntity dbEntity = new DbEntity("NEW_TABLE"); + + DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity); + column1.setMandatory(true); + column1.setPrimaryKey(true); + dbEntity.addAttribute(column1); + + DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity); + column2.setMaxLength(10); + column2.setMandatory(false); + dbEntity.addAttribute(column2); + + + DbEntity dbEntity1 = new DbEntity("NEW_table"); + + DbAttribute column3 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + column3.setMandatory(true); + column3.setPrimaryKey(true); + dbEntity1.addAttribute(column3); + + DbAttribute column4 = new DbAttribute("NUMBER", Types.INTEGER, dbEntity1); + column4.setMaxLength(10); + column4.setMandatory(false); + dbEntity1.addAttribute(column4); + + // for the new entity to the db + map.addDbEntity(dbEntity); + map.addDbEntity(dbEntity1); + execute(mergerFactory().createCreateTableToDb(dbEntity)); + execute(mergerFactory().createCreateTableToDb(dbEntity1)); + map.removeDbEntity(dbEntity.getName()); + map.removeDbEntity(dbEntity1.getName()); + + List tokens = createMergeTokensWithoutEmptyFilter(true); + List reverseTokens = new ArrayList<>(); + for (MergerToken token : tokens) { + if (token.getDirection().isToDb()) { + reverseTokens.add(token.createReverse(mergerFactory())); + } + } + execute(filterEmpty(reverseTokens)); + + ObjEntity objEntity1 = null; + for (ObjEntity candidate : map.getObjEntities()) { + if (dbEntity1.getName().equals(candidate.getDbEntityName())) { + objEntity1 = candidate; + break; + } + } + assertNotNull(objEntity1); + + assertEquals(objEntity1.getClassName(), map.getDefaultPackage() + "." + objEntity1.getName()); + assertEquals(objEntity1.getSuperClassName(), map.getDefaultSuperclass()); + assertEquals(objEntity1.getClientClassName(), map.getDefaultClientPackage() + "." + objEntity1.getName()); + assertEquals(objEntity1.getClientSuperClassName(), map.getDefaultClientSuperclass()); + + assertEquals(1, objEntity1.getAttributes().size()); + assertEquals("java.lang.Integer", objEntity1.getAttributes().iterator().next().getType()); + + // clear up + // fix psql case issue + map.removeDbEntity(objEntity1.getDbEntity().getName(), true); + map.removeObjEntity(objEntity1.getName(), true); + map.removeDbEntity(dbEntity1.getName(), true); + + ObjEntity objEntity = null; + for (ObjEntity candidate : map.getObjEntities()) { + if (dbEntity.getName().equals(candidate.getDbEntityName())) { + objEntity = candidate; + break; + } + } + map.removeDbEntity(objEntity.getDbEntity().getName(), true); + map.removeObjEntity(objEntity.getName(), true); + map.removeDbEntity(dbEntity.getName(), true); + resolver.refreshMappingCache(); + assertNull(map.getObjEntity(objEntity.getName())); + assertNull(map.getDbEntity(dbEntity.getName())); + assertFalse(map.getDbEntities().contains(dbEntity)); + assertNull(map.getObjEntity(objEntity1.getName())); + assertNull(map.getDbEntity(dbEntity1.getName())); + assertFalse(map.getDbEntities().contains(dbEntity1)); + + assertTokensAndExecute(2, 0, true); + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(false); + } + + @Test + public void testAddTableWithRelationship() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_table"); + assertTokensAndExecute(0, 0); + + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + column1.setMandatory(true); + column1.setPrimaryKey(true); + dbEntity1.addAttribute(column1); + + DbAttribute column2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1); + column2.setMaxLength(10); + column2.setMandatory(false); + dbEntity1.addAttribute(column2); + + DbEntity dbEntity2 = new DbEntity("NEW_table"); + + DbAttribute column3 = new DbAttribute("ID", Types.INTEGER, dbEntity2); + column3.setMandatory(true); + column3.setPrimaryKey(true); + dbEntity2.addAttribute(column3); + + DbAttribute column4 = new DbAttribute("NUMBER", Types.INTEGER, dbEntity2); + column4.setMaxLength(10); + column4.setMandatory(false); + dbEntity2.addAttribute(column4); + + // create db relationships + DbRelationship rel1To2 = new DbRelationship("rel1To2"); + rel1To2.setSourceEntity(dbEntity1); + rel1To2.setTargetEntityName(dbEntity2); + rel1To2.setToMany(true); + rel1To2.addJoin(new DbJoin(rel1To2, column1.getName(), column3.getName())); + dbEntity1.addRelationship(rel1To2); + + DbRelationship rel2To1 = new DbRelationship("rel2To1"); + rel2To1.setSourceEntity(dbEntity2); + rel2To1.setTargetEntityName(dbEntity1); + rel2To1.setToMany(false); + rel2To1.addJoin(new DbJoin(rel2To1, column3.getName(), column1.getName())); + dbEntity2.addRelationship(rel2To1); + + // for the new entity to the db + map.addDbEntity(dbEntity1); + map.addDbEntity(dbEntity2); + execute(mergerFactory().createCreateTableToDb(dbEntity1)); + execute(mergerFactory().createCreateTableToDb(dbEntity2)); + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + + List tokens = createMergeTokensWithoutEmptyFilter(true); + List reverseTokens = new ArrayList<>(); + for (MergerToken token : tokens) { + if (token.getDirection().isToDb()) { + reverseTokens.add(token.createReverse(mergerFactory())); + } + } + execute(filterEmpty(reverseTokens)); + + ObjEntity objEntity1 = null; + ObjEntity objEntity2 = null; + for (ObjEntity candidate : map.getObjEntities()) { + if (dbEntity1.getName().equals(candidate.getDbEntityName())) { + objEntity1 = candidate; + continue; + } + if (dbEntity2.getName().equals(candidate.getDbEntityName())) { + objEntity2 = candidate; + } + } + + assertNotNull(objEntity1); + assertNotNull(objEntity2); + assertEquals(0, objEntity1.getRelationships().size()); + assertEquals(0, objEntity2.getRelationships().size()); + + //clear entity + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + map.removeObjEntity(objEntity1.getName(), true); + map.removeObjEntity(objEntity2.getName(), true); + dropTableIfPresent("NEW_table"); + dropTableIfPresent("NEW_TABLE"); + + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(false); + } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java index 7dc4d5a965..9a52f062b9 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java @@ -189,4 +189,228 @@ public void testForeignKey() throws Exception { assertTokensAndExecute(2, 0); assertTokensAndExecute(0, 0); } + + @Test + public void testForeignKeyCaseSensitiveNaming() throws Exception { + map.setQuotingSQLIdentifiers(true); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_TABLE2"); + dropTableIfPresent("NEW_table"); + + assertTokensAndExecute(0, 0); + + DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); + + DbAttribute e1col1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); + e1col1.setMandatory(true); + e1col1.setPrimaryKey(true); + dbEntity1.addAttribute(e1col1); + + DbAttribute e1col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity1); + e1col2.setMaxLength(10); + e1col2.setMandatory(false); + dbEntity1.addAttribute(e1col2); + + map.addDbEntity(dbEntity1); + + DbEntity dbEntity2 = new DbEntity("NEW_TABLE2"); + DbAttribute e2col1 = new DbAttribute("ID", Types.INTEGER, dbEntity2); + e2col1.setMandatory(true); + e2col1.setPrimaryKey(true); + dbEntity2.addAttribute(e2col1); + DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2); + dbEntity2.addAttribute(e2col2); + DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2); + e2col3.setMaxLength(10); + dbEntity2.addAttribute(e2col3); + + map.addDbEntity(dbEntity2); + + + DbEntity dbEntity3 = new DbEntity("NEW_table"); + + DbAttribute e3col1 = new DbAttribute("ID", Types.INTEGER, dbEntity3); + e3col1.setMandatory(true); + e3col1.setPrimaryKey(true); + dbEntity3.addAttribute(e3col1); + + DbAttribute e3col2 = new DbAttribute("NAME", Types.VARCHAR, dbEntity3); + e3col2.setMaxLength(10); + e3col2.setMandatory(false); + dbEntity3.addAttribute(e3col2); + + map.addDbEntity(dbEntity3); + + // create db relationships + DbRelationship rel1To2 = new DbRelationship("rel1To2"); + rel1To2.setSourceEntity(dbEntity1); + rel1To2.setTargetEntityName(dbEntity2); + rel1To2.setToMany(true); + rel1To2.addJoin(new DbJoin(rel1To2, e1col1.getName(), e2col2.getName())); + dbEntity1.addRelationship(rel1To2); + DbRelationship rel2To1 = new DbRelationship("rel2To1"); + rel2To1.setSourceEntity(dbEntity2); + rel2To1.setTargetEntityName(dbEntity1); + rel2To1.setToMany(false); + rel2To1.addJoin(new DbJoin(rel2To1, e2col2.getName(), e1col1.getName())); + dbEntity2.addRelationship(rel2To1); + + DbRelationship rel3To2 = new DbRelationship("rel3To2"); + rel3To2.setSourceEntity(dbEntity3); + rel3To2.setTargetEntityName(dbEntity2); + rel3To2.setToMany(true); + rel3To2.addJoin(new DbJoin(rel3To2, e3col1.getName(), e2col2.getName())); + dbEntity3.addRelationship(rel3To2); + + DbRelationship rel2To3 = new DbRelationship("rel2To3"); + rel2To3.setSourceEntity(dbEntity2); + rel2To3.setTargetEntityName(dbEntity3); + rel2To3.setToMany(false); + rel2To3.addJoin(new DbJoin(rel2To3, e2col2.getName(), e3col1.getName())); + dbEntity2.addRelationship(rel2To3); + + assertSame(rel1To2, rel2To1.getReverseRelationship()); + assertSame(rel2To1, rel1To2.getReverseRelationship()); + assertSame(rel3To2, rel2To3.getReverseRelationship()); + assertSame(rel2To3, rel3To2.getReverseRelationship()); + + assertTokensAndExecute(5, 0, true); + assertTokensAndExecute(0, 0, true); + + // create ObjEntities + ObjEntity objEntity1 = new ObjEntity("NewTable"); + objEntity1.setDbEntity(dbEntity1); + ObjAttribute oatr1 = new ObjAttribute("name"); + oatr1.setDbAttributePath(e1col2.getName()); + oatr1.setType("java.lang.String"); + objEntity1.addAttribute(oatr1); + + map.addObjEntity(objEntity1); + ObjEntity objEntity2 = new ObjEntity("NewTable2"); + objEntity2.setDbEntity(dbEntity2); + ObjAttribute o2a1 = new ObjAttribute("name"); + o2a1.setDbAttributePath(e2col3.getName()); + o2a1.setType("java.lang.String"); + objEntity2.addAttribute(o2a1); + map.addObjEntity(objEntity2); + + ObjEntity objEntity3 = new ObjEntity("NewTable3"); + objEntity3.setDbEntity(dbEntity3); + ObjAttribute o3atr1 = new ObjAttribute("name"); + o3atr1.setDbAttributePath(e1col2.getName()); + o3atr1.setType("java.lang.String"); + objEntity3.addAttribute(o3atr1); + map.addObjEntity(objEntity3); + + // create ObjRelationships + assertEquals(0, objEntity1.getRelationships().size()); + assertEquals(0, objEntity2.getRelationships().size()); + assertEquals(0, objEntity3.getRelationships().size()); + ObjRelationship objRel1To2 = new ObjRelationship("objRel1To2"); + objRel1To2.addDbRelationship(rel1To2); + objRel1To2.setSourceEntity(objEntity1); + objRel1To2.setTargetEntityName(objEntity2); + objEntity1.addRelationship(objRel1To2); + + ObjRelationship objRel2To1 = new ObjRelationship("objRel2To1"); + objRel2To1.addDbRelationship(rel2To1); + objRel2To1.setSourceEntity(objEntity2); + objRel2To1.setTargetEntityName(objEntity1); + objEntity2.addRelationship(objRel2To1); + + ObjRelationship objRel2To3 = new ObjRelationship("objRel2To3"); + objRel2To3.addDbRelationship(rel2To3); + objRel2To3.setSourceEntity(objEntity2); + objRel2To3.setTargetEntityName(objEntity3); + objEntity2.addRelationship(objRel2To3); + + ObjRelationship objRel3To2 = new ObjRelationship("objRel2To3"); + objRel3To2.addDbRelationship(rel3To2); + objRel3To2.setSourceEntity(objEntity3); + objRel3To2.setTargetEntityName(objEntity2); + objEntity3.addRelationship(objRel3To2); + + assertEquals(1, objEntity1.getRelationships().size()); + assertEquals(2, objEntity2.getRelationships().size()); + assertEquals(1, objEntity3.getRelationships().size()); + assertSame(objRel1To2, objRel2To1.getReverseRelationship()); + assertSame(objRel2To1, objRel1To2.getReverseRelationship()); + assertSame(objRel2To3, objRel3To2.getReverseRelationship()); + assertSame(objRel3To2, objRel2To3.getReverseRelationship()); + + // remove relationship and fk from model, merge to db and read to model + dbEntity2.removeRelationship(rel2To3.getName()); + dbEntity3.removeRelationship(rel3To2.getName()); + List tokens = createMergeTokens(true); + + /** + * Drop Relationship NEW_TABLE2->NEW_TABLE To DB + * Drop Column NEW_TABLE2.FK To DB + * */ + assertTokens(tokens, 1, 0); + for (MergerToken token : tokens) { + if (token.getDirection().isToDb()) { + execute(token); + } + } + assertTokensAndExecute(0, 0, true); + + dbEntity2.addRelationship(rel2To3); + dbEntity3.addRelationship(rel3To2); + + // try do use the merger to remove the relationship in the model + tokens = createMergeTokens(true); + assertTokens(tokens, 1, 0); + // TODO: reversing the following two tokens should also reverse the + // order + MergerToken token0 = tokens.get(0).createReverse(mergerFactory()); + if (!(token0 instanceof DropRelationshipToModel)) { + fail(); + } + execute(token0); + + // check after merging + assertEquals(0, dbEntity3.getRelationships().size()); + assertEquals(1, dbEntity2.getRelationships().size()); + assertEquals(0, objEntity3.getRelationships().size()); + assertEquals(1, objEntity2.getRelationships().size()); + assertEquals(1, objEntity1.getRelationships().size()); + + // clear up + dbEntity1.removeRelationship(rel3To2.getName()); + dbEntity2.removeRelationship(rel2To3.getName()); + map.removeObjEntity(objEntity1.getName(), true); + map.removeDbEntity(dbEntity1.getName(), true); + map.removeObjEntity(objEntity2.getName(), true); + map.removeDbEntity(dbEntity2.getName(), true); + map.removeObjEntity(objEntity3.getName(), true); + map.removeDbEntity(dbEntity3.getName(), true); + resolver.refreshMappingCache(); + assertNull(map.getObjEntity(objEntity1.getName())); + assertNull(map.getDbEntity(dbEntity1.getName())); + assertNull(map.getObjEntity(objEntity2.getName())); + assertNull(map.getDbEntity(dbEntity2.getName())); + assertNull(map.getObjEntity(objEntity3.getName())); + assertNull(map.getDbEntity(dbEntity3.getName())); + assertFalse(map.getDbEntities().contains(dbEntity1)); + assertFalse(map.getDbEntities().contains(dbEntity2)); + assertFalse(map.getDbEntities().contains(dbEntity3)); + + assertTokensAndExecute(4, 0, true); + assertTokensAndExecute(0, 0, true); + + //clear entity + map.removeDbEntity(dbEntity1.getName()); + map.removeDbEntity(dbEntity2.getName()); + map.removeDbEntity(dbEntity3.getName()); + map.removeObjEntity(objEntity1.getName(), true); + map.removeObjEntity(objEntity2.getName(), true); + map.removeObjEntity(objEntity3.getName(), true); + dropTableIfPresent("NEW_table"); + dropTableIfPresent("NEW_TABLE"); + dropTableIfPresent("NEW_TABLE2"); + + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(false); + } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java index c94a1f4c5e..39db109d99 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/naming/NameBuilderTest.java @@ -269,4 +269,24 @@ public void testName_Callbacks_ObjEntityContext() { assertEquals("getUntitledAttr1", c3); entity.getCallbackMap().getPostAdd().addCallbackMethod(c3); } + + @Test + public void testName_MixedCase_DataMapContext() { + ObjectNameGenerator nameGenerator = new DefaultObjectNameGenerator(); + + DataMap dataMap = new DataMap(); + DbEntity dbEntity1 = new DbEntity(); + dbEntity1.setName("Artist"); + ObjEntity objEntity1 = new ObjEntity(); + objEntity1.setName(NameBuilder.builder(objEntity1, dataMap).baseName(nameGenerator.objEntityName(dbEntity1)).name()); + dataMap.addObjEntity(objEntity1); + assertEquals("Artist", objEntity1.getName()); + + DbEntity dbEntity2 = new DbEntity(); + dbEntity2.setName("ARTIST"); + ObjEntity objEntity2 = new ObjEntity(); + objEntity2.setName(NameBuilder.builder(objEntity2, dataMap).baseName(nameGenerator.objEntityName(dbEntity2)).name()); + dataMap.addObjEntity(objEntity2); + assertEquals("Artist1", objEntity2.getName()); + } } \ No newline at end of file diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java index 9f7a5a7c1b..1f221fd693 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbimport/DefaultDbImportActionTest.java @@ -125,7 +125,7 @@ public void testNewDataMapImport() throws Exception { when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance())); when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL); - DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) { + DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator, String::toUpperCase) { @Override public DataMap load() throws SQLException { DataMap map = new DataMap(); @@ -161,7 +161,7 @@ public void testImportWithFieldChanged() throws Exception { when(config.createNameGenerator()).thenReturn(new DefaultObjectNameGenerator(NoStemStemmer.getInstance())); when(config.createMeaningfulPKFilter()).thenReturn(NamePatternMatcher.EXCLUDE_ALL); - DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) { + DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator, String::toUpperCase) { @Override public DataMap load() throws SQLException { DataMap dataMap = new DataMap(); @@ -227,7 +227,7 @@ public void testImportWithoutChanges() throws Exception { when(config.createMergeDelegate()).thenReturn(new DefaultModelMergeDelegate()); when(config.getDbLoaderConfig()).thenReturn(new DbLoaderConfiguration()); - DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator) { + DbLoader dbLoader = new DbLoader(mockAdapter, mockConnection, config.getDbLoaderConfig(), mockDelegate, mockNameGenerator, String::toUpperCase) { @Override public DataMap load() throws SQLException { DataMap dataMap = new DataMap(); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/BaseLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/BaseLoaderIT.java index 2a775babeb..aa5c0bc4a0 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/BaseLoaderIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/BaseLoaderIT.java @@ -59,7 +59,7 @@ public class BaseLoaderIT extends ServerCase { @Before public void before() throws Exception { - store = new DbLoadDataStore(); + store = new DbLoadDataStore(String::toUpperCase); assertTrue("Store is not empty", store.getDbEntities().isEmpty()); this.connection = dataSourceFactory.getSharedDataSource().getConnection(); } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java index dc629210a5..49f0163f79 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java @@ -121,7 +121,7 @@ public void before() throws Exception { } private DbLoader createDbLoader(boolean meaningfulPK, boolean meaningfulFK) { - return new DbLoader(adapter, connection, CONFIG, null, new DefaultObjectNameGenerator(NoStemStemmer.getInstance())); + return new DbLoader(adapter, connection, CONFIG, null, new DefaultObjectNameGenerator(NoStemStemmer.getInstance()), String::toUpperCase); } @After diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java index 9f5a459589..929487e121 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigBuilderTest.java @@ -127,6 +127,23 @@ public void testCompact_04() { " Use primitives", engineering.toString()); } + @Test + public void testCompact_05() { + ReverseEngineering engineering = new ReverseEngineering(); + engineering.setUseCaseSensitiveNaming(true); + engineering.addSchema(new Schema("s")); + + FiltersConfigBuilder builder = new FiltersConfigBuilder(engineering); + builder.compact(); + assertEquals( + "ReverseEngineering: \n" + + " Catalog: null\n" + + " Schema: s\n" + + " IncludeTable: null\n\n" + + " Use primitives\n" + + " Use case sensitive naming", engineering.toString()); + } + @Test public void testCompact_full() { ReverseEngineering engineering = new ReverseEngineering(); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java index e947b31c09..e0618a4118 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/FiltersConfigTest.java @@ -47,10 +47,10 @@ public void testToString_02() { new SchemaFilter("schema_21", TableFilter.everything(), PatternFilter.INCLUDE_NOTHING), new SchemaFilter("schema_22", new TableFilter( - includes(new IncludeTableFilter(null, PatternFilter.INCLUDE_NOTHING)), + includes(new IncludeTableFilter(null, PatternFilter.INCLUDE_NOTHING, false)), excludes("aaa")), PatternFilter.INCLUDE_NOTHING), - new SchemaFilter("schema_23", TableFilter.include("include"), PatternFilter.INCLUDE_NOTHING) + new SchemaFilter("schema_23", TableFilter.include("include", false), PatternFilter.INCLUDE_NOTHING) ) ); @@ -78,7 +78,7 @@ public void testToString_02() { private SortedSet excludes(String ... p) { SortedSet patterns = new TreeSet(PatternFilter.PATTERN_COMPARATOR); for (String pattern : p) { - patterns.add(PatternFilter.pattern(pattern)); + patterns.add(PatternFilter.pattern(pattern, false)); } return patterns; } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java index 594f23ba5a..5edeaf9173 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/PatternFilterTest.java @@ -23,7 +23,7 @@ public class PatternFilterTest extends TestCase { public void testInclude() throws Exception { - PatternFilter filter = new PatternFilter() + PatternFilter filter = new PatternFilter(false) .include("aaa") .include("bbb"); @@ -33,7 +33,7 @@ public void testInclude() throws Exception { assertFalse(filter.isIncluded("aa")); assertFalse(filter.isIncluded("abb")); - filter = new PatternFilter().include("^v_.*$"); + filter = new PatternFilter(false).include("^v_.*$"); assertTrue(filter.isIncluded("v_new_view")); assertFalse(filter.isIncluded("new_view")); assertFalse(filter.isIncluded("view")); @@ -41,7 +41,7 @@ public void testInclude() throws Exception { } public void testExclude() throws Exception { - PatternFilter filter = new PatternFilter() + PatternFilter filter = new PatternFilter(false) .exclude("aaa") .exclude("bbb"); @@ -53,7 +53,7 @@ public void testExclude() throws Exception { } public void testIncludeExclude() throws Exception { - PatternFilter filter = new PatternFilter() + PatternFilter filter = new PatternFilter(false) .include("aa.*") .exclude("aaa"); @@ -75,4 +75,44 @@ public void testIncludeNoneFilter() { assertFalse(PatternFilter.INCLUDE_NOTHING.isIncluded("")); assertFalse(PatternFilter.INCLUDE_NOTHING.isIncluded(null)); } + + public void testIncludeCaseSensitive() throws Exception { + PatternFilter filter = new PatternFilter(true) + .include("aaa") + .include("bbb"); + + assertTrue(filter.isIncluded("aaa")); + assertTrue(filter.isIncluded("bbb")); + assertFalse(filter.isIncluded("aaA")); + assertFalse(filter.isIncluded("AAA")); + assertFalse(filter.isIncluded("Bbb")); + + filter = new PatternFilter(true).include("^v_.*$"); + assertTrue(filter.isIncluded("v_new_view")); + assertFalse(filter.isIncluded("V_new_view")); + } + + public void testExcludeCaseSensitive() throws Exception { + PatternFilter filter = new PatternFilter(true) + .exclude("aaa") + .exclude("bbb"); + + assertTrue(filter.isIncluded("Aaa")); + assertTrue(filter.isIncluded("bbB")); + assertTrue(filter.isIncluded("AAA")); + assertTrue(filter.isIncluded("Bbb")); + } + + public void testIncludeExcludeCaseSensitive() throws Exception { + PatternFilter filter = new PatternFilter(true) + .include("aa.*") + .exclude("aaa"); + + assertFalse(filter.isIncluded("aaa")); + assertTrue(filter.isIncluded("aaA")); + assertFalse(filter.isIncluded("bbb")); + assertFalse(filter.isIncluded("Aaaa")); + assertTrue(filter.isIncluded("aaAA")); + assertFalse(filter.isIncluded("abb")); + } } \ No newline at end of file diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java index 21b0e2179e..a4263ef6d6 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/filters/TableFilterTest.java @@ -40,8 +40,8 @@ public void testIncludeEverything() { @Test public void testInclude() { TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter("aaa")); - includes.add(new IncludeTableFilter("bb")); + includes.add(new IncludeTableFilter("aaa", false)); + includes.add(new IncludeTableFilter("bb", false)); TableFilter filter = new TableFilter(includes, new TreeSet<>(PatternFilter.PATTERN_COMPARATOR)); @@ -61,7 +61,7 @@ public void testExclude() { excludes.add(Pattern.compile("bb")); TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter(null, PatternFilter.INCLUDE_EVERYTHING)); + includes.add(new IncludeTableFilter(null, PatternFilter.INCLUDE_EVERYTHING, false)); TableFilter filter = new TableFilter(includes, excludes); @@ -81,7 +81,7 @@ public void testIncludeExclude() { excludes.add(Pattern.compile("bb")); TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter("aa.*")); + includes.add(new IncludeTableFilter("aa.*", false)); TableFilter filter = new TableFilter(includes, excludes); @@ -97,8 +97,8 @@ public void testIncludeExclude() { @Test public void testGetTableFilter() { TreeSet includes = new TreeSet(); - includes.add(new IncludeTableFilter("aaa")); - includes.add(new IncludeTableFilter("bb")); + includes.add(new IncludeTableFilter("aaa", false)); + includes.add(new IncludeTableFilter("bb", false)); TreeSet excludes = new TreeSet<>(); @@ -112,4 +112,80 @@ public void testGetTableFilter() { assertNull(filter.getIncludeTableColumnFilter("")); assertNull(filter.getIncludeTableColumnFilter("bbbb")); } + + @Test + public void testIncludeCaseSensitive() { + TreeSet includes = new TreeSet<>(); + includes.add(new IncludeTableFilter("aaa", true)); + includes.add(new IncludeTableFilter("bb", true)); + + TableFilter filter = new TableFilter(includes, new TreeSet<>(PatternFilter.PATTERN_COMPARATOR)); + + assertTrue(filter.isIncludeTable("aaa")); + assertFalse(filter.isIncludeTable("aaA")); + assertFalse(filter.isIncludeTable("AAA")); + + assertTrue(filter.isIncludeTable("bb")); + assertFalse(filter.isIncludeTable("Bb")); + assertFalse(filter.isIncludeTable("BB")); + } + + @Test + public void testExcludeCaseSensitive() { + TreeSet excludes = new TreeSet<>(PatternFilter.PATTERN_COMPARATOR); + excludes.add(Pattern.compile("aaa")); + excludes.add(Pattern.compile("bb")); + + TreeSet includes = new TreeSet<>(); + includes.add(new IncludeTableFilter(null, PatternFilter.INCLUDE_EVERYTHING, true)); + + TableFilter filter = new TableFilter(includes, excludes); + + assertTrue(filter.isIncludeTable("aaA")); + assertTrue(filter.isIncludeTable("AAA")); + assertTrue(filter.isIncludeTable("aaaa")); + + assertTrue(filter.isIncludeTable("bB")); + assertTrue(filter.isIncludeTable("")); + assertTrue(filter.isIncludeTable("bbbb")); + } + + @Test + public void testIncludeExcludeCaseSensitive() { + TreeSet excludes = new TreeSet<>(PatternFilter.PATTERN_COMPARATOR); + excludes.add(Pattern.compile("aaa")); + excludes.add(Pattern.compile("bb")); + + TreeSet includes = new TreeSet<>(); + includes.add(new IncludeTableFilter("aa.*", true)); + + TableFilter filter = new TableFilter(includes, excludes); + + assertFalse(filter.isIncludeTable("aaa")); + assertTrue(filter.isIncludeTable("aa")); + assertTrue(filter.isIncludeTable("aaA")); + + assertFalse(filter.isIncludeTable("bb")); + assertFalse(filter.isIncludeTable("")); + assertFalse(filter.isIncludeTable("bB")); + } + + @Test + public void testGetTableFilterCaseSensitive() { + TreeSet includes = new TreeSet(); + includes.add(new IncludeTableFilter("aaa", true)); + includes.add(new IncludeTableFilter("bb", true)); + + TreeSet excludes = new TreeSet<>(); + + TableFilter filter = new TableFilter(includes, excludes); + + assertNotNull(filter.getIncludeTableColumnFilter("aaa")); + assertNull(filter.getIncludeTableColumnFilter("aa")); + assertNull(filter.getIncludeTableColumnFilter("aaA")); + + assertNotNull(filter.getIncludeTableColumnFilter("bb")); + assertNull(filter.getIncludeTableColumnFilter("")); + assertNull(filter.getIncludeTableColumnFilter("bB")); + } } \ No newline at end of file diff --git a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java index 9425916cd2..314f1f271a 100644 --- a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java +++ b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/DbImportTask.java @@ -146,6 +146,7 @@ DbImportConfiguration createConfig() { config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema()); config.setDefaultPackage(reverseEngineering.getDefaultPackage()); config.setUsePrimitives(reverseEngineering.isUsePrimitives()); + config.setUseCaseSensitiveNaming(reverseEngineering.isUseCaseSensitiveNaming()); config.setUseJava7Types(reverseEngineering.isUseJava7Types()); config.setCayenneProject(cayenneProject); diff --git a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/model/DbImportConfig.java b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/model/DbImportConfig.java index 9c2ed0864c..0d938a4354 100644 --- a/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/model/DbImportConfig.java +++ b/cayenne-gradle-plugin/src/main/java/org/apache/cayenne/tools/model/DbImportConfig.java @@ -92,6 +92,12 @@ public class DbImportConfig extends SchemaContainer { */ private boolean usePrimitives = true; + /** + *

If true, would use case sensitive naming.

+ *

Default is "false", i.e. case insensitive naming will be used.

+ */ + private boolean useCaseSensitiveNaming = false; + /** * Use old Java 7 date types */ @@ -135,6 +141,7 @@ public ReverseEngineering toReverseEngineering() { reverseEngineering.setNamingStrategy(namingStrategy); reverseEngineering.setStripFromTableNames(stripFromTableNames); reverseEngineering.setUsePrimitives(usePrimitives); + reverseEngineering.setUseCaseSensitiveNaming(useCaseSensitiveNaming); reverseEngineering.setUseJava7Types(useJava7Types); reverseEngineering.setTableTypes(tableTypes); @@ -259,6 +266,27 @@ public void usePrimitives(boolean usePrimitives) { setUsePrimitives(usePrimitives); } + /** + * @since 4.2 + */ + public boolean isUseCaseSensitiveNaming() { + return useCaseSensitiveNaming; + } + + /** + * @since 4.2 + */ + public void setUseCaseSensitiveNaming(boolean useCaseSensitiveNaming) { + this.useCaseSensitiveNaming = useCaseSensitiveNaming; + } + + /** + * @since 4.2 + */ + public void useCaseSensitiveNaming(boolean useCaseSensitiveNaming) { + setUseCaseSensitiveNaming(useCaseSensitiveNaming); + } + public boolean isUseJava7Types() { return useJava7Types; } diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd index 0cbf2b5c00..341d3a8e92 100644 --- a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd +++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd @@ -42,6 +42,7 @@ + diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part4/revEngineering.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part4/revEngineering.adoc index b48d784de7..ba34cff335 100644 --- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part4/revEngineering.adoc +++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part4/revEngineering.adoc @@ -57,6 +57,8 @@ Here is a list of options to tune what will be processed by reverse engineering: - *Use Java primitive types*: Use primitive types (e.g. *int*) or Object types (e.g. *java.lang.Integer*). +- *Use case sensitive naming*: Use case sensitive naming (e.g. "Name", "NAME") for tables, attributes etc. + - *Use old java.util.Date type*: Use *java.util.Date* for all columns with *DATE/TIME/TIMESTAMP* types. By default *java.time.* types will be used. ==== DataSource selection diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/gradle-plugin.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/gradle-plugin.adoc index 85d98f68b9..b414d74e89 100644 --- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/gradle-plugin.adoc +++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/gradle-plugin.adoc @@ -96,6 +96,7 @@ cdbimport { dbImport { // additional settings usePrimitives false + useCaseSensitiveNaming true defaultPackage 'org.apache.cayenne.test' // DB filter configuration diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/maven-plugin.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/maven-plugin.adoc index 510bf4c1ec..f46bbdae20 100644 --- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/maven-plugin.adoc +++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part6/maven-plugin.adoc @@ -263,6 +263,10 @@ a|Regex that matches the part of the table name that needs to be stripped off wh .^|boolean .^|Whether numeric and boolean data types should be mapped as Java primitives or Java classes. Default is "true", i.e. primitives will be used. +.^|useCaseSensitiveNaming +.^|boolean +.^|If the database uses case-sensitive naming, this option helps to convey the same names with different case-type letters. The default is "false", i.e. case-insensitive naming will be used. Note that if the database uses different case-type letters, merges are possible without this option. + .^|useJava7Types .^|boolean .^|Whether _DATE_, _TIME_ and _TIMESTAMP_ data types should be mapped as `java.util.Date` or `java.time.* classes`. Default is "false", i.e. `java.time.*` will be used. @@ -320,6 +324,7 @@ Example - loading a DB schema from a local HSQLDB database (essentially a revers com.example.cayenne + true diff --git a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java index 94a5c15998..1f807e9839 100644 --- a/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java +++ b/maven-plugins/cayenne-maven-plugin/src/main/java/org/apache/cayenne/tools/DbImporterMojo.java @@ -177,6 +177,7 @@ DbImportConfiguration createConfig(final Logger logger) { config.setUrl(dataSource.getUrl()); config.setUsername(dataSource.getUsername()); config.setUsePrimitives(dbImportConfig.isUsePrimitives()); + config.setUseCaseSensitiveNaming(dbImportConfig.isUseCaseSensitiveNaming()); config.setUseJava7Types(dbImportConfig.isUseJava7Types()); return config; diff --git a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java index 6ca8ef2ac0..5a72ee189b 100644 --- a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java +++ b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoConfigurationTest.java @@ -76,10 +76,10 @@ public void testLoadSchema2() throws Exception { FiltersConfig filters = dbImportConfiguration.getDbLoaderConfig().getFiltersConfig(); TreeSet includes = new TreeSet<>(); - includes.add(new IncludeTableFilter(null, new PatternFilter().exclude("^ETL_.*"))); + includes.add(new IncludeTableFilter(null, new PatternFilter(false).exclude("^ETL_.*"), false)); TreeSet excludes = new TreeSet<>(PatternFilter.PATTERN_COMPARATOR); - excludes.add(PatternFilter.pattern("^ETL_.*")); + excludes.add(PatternFilter.pattern("^ETL_.*", false)); assertEquals(filters.tableFilter(null, "NHL_STATS"), new TableFilter(includes, excludes)); diff --git a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java index 24657a98ce..ff61c9333c 100644 --- a/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java +++ b/maven-plugins/cayenne-maven-plugin/src/test/java/org/apache/cayenne/tools/DbImporterMojoTest.java @@ -128,6 +128,21 @@ public void testImportAddTableAndColumn() throws Exception { test("testImportAddTableAndColumn"); } + @Test + public void testImportAddTableCaseSensitiveNaming() throws Exception { + test("testImportAddTableCaseSensitiveNaming", true); + } + + @Test + public void testImportAddColumnCaseSensitiveNaming() throws Exception { + test("testImportAddColumnCaseSensitiveNaming", true); + } + + @Test + public void testImportNewRelationshipCaseSensitiveNaming() throws Exception { + test("testImportNewRelationshipCaseSensitiveNaming", true); + } + @Test public void testFilteringWithSchema() throws Exception { test("testFilteringWithSchema"); @@ -306,6 +321,11 @@ public void testImportProcedure() throws Exception { test("testImportProcedure"); } + @Test + public void testImportProcedureCaseSensitiveNaming() throws Exception { + test("testImportProcedureCaseSensitiveNaming", true); + } + @Test public void testDropProcedure() throws Exception { test("testDropProcedure"); @@ -389,9 +409,10 @@ public void testSupportsCatalogsOnReverseEngineering() throws Exception { assertEquals(exceptedMessage, exceptedException.getCause().getMessage()); } - private void test(String name) throws Exception { + private void test(String name, boolean useCaseSensitiveNaming) throws Exception { DbImporterMojo cdbImport = getCdbImport("dbimport/" + name + "-pom.xml"); File mapFile = cdbImport.getMap(); + cdbImport.getReverseEngineering().setUseCaseSensitiveNaming(useCaseSensitiveNaming); File mapFileCopy = new File(mapFile.getParentFile(), "copy-" + mapFile.getName()); if (mapFile.exists()) { FileUtils.copyFile(mapFile, mapFileCopy); @@ -411,6 +432,10 @@ private void test(String name) throws Exception { } } + private void test(String name) throws Exception { + test(name, false); + } + private void cleanDb(DbImportDataSourceConfig dataSource) throws Exception { // TODO: refactor to common DB management code... E.g. bootique-jdbc-test? @@ -433,14 +458,14 @@ private void cleanDb(DbImportDataSourceConfig dataSource) throws Exception { while (tables.next()) { String schema = tables.getString("TABLE_SCHEM"); String tableName = tables.getString("TABLE_NAME"); - String tableNameFull = (isBlank(schema) ? "" : schema + ".") + tableName; + String tableNameFull = (isBlank(schema) ? "" : "\"" + schema + "\".") + "\"" + tableName + "\""; ResultSet keys = connection.getMetaData().getExportedKeys(null, schema, tableName); while (keys.next()) { String fkTableSchem = keys.getString("FKTABLE_SCHEM"); String fkTableName = keys.getString("FKTABLE_NAME"); - String fkTableNameFull = (isBlank(fkTableSchem) ? "" : fkTableSchem + ".") + fkTableName; - execute(stmt, "ALTER TABLE " + fkTableNameFull + " DROP CONSTRAINT " + keys.getString("FK_NAME")); + String fkTableNameFull = (isBlank(fkTableSchem) ? "" : "\"" + fkTableSchem + "\".") + "\"" + fkTableName + "\""; + execute(stmt, "ALTER TABLE " + fkTableNameFull + " DROP CONSTRAINT \"" + keys.getString("FK_NAME") + "\""); } String sql = "DROP TABLE " + tableNameFull; @@ -449,11 +474,11 @@ private void cleanDb(DbImportDataSourceConfig dataSource) throws Exception { } try(ResultSet procedures = connection.getMetaData() - .getProcedures(null, null,"PROC")) { + .getProcedures(null, null,"PRO_")) { while(procedures.next()) { String schema = procedures.getString("PROCEDURE_SCHEM"); String name = procedures.getString("PROCEDURE_NAME"); - execute(stmt, "DROP PROCEDURE " + (isBlank(schema) ? "" : schema + ".") + name); + execute(stmt, "DROP PROCEDURE " + (isBlank(schema) ? "" : schema + ".") + "\"" + name + "\""); } } diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testConfigFromDataMap.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testConfigFromDataMap.map.xml-result index 676d6cc202..963afd59e6 100644 --- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testConfigFromDataMap.map.xml-result +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testConfigFromDataMap.map.xml-result @@ -44,5 +44,6 @@ false false true + false diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming-pom.xml new file mode 100644 index 0000000000..0c576e36a7 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming-pom.xml @@ -0,0 +1,47 @@ + + + + + DbImporterMojo Test1 + org.apache.maven.plugin-testing + maven-plugin-testing + 1.0-SNAPSHOT + + 4.0.0 + + + + cayenne-maven-plugin + + target/test-classes/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:memory:DbImporterMojoTest;create=true + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml new file mode 100644 index 0000000000..090cd8919f --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml-result new file mode 100644 index 0000000000..2c4002a751 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.map.xml-result @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.sql b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.sql new file mode 100644 index 0000000000..c14386c4d3 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddColumnCaseSensitiveNaming.sql @@ -0,0 +1,33 @@ +-- 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. + +CREATE TABLE "CHILD" ( + id INTEGER NOT NULL, + COL2 CHAR(25), + COL3 DECIMAL(10,2), + + PRIMARY KEY (id), + UNIQUE (COL3) +); + +CREATE TABLE "child" ( + id INTEGER NOT NULL, + "COL2" CHAR(25), + "col2" DECIMAL(10,2), + + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming-pom.xml new file mode 100644 index 0000000000..8fc38c8512 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming-pom.xml @@ -0,0 +1,47 @@ + + + + + DbImporterMojo Test1 + org.apache.maven.plugin-testing + maven-plugin-testing + 1.0-SNAPSHOT + + 4.0.0 + + + + cayenne-maven-plugin + + target/test-classes/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:memory:DbImporterMojoTest;create=true + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml new file mode 100644 index 0000000000..090cd8919f --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml-result new file mode 100644 index 0000000000..ff0a1a7a2a --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.map.xml-result @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.sql b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.sql new file mode 100644 index 0000000000..dcf8d49a5c --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportAddTableCaseSensitiveNaming.sql @@ -0,0 +1,33 @@ +-- 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. + +CREATE TABLE "CHILD" ( + id INTEGER NOT NULL, + COL2 CHAR(25), + COL3 DECIMAL(10,2), + + PRIMARY KEY (id), + UNIQUE (COL3) +); + +CREATE TABLE "child" ( + id INTEGER NOT NULL, + COL2 CHAR(25), + COL3 DECIMAL(10,2), + + PRIMARY KEY (id) +); \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming-pom.xml new file mode 100644 index 0000000000..17bb5e00b0 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming-pom.xml @@ -0,0 +1,50 @@ + + + + + DbImporterMojo Test1 + org.apache.maven.plugin-testing + maven-plugin-testing + 1.0-SNAPSHOT + + 4.0.0 + + + + cayenne-maven-plugin + + target/test-classes/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:memory:DbImporterMojoTest;create=true + + + SCHEMA_01 + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml new file mode 100644 index 0000000000..eed2270440 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml-result new file mode 100644 index 0000000000..6b5bb2f476 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.map.xml-result @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.sql b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.sql new file mode 100644 index 0000000000..42d422a7a0 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportNewRelationshipCaseSensitiveNaming.sql @@ -0,0 +1,41 @@ +-- 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. + +CREATE SCHEMA schema_01; +SET SCHEMA schema_01; + +CREATE TABLE schema_01."TABLE1" ( + id INTEGER NOT NULL, + t1_name VARCHAR (45), + PRIMARY KEY (id) +); + +CREATE TABLE schema_01."table1" ( + id INTEGER NOT NULL, + t3_name VARCHAR (45), + PRIMARY KEY (id) +); + +CREATE TABLE schema_01.table2 ( + id INTEGER NOT NULL, + t2_name VARCHAR (45), + "TABLE1_id" INTEGER NOT NULL, + "table1_id" INTEGER NOT NULL, + PRIMARY KEY (id), + CONSTRAINT fk_table2_table1b_id FOREIGN KEY ("TABLE1_id") REFERENCES schema_01."TABLE1" (id), + CONSTRAINT fk_table2_table1_id FOREIGN KEY ("table1_id") REFERENCES schema_01."table1" (id) +); diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming-pom.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming-pom.xml new file mode 100644 index 0000000000..4d631afca9 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming-pom.xml @@ -0,0 +1,51 @@ + + + + + DbImporterMojo Test1 + org.apache.maven.plugin-testing + maven-plugin-testing + 1.0-SNAPSHOT + + 4.0.0 + + + + cayenne-maven-plugin + + target/test-classes/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml + + org.apache.derby.jdbc.EmbeddedDriver + jdbc:derby:memory:DbImporterMojoTest;create=true + + + .* + PRO. + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml new file mode 100644 index 0000000000..b8fec94e9a --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml-result new file mode 100644 index 0000000000..a5989dc6e3 --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.map.xml-result @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.sql b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.sql new file mode 100644 index 0000000000..829eb5bcab --- /dev/null +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testImportProcedureCaseSensitiveNaming.sql @@ -0,0 +1,29 @@ +-- 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. + +CREATE SCHEMA schema_01; +SET SCHEMA schema_01; + +CREATE TABLE schema_01.table2 ( + id INTEGER NOT NULL, + t1_name VARCHAR (45), + PRIMARY KEY (id) +); + +CREATE PROCEDURE "PROc"(IN test INTEGER, OUT TOTAL DECIMAL(10,2)) +PARAMETER STYLE JAVA READS SQL DATA LANGUAGE JAVA EXTERNAL NAME +'org.apache.cayenne.test'; \ No newline at end of file diff --git a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypesMap.map.xml-result b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypesMap.map.xml-result index 188266f311..a3ee0fcc57 100644 --- a/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypesMap.map.xml-result +++ b/maven-plugins/cayenne-maven-plugin/src/test/resources/org/apache/cayenne/tools/dbimport/testTableTypesMap.map.xml-result @@ -37,5 +37,6 @@ false false true + false diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java index 2654e230e0..ea47de3579 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/load/DbLoaderContext.java @@ -117,6 +117,7 @@ void setStatusNote(String loadStatusNote) { private void fillReverseEngineeringFromView(ReverseEngineering reverseEngineering, DbImportView view) { reverseEngineering.setUsePrimitives(view.isUsePrimitives()); + reverseEngineering.setUseCaseSensitiveNaming(view.isUseCaseSensitiveNaming()); reverseEngineering.setUseJava7Types(view.isUseJava7Typed()); reverseEngineering.setForceDataMapCatalog(view.isForceDataMapCatalog()); reverseEngineering.setForceDataMapSchema(view.isForceDataMapSchema()); @@ -180,6 +181,7 @@ private void fillConfig(DbImportConfiguration config, DBConnectionInfo connectio config.setDefaultPackage(reverseEngineering.getDefaultPackage()); config.setStripFromTableNames(reverseEngineering.getStripFromTableNames()); config.setUsePrimitives(reverseEngineering.isUsePrimitives()); + config.setUseCaseSensitiveNaming(reverseEngineering.isUseCaseSensitiveNaming()); config.setUseJava7Types(reverseEngineering.isUseJava7Types()); config.setForceDataMapCatalog(reverseEngineering.isForceDataMapCatalog()); config.setForceDataMapSchema(reverseEngineering.isForceDataMapSchema()); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java index 8c0d521ebf..d7395628fd 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/db/merge/MergerOptions.java @@ -73,6 +73,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.function.Function; public class MergerOptions extends CayenneController { @@ -162,6 +163,7 @@ protected void prepareMigrator() { DataMapMerger merger = DataMapMerger.builder(mergerTokenFactory) .filters(filters) + .nameConverter(Function.identity()) .build(); DbLoaderConfiguration config = new DbLoaderConfiguration(); @@ -174,7 +176,8 @@ protected void prepareMigrator() { dbImport = new DbLoader(adapter, conn, config, new LoggingDbLoaderDelegate(LoggerFactory.getLogger(DbLoader.class)), - new DefaultObjectNameGenerator(NoStemStemmer.getInstance())) + new DefaultObjectNameGenerator(NoStemStemmer.getInstance()), + Function.identity()) .load(); } catch (SQLException e) { throw new CayenneRuntimeException("Can't doLoad dataMap from db.", e); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java index 8b85e067c2..8280a761d4 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/CodeGeneratorController.java @@ -26,7 +26,10 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; import java.util.List; +import java.util.TreeSet; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.function.Predicate; @@ -36,9 +39,6 @@ import org.apache.cayenne.configuration.event.DataMapEvent; import org.apache.cayenne.configuration.event.DataMapListener; import org.apache.cayenne.configuration.xml.DataChannelMetaData; -import org.apache.cayenne.di.DIBootstrap; -import org.apache.cayenne.di.Module; -import org.apache.cayenne.di.spi.ModuleLoader; import org.apache.cayenne.gen.CgenConfiguration; import org.apache.cayenne.gen.ClassGenerationAction; import org.apache.cayenne.gen.ClassGenerationActionFactory; @@ -197,8 +197,12 @@ public void enableGenerateButton(boolean enable) { private void prepareClasses(DataMap dataMap) { classes.clear(); classes.add(dataMap); - classes.addAll(dataMap.getObjEntities()); - classes.addAll(dataMap.getEmbeddables()); + TreeSet objEntities = new TreeSet<>(Comparator.comparing(ObjEntity::getName)); + objEntities.addAll(dataMap.getObjEntities()); + classes.addAll(objEntities); + TreeSet embedded = new TreeSet<>(Comparator.comparing(o -> o.getDataMap().getName())); + embedded.addAll(dataMap.getEmbeddables()); + classes.addAll(embedded); selectionModel.initCollectionsForSelection(dataMap); } @@ -208,8 +212,8 @@ private void prepareClasses(DataMap dataMap) { public void createConfiguration(DataMap map) { cgenConfiguration = projectController.getApplication().getMetaData().get(map, CgenConfiguration.class); if (cgenConfiguration != null) { - addToSelectedEntities(cgenConfiguration.getEntities()); - addToSelectedEmbeddables(cgenConfiguration.getEmbeddables()); + updateEntities(); + updateEmbeddables(); cgenConfiguration.setForce(true); return; } @@ -255,7 +259,7 @@ public void createConfiguration(DataMap map) { } public List getClasses() { - return classes; + return Collections.unmodifiableList(classes); } public boolean updateSelection(Predicate predicate) { @@ -379,6 +383,11 @@ public void setInitFromModel(boolean initFromModel) { @Override public void objEntityChanged(EntityEvent e) { + selectionModel.removeFromSelectedEntities(e.getOldName()); + objEntityAdded(e); + if (cgenConfiguration != null) { + cgenConfiguration.getEntities().remove(e.getOldName()); + } } @Override @@ -397,6 +406,7 @@ public void objEntityRemoved(EntityEvent e) { @Override public void embeddableChanged(EmbeddableEvent e, DataMap map) { + selectionModel.removeFromSelectedEmbeddables(e.getOldName()); } @Override diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java index 3ef4a1e3a2..7893095bd9 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/cgen/SelectionModel.java @@ -165,11 +165,25 @@ void removeFromSelectedEntities(ObjEntity objEntity) { selectedEntities.remove(objEntity.getName()); } + /** + * @since 4.2 + */ + void removeFromSelectedEntities(String oldName) { + selectedEntities.remove(oldName); + } + void removeFromSelectedEmbeddables(Embeddable embeddable) { initCollectionsForSelection(embeddable.getDataMap()); selectedEmbeddables.remove(embeddable.getClassName()); } + /** + * @since 4.2 + */ + void removeFromSelectedEmbeddables(String oldName) { + selectedEmbeddables.remove(oldName); + } + void addSelectedEntities(Collection entities) { selectedEntities.addAll(entities); } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java index c99be2658b..59f5275b1b 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/DbImportView.java @@ -245,6 +245,13 @@ public boolean isUsePrimitives() { return configPanel.getUsePrimitives().isSelected(); } + /** + * @since 4.2 + */ + public boolean isUseCaseSensitiveNaming() { + return configPanel.getUseCaseSensitiveNaming().isSelected(); + } + public boolean isUseJava7Typed() { return configPanel.getUseJava7Types().isSelected(); } diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java index c9ce342159..3fa7369241 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/editor/dbimport/ReverseEngineeringConfigPanel.java @@ -53,6 +53,7 @@ public class ReverseEngineeringConfigPanel extends JPanel { private JCheckBox forceDataMapCatalog; private JCheckBox forceDataMapSchema; private JCheckBox usePrimitives; + private JCheckBox useCaseSensitiveNaming; private JCheckBox useJava7Types; private TextAdapter tableTypes; @@ -81,6 +82,7 @@ private void buildView() { panelBuilder.append("Force datamap catalog:", forceDataMapCatalog); panelBuilder.append("Force datamap schema:", forceDataMapSchema); panelBuilder.append("Use Java primitive types:", usePrimitives); + panelBuilder.append("Use case sensitive naming:", useCaseSensitiveNaming); panelBuilder.append("Use java.util.Date type:", useJava7Types); panelBuilder.append("Naming strategy:", strategyCombo); panelBuilder.append("Table types:", tableTypes.getComponent()); @@ -94,6 +96,7 @@ void fillCheckboxes(ReverseEngineering reverseEngineering) { forceDataMapCatalog.setSelected(reverseEngineering.isForceDataMapCatalog()); forceDataMapSchema.setSelected(reverseEngineering.isForceDataMapSchema()); usePrimitives.setSelected(reverseEngineering.isUsePrimitives()); + useCaseSensitiveNaming.setSelected(reverseEngineering.isUseCaseSensitiveNaming()); useJava7Types.setSelected(reverseEngineering.isUseJava7Types()); } @@ -191,6 +194,8 @@ protected void updateModel(String text) throws ValidationException { "By default java.time.* types will be used."); usePrimitives = new JCheckBox(); usePrimitives.setToolTipText("Use primitive types (e.g. int) or Object types (e.g. java.lang.Integer)"); + useCaseSensitiveNaming = new JCheckBox(); + usePrimitives.setToolTipText("Use case sensitive namespace"); } private void initListeners() { @@ -224,6 +229,12 @@ private void initListeners() { projectController.setDirty(true); } }); + useCaseSensitiveNaming.addActionListener(e -> { + getReverseEngineeringBySelectedMap().setUseCaseSensitiveNaming(useCaseSensitiveNaming.isSelected()); + if(!dbImportView.isInitFromModel()) { + projectController.setDirty(true); + } + }); useJava7Types.addActionListener(e -> { getReverseEngineeringBySelectedMap().setUseJava7Types(useJava7Types.isSelected()); if(!dbImportView.isInitFromModel()) { @@ -285,6 +296,13 @@ JCheckBox getUsePrimitives() { return usePrimitives; } + /** + * @since 4.2 + */ + JCheckBox getUseCaseSensitiveNaming() { + return useCaseSensitiveNaming; + } + JCheckBox getUseJava7Types() { return useJava7Types; } From 6882fa5e2abe3fee0e0db7b1c40f265cb81bbd35 Mon Sep 17 00:00:00 2001 From: Oleg Khodokevich Date: Mon, 31 Jan 2022 11:23:00 +0300 Subject: [PATCH 2/5] Added additional validation for quoted strategy. Corrected tests for other DB. --- .github/workflows/github-actions-demo.yml | 66 +++++++++++++++++++ .../dbsync/merge/DbEntityMergerIT.java | 34 ++++++---- .../cayenne/dbsync/merge/MergeCase.java | 49 +++++++++++--- .../cayenne/dbsync/merge/MergerFactoryIT.java | 30 ++++++--- .../merge/token/db/SetPrimaryKeyToDbIT.java | 10 +++ .../merge/token/model/AddColumnToModelIT.java | 17 +++-- .../token/model/CreateTableToModelIT.java | 30 ++++++--- .../token/model/DropColumnToModelIT.java | 2 +- .../model/DropRelationshipToModelIT.java | 18 +++-- .../reverse/dbload/AttributeLoaderIT.java | 11 ++-- .../cayenne/dba/DefaultQuotingStrategy.java | 2 +- 11 files changed, 212 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/github-actions-demo.yml diff --git a/.github/workflows/github-actions-demo.yml b/.github/workflows/github-actions-demo.yml new file mode 100644 index 0000000000..fcac50548e --- /dev/null +++ b/.github/workflows/github-actions-demo.yml @@ -0,0 +1,66 @@ +# 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. + +name: cayenne + +on: [push, pull_request] + +jobs: + test: + runs-on: ubuntu-latest + name: JDK ${{ matrix.java }}, DB ${{ matrix.db-profile }} + continue-on-error: true + strategy: + matrix: + java: [8, 11, 16-ea] + db-profile: [hsql, h2, derby, mysql-tc, postgres-tc, sqlserver-tc] + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up java ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + + - uses: actions/cache@v2 + with: + path: $HOME/.m2 + key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} + restore-keys: ${{ runner.os }}-m2 + + - name: Set up DB ${{ matrix.db-profile }} + run: mvn verify -q -DcayenneTestConnection=${{ matrix.db-profile }} -DcayenneLogLevel=ERROR -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false + +# deploy: +# runs-on: ubuntu-latest +# needs: test +# # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'apache/cayenne' }} +# # env: +# # SNAPSHOT_REPO_USERNAME: ${{ secrets.SNAPSHOT_REPO_USERNAME }} +# # SNAPSHOT_REPO_PASSWORD: ${{ secrets.SNAPSHOT_REPO_PASSWORD }} +# env: +# GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} +# GITHUB_USERNAME: KravchenkoAS +# steps: +# - name: Checkout repository +# uses: actions/checkout@v1 +# - name: Set up java 8 +# uses: actions/setup-java@v1 +# with: +# java-version: 8 +# - name: Deploy +# run: mvn deploy -DskipTests --settings .github/workflows/.settings.xml \ No newline at end of file diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java index b2b335f4e3..711e8fa5c1 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java @@ -49,7 +49,6 @@ public class DbEntityMergerIT extends MergeCase { @Test public void testCreateTokensForMissingImported() throws Exception { - map.setQuotingSQLIdentifiers(true); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_TABLE2"); assertTokensAndExecute(0, 0); @@ -67,6 +66,9 @@ public void testCreateTokensForMissingImported() throws Exception { column2.setPrimaryKey(false); dbEntity1.addAttribute(column2); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity1); + map.addDbEntity(dbEntity1); DbEntity dbEntity2 = new DbEntity("NEW_TABLE2"); @@ -75,12 +77,16 @@ public void testCreateTokensForMissingImported() throws Exception { column3.setPrimaryKey(false); dbEntity2.addAttribute(column3); - DbAttribute column4 = new DbAttribute("NUMBER", Types.INTEGER, dbEntity2); - column3.setMandatory(false); - column3.setPrimaryKey(false); + DbAttribute column4 = new DbAttribute("NUMBER_ID", Types.INTEGER, dbEntity2); + column4.setMandatory(false); + column4.setPrimaryKey(false); column4.setMaxLength(10); dbEntity2.addAttribute(column4); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity2); + map.addDbEntity(dbEntity2); + // create db relationships DbRelationship rel1To2 = new DbRelationship("rel1To2"); rel1To2.setSourceEntity(dbEntity1); @@ -97,8 +103,6 @@ public void testCreateTokensForMissingImported() throws Exception { dbEntity2.addRelationship(rel2To1); // for the new entity to the db - map.addDbEntity(dbEntity1); - map.addDbEntity(dbEntity2); execute(mergerFactory().createCreateTableToDb(dbEntity1)); execute(mergerFactory().createCreateTableToDb(dbEntity2)); execute(mergerFactory().createDropRelationshipToModel(dbEntity1, rel1To2).createReverse(mergerFactory())); @@ -121,13 +125,16 @@ public void testCreateTokensForMissingImported() throws Exception { ObjEntity objEntity1 = null; ObjEntity objEntity2 = null; for (ObjEntity candidate : map.getObjEntities()) { - if (dbEntity1.getName().equals(candidate.getDbEntityName())) { + if (dbEntity1.getName().equalsIgnoreCase(candidate.getDbEntityName())) { objEntity1 = candidate; continue; } - if (dbEntity2.getName().equals(candidate.getDbEntityName())) { + if (dbEntity2.getName().equalsIgnoreCase(candidate.getDbEntityName())) { objEntity2 = candidate; } + if(objEntity1 != null && objEntity2 != null) { + break; + } } assertNotNull(objEntity1); @@ -141,16 +148,15 @@ public void testCreateTokensForMissingImported() throws Exception { ObjRelationship objRelationship1 = iterator1.next(); assertTrue(objRelationship1.isToMany()); + dropTableIfPresent(objEntity2.getDbEntity().getName()); + dropTableIfPresent(objEntity1.getDbEntity().getName()); //clear entity - map.removeDbEntity(dbEntity1.getName()); - map.removeDbEntity(dbEntity2.getName()); + map.removeDbEntity(objEntity1.getDbEntity().getName()); + map.removeDbEntity(objEntity2.getDbEntity().getName()); map.removeObjEntity(objEntity1.getName(), true); map.removeObjEntity(objEntity2.getName(), true); - dropTableIfPresent("NEW_TABLE2"); - dropTableIfPresent("NEW_TABLE"); - assertTokensAndExecute(0, 0, true); + assertTokensAndExecute(0, 0); - map.setQuotingSQLIdentifiers(false); } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java index f4472893e1..8c84848696 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java @@ -42,6 +42,7 @@ import org.apache.cayenne.map.DataMap; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbKeyGenerator; import org.apache.cayenne.map.EntityResolver; import org.apache.cayenne.test.jdbc.DBHelper; import org.apache.cayenne.unit.UnitDbAdapter; @@ -93,16 +94,17 @@ public void setUp() throws Exception { // container // on every test map = runtime.getDataDomain().getDataMap("testmap"); - map.setQuotingSQLIdentifiers(true); - +// map.setQuotingSQLIdentifiers(true); + //to prevent postgresql from creating pk_table +// setPrimaryKeyGeneratorDBGenerateForMap(map); filterDataMap(); - List tokens = createMergeTokens(true); + List tokens = createMergeTokens(); execute(tokens); - assertTokensAndExecute(0, 0, true); - map.setQuotingSQLIdentifiers(false); + assertTokensAndExecute(0, 0); +// map.setQuotingSQLIdentifiers(false); } protected DataMapMerger.Builder merger() { @@ -123,7 +125,6 @@ protected List createMergeTokensWithoutEmptyFilter(boolean useCaseS } private List createMergeTokens(String tableFilterInclude, boolean useCaseSensitiveNaming) { - FiltersConfig filters = FiltersConfig.create(null, null, TableFilter.include(tableFilterInclude, useCaseSensitiveNaming), PatternFilter.INCLUDE_NOTHING); @@ -289,9 +290,8 @@ protected void dropTableIfPresent(String tableName) throws Exception { // must have a dummy datamap for the dummy table for the downstream code // to work DataMap map = new DataMap("dummy"); - map.setQuotingSQLIdentifiers(true); + map.setQuotingSQLIdentifiers(this.map.isQuotingSQLIdentifiers()); - map.setQuotingSQLIdentifiers(map.isQuotingSQLIdentifiers()); DbEntity entity = new DbEntity(tableName); map.addDbEntity(entity); @@ -305,6 +305,37 @@ protected void dropTableIfPresent(String tableName) throws Exception { logger.info("Exception dropping table " + tableName + ", probably abscent.."); } } - map.setQuotingSQLIdentifiers(false); + } + + //Methode sets the DBGenerate for the PrimaryKeyGenerator. pk_table are created with same name in postgres for tables with different case name + protected void setPrimaryKeyGeneratorDBGenerate(DbEntity dbEntity) { + dbEntity.setPrimaryKeyGenerator(new DbKeyGenerator()); + } + + private void setPrimaryKeyGeneratorDBGenerateForMap(DataMap dataMap) { + for (DbEntity dbEntity : dataMap.getDbEntities()) { + if ("ARTIST|GALLERY|PAINTING|NEW_table|NEW_TABLE2?".contains(dbEntity.getName())) { + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity); + } + } + } + + protected List syncDBForCaseSensitiveTest() { + boolean isQuotingSQLIdentifiers = map.isQuotingSQLIdentifiers(); + map.setQuotingSQLIdentifiers(true); + setPrimaryKeyGeneratorDBGenerateForMap(map); + filterDataMap(); + List tokens = createMergeTokens(true); + execute(tokens); + assertTokensAndExecute(0, 0, true); + map.setQuotingSQLIdentifiers(isQuotingSQLIdentifiers); + return tokens; + } + + protected void reverseSyncDBForCaseSensitiveTest(List tokens) throws Exception { + for (MergerToken token: tokens) { + execute(token.createReverse(mergerFactory())); + } } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java index 1813b5f395..e68341220f 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java @@ -23,9 +23,11 @@ import static org.junit.Assert.assertNull; import java.sql.Types; +import java.util.List; import org.apache.cayenne.CayenneDataObject; import org.apache.cayenne.access.DataContext; +import org.apache.cayenne.dbsync.merge.token.MergerToken; import org.apache.cayenne.di.Inject; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; @@ -33,6 +35,7 @@ import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; +import org.junit.Assume; import org.junit.Test; public class MergerFactoryIT extends MergeCase { @@ -301,17 +304,19 @@ public void testAddForeignKeyAfterTable() throws Exception { @Test public void testAddTableWithSameNameInDifferentCapitalization() throws Exception { + // Mariadb don't support the case of binding tables when there are several tables with names in different cases. + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List tokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_table"); - assertTokensAndExecute(0, 0,true); DbEntity dbEntity = new DbEntity("NEW_TABLE"); attr(dbEntity, "ID", Types.INTEGER, true, true); attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10); attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false); - + setPrimaryKeyGeneratorDBGenerate(dbEntity); map.addDbEntity(dbEntity); DbEntity artistDbEntity = map.getDbEntity("ARTIST"); @@ -320,7 +325,7 @@ public void testAddTableWithSameNameInDifferentCapitalization() throws Exception assertTokensAndExecute(1, 0,true); assertTokensAndExecute(0, 0,true); - // relation from new_table to artist + // relation from NEW_TABLE to artist DbRelationship r1 = new DbRelationship("toArtistR1"); r1.setSourceEntity(dbEntity); r1.setTargetEntityName(artistDbEntity); @@ -328,7 +333,7 @@ public void testAddTableWithSameNameInDifferentCapitalization() throws Exception r1.addJoin(new DbJoin(r1, "ARTIST_ID", "ARTIST_ID")); dbEntity.addRelationship(r1); - // relation from artist to new_table + // relation from artist to NEW_TABLE DbRelationship r2 = new DbRelationship("toNewTableR2"); r2.setSourceEntity(artistDbEntity); r2.setTargetEntityName(dbEntity); @@ -343,13 +348,14 @@ public void testAddTableWithSameNameInDifferentCapitalization() throws Exception attr(dbEntity1, "ID", Types.INTEGER, true, true); attr(dbEntity1, "NAME", Types.VARCHAR, false, false).setMaxLength(10); attr(dbEntity1, "ARTIST_ID", Types.BIGINT, false, false); - + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity1); map.addDbEntity(dbEntity1); assertTokensAndExecute(1, 0,true); assertTokensAndExecute(0, 0,true); - // relation from new_table to artist + // relation from NEW_table to artist DbRelationship r3 = new DbRelationship("toArtistR3"); r3.setSourceEntity(dbEntity1); r3.setTargetEntityName(artistDbEntity); @@ -357,7 +363,7 @@ public void testAddTableWithSameNameInDifferentCapitalization() throws Exception r3.addJoin(new DbJoin(r3, "ARTIST_ID", "ARTIST_ID")); dbEntity1.addRelationship(r3); - // relation from artist to new_table + // relation from artist to NEW_table DbRelationship r4 = new DbRelationship("toNewTableR4"); r4.setSourceEntity(artistDbEntity); r4.setTargetEntityName(dbEntity1); @@ -394,13 +400,17 @@ public void testAddTableWithSameNameInDifferentCapitalization() throws Exception assertTokensAndExecute(2, 0,true); assertTokensAndExecute(0, 0,true); - + reverseSyncDBForCaseSensitiveTest(tokens); map.setQuotingSQLIdentifiers(false); } @Test public void testAddAttrWithSameNameInDifferentCapitalization() throws Exception { + // Mariadb don't support the same attributes name in different cases. + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); + map.setQuotingSQLIdentifiers(true); + List tokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0,true); @@ -410,7 +420,8 @@ public void testAddAttrWithSameNameInDifferentCapitalization() throws Exception attr(dbEntity, "NAME", Types.VARCHAR, false, false).setMaxLength(10); attr(dbEntity, "ARTIST_ID", Types.BIGINT, false, false); - map.setQuotingSQLIdentifiers(true); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity); map.addDbEntity(dbEntity); DbEntity artistDbEntity = map.getDbEntity("ARTIST"); @@ -424,6 +435,7 @@ public void testAddAttrWithSameNameInDifferentCapitalization() throws Exception assertTokensAndExecute(1, 0,true); assertTokensAndExecute(0, 0,true); + reverseSyncDBForCaseSensitiveTest(tokens); map.setQuotingSQLIdentifiers(false); } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java index 453eeb3a48..824b366949 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java @@ -20,10 +20,13 @@ package org.apache.cayenne.dbsync.merge.token.db; import java.sql.Types; +import java.util.List; import org.apache.cayenne.dbsync.merge.MergeCase; +import org.apache.cayenne.dbsync.merge.token.MergerToken; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.junit.Assume; import org.junit.Test; public class SetPrimaryKeyToDbIT extends MergeCase { @@ -60,7 +63,10 @@ public void test() throws Exception { @Test public void testCaseSensitiveNaming() throws Exception { + // Mariadb don't support the same attributes name in different cases. + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List tokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0, true); @@ -70,6 +76,9 @@ public void testCaseSensitiveNaming() throws Exception { e1col1.setMandatory(true); e1col1.setPrimaryKey(true); dbEntity1.addAttribute(e1col1); + + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity1); map.addDbEntity(dbEntity1); assertTokensAndExecute(1, 0, true); @@ -93,6 +102,7 @@ public void testCaseSensitiveNaming() throws Exception { dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0, true); + reverseSyncDBForCaseSensitiveTest(tokens); map.setQuotingSQLIdentifiers(false); } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java index d2ef981862..f313779795 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/AddColumnToModelIT.java @@ -34,6 +34,7 @@ import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; +import org.junit.Assume; import org.junit.Test; public class AddColumnToModelIT extends MergeCase { @@ -101,7 +102,10 @@ public void testAddColumn() throws Exception { @Test public void testAddColumnCaseSensitiveNaming() throws Exception { + // Mariadb don't support the same attributes name in different cases. + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List syncTokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0); @@ -121,10 +125,13 @@ public void testAddColumnCaseSensitiveNaming() throws Exception { column3.setMaxLength(10); column3.setMandatory(false); dbEntity.addAttribute(column3); + + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity); map.addDbEntity(dbEntity); - assertTokensAndExecute(1, 0); - assertTokensAndExecute(0, 0); + assertTokensAndExecute(1, 0, true); + assertTokensAndExecute(0, 0, true); ObjEntity objEntity = new ObjEntity("NewTable"); objEntity.setDbEntity(dbEntity); @@ -165,8 +172,10 @@ public void testAddColumnCaseSensitiveNaming() throws Exception { assertNull(map.getDbEntity(dbEntity.getName())); assertFalse(map.getDbEntities().contains(dbEntity)); - assertTokensAndExecute(1, 0); - assertTokensAndExecute(0, 0); + assertTokensAndExecute(1, 0, true); + assertTokensAndExecute(0, 0, true); + + reverseSyncDBForCaseSensitiveTest(syncTokens); map.setQuotingSQLIdentifiers(false); } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java index 739ad3e989..a54e3930bd 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java @@ -36,6 +36,7 @@ import org.apache.cayenne.map.DbJoin; import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.ObjEntity; +import org.junit.Assume; import org.junit.Test; public class CreateTableToModelIT extends MergeCase { @@ -103,7 +104,9 @@ public void testAddTable() throws Exception { @Test public void testAddTableCaseSensitive() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List syncTokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_table"); assertTokensAndExecute(0, 0); @@ -128,13 +131,17 @@ public void testAddTableCaseSensitive() throws Exception { column3.setPrimaryKey(true); dbEntity1.addAttribute(column3); - DbAttribute column4 = new DbAttribute("NUMBER", Types.INTEGER, dbEntity1); + DbAttribute column4 = new DbAttribute("NUMBER_ID", Types.INTEGER, dbEntity1); column4.setMaxLength(10); column4.setMandatory(false); dbEntity1.addAttribute(column4); - // for the new entity to the db + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity); map.addDbEntity(dbEntity); + + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity1); map.addDbEntity(dbEntity1); execute(mergerFactory().createCreateTableToDb(dbEntity)); execute(mergerFactory().createCreateTableToDb(dbEntity1)); @@ -165,10 +172,10 @@ public void testAddTableCaseSensitive() throws Exception { assertEquals(objEntity1.getClientSuperClassName(), map.getDefaultClientSuperclass()); assertEquals(1, objEntity1.getAttributes().size()); - assertEquals("java.lang.Integer", objEntity1.getAttributes().iterator().next().getType()); + assertTrue("java.lang.Integer".equals(objEntity1.getAttributes().iterator().next().getType()) || + "java.math.BigDecimal".equals(objEntity1.getAttributes().iterator().next().getType())); // clear up - // fix psql case issue map.removeDbEntity(objEntity1.getDbEntity().getName(), true); map.removeObjEntity(objEntity1.getName(), true); map.removeDbEntity(dbEntity1.getName(), true); @@ -193,18 +200,20 @@ public void testAddTableCaseSensitive() throws Exception { assertTokensAndExecute(2, 0, true); assertTokensAndExecute(0, 0, true); + reverseSyncDBForCaseSensitiveTest(syncTokens); map.setQuotingSQLIdentifiers(false); } @Test - public void testAddTableWithRelationship() throws Exception { + public void testAddTableCaseSensitiveWithRelationship() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List syncTokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_table"); assertTokensAndExecute(0, 0); DbEntity dbEntity1 = new DbEntity("NEW_TABLE"); - DbAttribute column1 = new DbAttribute("ID", Types.INTEGER, dbEntity1); column1.setMandatory(true); column1.setPrimaryKey(true); @@ -215,6 +224,9 @@ public void testAddTableWithRelationship() throws Exception { column2.setMandatory(false); dbEntity1.addAttribute(column2); + setPrimaryKeyGeneratorDBGenerate(dbEntity1); + map.addDbEntity(dbEntity1); + DbEntity dbEntity2 = new DbEntity("NEW_table"); DbAttribute column3 = new DbAttribute("ID", Types.INTEGER, dbEntity2); @@ -227,6 +239,9 @@ public void testAddTableWithRelationship() throws Exception { column4.setMandatory(false); dbEntity2.addAttribute(column4); + setPrimaryKeyGeneratorDBGenerate(dbEntity2); + map.addDbEntity(dbEntity2); + // create db relationships DbRelationship rel1To2 = new DbRelationship("rel1To2"); rel1To2.setSourceEntity(dbEntity1); @@ -243,8 +258,6 @@ public void testAddTableWithRelationship() throws Exception { dbEntity2.addRelationship(rel2To1); // for the new entity to the db - map.addDbEntity(dbEntity1); - map.addDbEntity(dbEntity2); execute(mergerFactory().createCreateTableToDb(dbEntity1)); execute(mergerFactory().createCreateTableToDb(dbEntity2)); map.removeDbEntity(dbEntity1.getName()); @@ -285,6 +298,7 @@ public void testAddTableWithRelationship() throws Exception { dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0, true); + reverseSyncDBForCaseSensitiveTest(syncTokens); map.setQuotingSQLIdentifiers(false); } } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java index 69e5cc3163..c32f73b049 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java @@ -126,7 +126,7 @@ public void testRemoveFKColumnWithoutRelationshipInDb() throws Exception { e2col1.setMandatory(true); e2col1.setPrimaryKey(true); dbEntity2.addAttribute(e2col1); - DbAttribute e2col2 = new DbAttribute("FK", Types.INTEGER, dbEntity2); + DbAttribute e2col2 = new DbAttribute("FK_ID", Types.INTEGER, dbEntity2); dbEntity2.addAttribute(e2col2); DbAttribute e2col3 = new DbAttribute("NAME", Types.VARCHAR, dbEntity2); e2col3.setMaxLength(10); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java index 9a52f062b9..286cfc2035 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java @@ -37,6 +37,7 @@ import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.map.ObjRelationship; +import org.junit.Assume; import org.junit.Test; public class DropRelationshipToModelIT extends MergeCase { @@ -192,7 +193,9 @@ public void testForeignKey() throws Exception { @Test public void testForeignKeyCaseSensitiveNaming() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsCaseSensitiveLike()); map.setQuotingSQLIdentifiers(true); + List syncTokens = syncDBForCaseSensitiveTest(); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_TABLE2"); dropTableIfPresent("NEW_table"); @@ -211,6 +214,8 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { e1col2.setMandatory(false); dbEntity1.addAttribute(e1col2); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity1); map.addDbEntity(dbEntity1); DbEntity dbEntity2 = new DbEntity("NEW_TABLE2"); @@ -224,9 +229,10 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { e2col3.setMaxLength(10); dbEntity2.addAttribute(e2col3); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity2); map.addDbEntity(dbEntity2); - DbEntity dbEntity3 = new DbEntity("NEW_table"); DbAttribute e3col1 = new DbAttribute("ID", Types.INTEGER, dbEntity3); @@ -239,6 +245,8 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { e3col2.setMandatory(false); dbEntity3.addAttribute(e3col2); + //to prevent postgresql from creating pk_table + setPrimaryKeyGeneratorDBGenerate(dbEntity3); map.addDbEntity(dbEntity3); // create db relationships @@ -344,8 +352,7 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { List tokens = createMergeTokens(true); /** - * Drop Relationship NEW_TABLE2->NEW_TABLE To DB - * Drop Column NEW_TABLE2.FK To DB + * Drop Relationship NEW_TABLE2->NEW_table To DB * */ assertTokens(tokens, 1, 0); for (MergerToken token : tokens) { @@ -358,11 +365,9 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { dbEntity2.addRelationship(rel2To3); dbEntity3.addRelationship(rel3To2); - // try do use the merger to remove the relationship in the model + // try do use the merger to remove the relationship NEW_TABLE2->NEW_table To DB in the model tokens = createMergeTokens(true); assertTokens(tokens, 1, 0); - // TODO: reversing the following two tokens should also reverse the - // order MergerToken token0 = tokens.get(0).createReverse(mergerFactory()); if (!(token0 instanceof DropRelationshipToModel)) { fail(); @@ -411,6 +416,7 @@ public void testForeignKeyCaseSensitiveNaming() throws Exception { dropTableIfPresent("NEW_TABLE2"); assertTokensAndExecute(0, 0, true); + reverseSyncDBForCaseSensitiveTest(syncTokens); map.setQuotingSQLIdentifiers(false); } } 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 d811e488c7..1828dc9cd6 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 @@ public void testAttributeLoad() throws Exception { DbEntity artist = getDbEntity("ARTIST"); DbAttribute a = getDbAttribute(artist, "ARTIST_ID"); assertNotNull(a); + //For oracle type numeric if(accessStackAdapter.onlyGenericNumberType()) { - assertEquals(Types.INTEGER, a.getType()); + assertTrue(Types.INTEGER == a.getType() || Types.NUMERIC == a.getType()); } else { assertEquals(Types.BIGINT, a.getType()); } @@ -105,15 +106,15 @@ public void testAttributeLoadTypes() throws Exception { // 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()); + // check integer. For oracle type numeric + assertTrue(msgForTypeMismatch(Types.INTEGER, integerAttr), Types.INTEGER == integerAttr.getType() || Types.NUMERIC == decimalAttr.getType()); // check float assertTrue(msgForTypeMismatch(Types.FLOAT, floatAttr), Types.FLOAT == floatAttr.getType() || Types.DOUBLE == floatAttr.getType() || Types.REAL == floatAttr.getType()); - // check smallint + // check smallint. For oracle type numeric assertTrue(msgForTypeMismatch(Types.SMALLINT, smallintAttr), Types.SMALLINT == smallintAttr.getType() - || Types.INTEGER == smallintAttr.getType()); + || Types.INTEGER == smallintAttr.getType() || Types.NUMERIC == decimalAttr.getType()); } private void assertGenerated() { diff --git a/cayenne-server/src/main/java/org/apache/cayenne/dba/DefaultQuotingStrategy.java b/cayenne-server/src/main/java/org/apache/cayenne/dba/DefaultQuotingStrategy.java index f61a71016e..0496f71806 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/dba/DefaultQuotingStrategy.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/dba/DefaultQuotingStrategy.java @@ -89,7 +89,7 @@ public String quotedIdentifier(DataMap dataMap, String... identifierParts) { StringBuilder buffer = new StringBuilder(); for (String part : identifierParts) { - if (part == null) { + if (part == null || part.isEmpty()) { continue; } if (buffer.length() > 0) { From 4be04f205aa59c20c6190ae9b02847340fe066b9 Mon Sep 17 00:00:00 2001 From: Oleg Khodokevich Date: Mon, 31 Jan 2022 11:51:49 +0300 Subject: [PATCH 3/5] Corrected MergeCase for postgres. --- .../java/org/apache/cayenne/dbsync/merge/MergeCase.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java index 8c84848696..4832fdf731 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java @@ -94,9 +94,9 @@ public void setUp() throws Exception { // container // on every test map = runtime.getDataDomain().getDataMap("testmap"); -// map.setQuotingSQLIdentifiers(true); + map.setQuotingSQLIdentifiers(true); //to prevent postgresql from creating pk_table -// setPrimaryKeyGeneratorDBGenerateForMap(map); + setPrimaryKeyGeneratorDBGenerateForMap(map); filterDataMap(); List tokens = createMergeTokens(); @@ -104,7 +104,7 @@ public void setUp() throws Exception { execute(tokens); assertTokensAndExecute(0, 0); -// map.setQuotingSQLIdentifiers(false); + map.setQuotingSQLIdentifiers(false); } protected DataMapMerger.Builder merger() { From 9838f71bbac1bac990ba8c321255830fe77e3234 Mon Sep 17 00:00:00 2001 From: Oleg Khodokevich Date: Tue, 1 Feb 2022 15:47:17 +0300 Subject: [PATCH 4/5] Corrected tokens creating and tests for SQLite. --- .../apache/cayenne/dbsync/DbSyncModule.java | 5 +- .../factory/SQLiteMergerTokenFactory.java | 155 ++++++++++++++++++ .../dbsync/merge/DbEntityMergerIT.java | 2 + .../cayenne/dbsync/merge/MergeCase.java | 33 +++- .../cayenne/dbsync/merge/MergerFactoryIT.java | 7 + .../dbsync/merge/token/ValueForNullIT.java | 2 + .../merge/token/db/SetAllowNullToDbIT.java | 2 + .../token/db/SetGeneratedFlagToDbIT.java | 4 +- .../merge/token/db/SetNotNullToDbIT.java | 2 + .../merge/token/db/SetPrimaryKeyToDbIT.java | 1 + .../token/model/CreateTableToModelIT.java | 4 +- .../token/model/DropColumnToModelIT.java | 2 + .../model/DropRelationshipToModelIT.java | 1 + .../reverse/dbload/AttributeLoaderIT.java | 3 + .../dbsync/reverse/dbload/DbLoaderIT.java | 2 + .../cayenne/unit/SQLiteUnitDbAdapter.java | 4 + .../ServerCaseDataSourceInfoProvider.java | 2 +- .../dialog/db/merge/MergerOptions.java | 7 +- .../cayenne/modeler/util/AdapterMapping.java | 2 +- pom.xml | 2 +- 20 files changed, 230 insertions(+), 12 deletions(-) create mode 100644 cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLiteMergerTokenFactory.java diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java index 2bcd0cfbb0..4ceab8982e 100644 --- a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/DbSyncModule.java @@ -30,6 +30,7 @@ import org.apache.cayenne.dba.oracle.Oracle8Adapter; import org.apache.cayenne.dba.oracle.OracleAdapter; import org.apache.cayenne.dba.postgres.PostgresAdapter; +import org.apache.cayenne.dba.sqlite.SQLiteAdapter; import org.apache.cayenne.dba.sqlserver.SQLServerAdapter; import org.apache.cayenne.dba.sybase.SybaseAdapter; import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider; @@ -46,6 +47,7 @@ import org.apache.cayenne.dbsync.merge.factory.OracleMergerTokenFactory; import org.apache.cayenne.dbsync.merge.factory.PostgresMergerTokenFactory; import org.apache.cayenne.dbsync.merge.factory.SQLServerMergerTokenFactory; +import org.apache.cayenne.dbsync.merge.factory.SQLiteMergerTokenFactory; import org.apache.cayenne.dbsync.merge.factory.SybaseMergerTokenFactory; import org.apache.cayenne.di.Binder; import org.apache.cayenne.di.MapBuilder; @@ -84,7 +86,8 @@ public void configure(Binder binder) { .put(Oracle8Adapter.class.getName(), OracleMergerTokenFactory.class) .put(PostgresAdapter.class.getName(), PostgresMergerTokenFactory.class) .put(SQLServerAdapter.class.getName(), SQLServerMergerTokenFactory.class) - .put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class); + .put(SybaseAdapter.class.getName(), SybaseMergerTokenFactory.class) + .put(SQLiteAdapter.class.getName(), SQLiteMergerTokenFactory.class); binder.bind(MergerTokenFactoryProvider.class).to(MergerTokenFactoryProvider.class); diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLiteMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLiteMergerTokenFactory.java new file mode 100644 index 0000000000..88ba340dd7 --- /dev/null +++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLiteMergerTokenFactory.java @@ -0,0 +1,155 @@ +/***************************************************************** + * 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.dbsync.merge.factory; + +import org.apache.cayenne.CayenneRuntimeException; +import org.apache.cayenne.dba.DbAdapter; +import org.apache.cayenne.dbsync.merge.token.MergerToken; +import org.apache.cayenne.dbsync.merge.token.ValueForNullProvider; +import org.apache.cayenne.dbsync.merge.token.db.AddRelationshipToDb; +import org.apache.cayenne.dbsync.merge.token.db.DropRelationshipToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetAllowNullToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetColumnTypeToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetGeneratedFlagToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetNotNullToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetPrimaryKeyToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetValueForNullToDb; +import org.apache.cayenne.map.DbAttribute; +import org.apache.cayenne.map.DbEntity; +import org.apache.cayenne.map.DbRelationship; + +import java.util.Collection; +import java.util.List; +import java.util.function.Function; + +/** + * @since 4.3 + */ +public class SQLiteMergerTokenFactory extends DefaultMergerTokenFactory { + + @Override + public MergerToken createSetColumnTypeToDb( + final DbEntity entity, + final DbAttribute columnOriginal, + final DbAttribute columnNew) { + return new SetColumnTypeToDb(entity, columnOriginal, columnNew) { + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support altering column type."); + } + + }; + } + + @Override + public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) { + return new SetNotNullToDb(entity, column) { + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support adding constrains to existing column."); + } + + }; + } + + @Override + public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) { + return new SetAllowNullToDb(entity, column) { + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support changing constrains."); + } + + }; + } + + @Override + public MergerToken createSetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider) { + return new SetValueForNullToDb(entity, column, valueForNullProvider){ + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support adding constrains to existing column."); + } + + }; + } + + @Override + public MergerToken createSetPrimaryKeyToDb( + DbEntity entity, + Collection primaryKeyOriginal, + Collection primaryKeyNew, + String detectedPrimaryKeyName, + Function nameConverter) { + return new SetPrimaryKeyToDb( + entity, + primaryKeyOriginal, + primaryKeyNew, + detectedPrimaryKeyName, + nameConverter){ + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support adding constrains to existing column."); + } + + }; + } + + @Override + public MergerToken createSetGeneratedFlagToDb(DbEntity entity, DbAttribute column, boolean isGenerated) { + return new SetGeneratedFlagToDb(entity, column, isGenerated){ + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support adding constrains to existing column."); + } + + }; + } + + @Override + public MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel) { + return new DropRelationshipToDb(entity, rel){ + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support removing constrains."); + } + + }; + } + + @Override + public MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel) { + return new AddRelationshipToDb(entity, rel){ + + @Override + public List createSql(DbAdapter adapter) { + throw new CayenneRuntimeException("SQLite doesn't support adding FK to existing column."); + } + + }; + } +} \ No newline at end of file diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java index 711e8fa5c1..329aa3f060 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/DbEntityMergerIT.java @@ -29,6 +29,7 @@ import org.apache.cayenne.map.DbRelationship; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.map.ObjRelationship; +import org.junit.Assume; import org.junit.Test; import java.sql.Types; @@ -49,6 +50,7 @@ public class DbEntityMergerIT extends MergeCase { @Test public void testCreateTokensForMissingImported() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_TABLE2"); assertTokensAndExecute(0, 0); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java index 4832fdf731..ae29990125 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergeCase.java @@ -28,7 +28,14 @@ import org.apache.cayenne.dbsync.merge.factory.MergerTokenFactoryProvider; import org.apache.cayenne.dbsync.merge.token.db.AbstractToDbToken; import org.apache.cayenne.dbsync.merge.token.MergerToken; +import org.apache.cayenne.dbsync.merge.token.db.AddRelationshipToDb; +import org.apache.cayenne.dbsync.merge.token.db.DropRelationshipToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetAllowNullToDb; import org.apache.cayenne.dbsync.merge.token.db.SetColumnTypeToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetGeneratedFlagToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetNotNullToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetPrimaryKeyToDb; +import org.apache.cayenne.dbsync.merge.token.db.SetValueForNullToDb; import org.apache.cayenne.dbsync.naming.DefaultObjectNameGenerator; import org.apache.cayenne.dbsync.naming.NoStemStemmer; import org.apache.cayenne.dbsync.reverse.dbload.DbLoader; @@ -117,7 +124,7 @@ protected List createMergeTokens() { } protected List createMergeTokens(boolean useCaseSensitiveNaming) { - return filterEmpty(createMergeTokensWithoutEmptyFilter(useCaseSensitiveNaming)); + return filterNotValid(createMergeTokensWithoutEmptyFilter(useCaseSensitiveNaming)); } protected List createMergeTokensWithoutEmptyFilter(boolean useCaseSensitiveNaming) { @@ -190,15 +197,33 @@ private static boolean isDateTimeType(int type) { return type == Types.DATE || type == Types.TIME || type == Types.TIMESTAMP; } - protected List filterEmpty(List tokens) { + protected List filterNotValid(List tokens) { List tokensOut = new ArrayList<>(); for(MergerToken token : tokens) { - if(!token.isEmpty()) { + if(validateToken(token)) { tokensOut.add(token); } } return tokensOut; } + + private boolean validateToken(MergerToken token) { + if (token.isEmpty()) { + return false; + } + if (!accessStackAdapter.supportsFKConstraints() + && (token instanceof AddRelationshipToDb + || token instanceof DropRelationshipToDb)) { + return false; + } + return accessStackAdapter.supportsColumnTypeReengineering() + || !(token instanceof SetColumnTypeToDb + || token instanceof SetNotNullToDb + || token instanceof SetAllowNullToDb + || token instanceof SetGeneratedFlagToDb + || token instanceof SetPrimaryKeyToDb + || token instanceof SetValueForNullToDb); + } /** * Remote binary pk {@link DbEntity} for {@link DbAdapter} not supporting @@ -276,7 +301,7 @@ protected void assertTokensAndExecute(int expectedToDb, int expectedToModel) { protected void assertTokensAndExecute(int expectedToDb, int expectedToModel, boolean useCaseSensitiveNaming) { List tokens = createMergeTokens(useCaseSensitiveNaming); - tokens = filterEmpty(tokens); + tokens = filterNotValid(tokens); assertTokens(tokens, expectedToDb, expectedToModel); execute(tokens); } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java index e68341220f..a78c3acd6b 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/MergerFactoryIT.java @@ -67,6 +67,7 @@ public void testAddAndDropColumnToDb() throws Exception { @Test public void testChangeVarcharSizeToDb() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DbEntity dbEntity = map.getDbEntity("PAINTING"); assertNotNull(dbEntity); @@ -119,6 +120,10 @@ public void testMultipleTokensToDb() throws Exception { column1.setMaxLength(20); column2.setMaxLength(30); + if (!accessStackAdapter.supportsColumnTypeReengineering()) { + assertTokensAndExecute(0, 0); + return; + } // merge to db assertTokensAndExecute(2, 0); @@ -184,6 +189,7 @@ public void testAddTableToDb() throws Exception { @Test public void testAddForeignKeyWithTable() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0); @@ -243,6 +249,7 @@ public void testAddForeignKeyWithTable() throws Exception { @Test public void testAddForeignKeyAfterTable() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java index 701e6fcaae..9eb7c07752 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/ValueForNullIT.java @@ -38,6 +38,7 @@ import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.query.ObjectSelect; import org.apache.cayenne.testdo.testmap.Painting; +import org.junit.Assume; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -53,6 +54,7 @@ public class ValueForNullIT extends MergeCase { @Test public void test() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DbEntity dbEntity = map.getDbEntity("PAINTING"); assertNotNull(dbEntity); ObjEntity objEntity = map.getObjEntity("Painting"); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetAllowNullToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetAllowNullToDbIT.java index e14f0814df..6167d0423b 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetAllowNullToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetAllowNullToDbIT.java @@ -26,12 +26,14 @@ import org.apache.cayenne.dbsync.merge.MergeCase; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.junit.Assume; import org.junit.Test; public class SetAllowNullToDbIT extends MergeCase { @Test public void test() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DbEntity dbEntity = map.getDbEntity("PAINTING"); assertNotNull(dbEntity); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetGeneratedFlagToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetGeneratedFlagToDbIT.java index bb1c15780d..b36002de40 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetGeneratedFlagToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetGeneratedFlagToDbIT.java @@ -30,6 +30,7 @@ import org.apache.cayenne.map.DbEntity; import org.apache.cayenne.unit.UnitDbAdapter; import org.junit.After; +import org.junit.Assume; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -67,6 +68,7 @@ public class SetGeneratedFlagToDbIT extends MergeCase { @Test public void setGeneratedFlag() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DbEntity dbEntity = createTestTable(false); assertNotNull(dbEntity); @@ -111,7 +113,7 @@ public void dropGeneratedFlag() throws Exception { attribute.setGenerated(false); List tokens = createMergeTokens(); - if(!dbAdapter.supportsGeneratedKeys()) { + if(!dbAdapter.supportsGeneratedKeys() || !accessStackAdapter.supportsColumnTypeReengineering()) { assertEquals(0, tokens.size()); return; } diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetNotNullToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetNotNullToDbIT.java index a288c76153..26d66737c4 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetNotNullToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetNotNullToDbIT.java @@ -26,12 +26,14 @@ import org.apache.cayenne.dbsync.merge.MergeCase; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.junit.Assume; import org.junit.Test; public class SetNotNullToDbIT extends MergeCase { @Test public void test() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DbEntity dbEntity = map.getDbEntity("PAINTING"); assertNotNull(dbEntity); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java index 824b366949..f57619480d 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/db/SetPrimaryKeyToDbIT.java @@ -33,6 +33,7 @@ public class SetPrimaryKeyToDbIT extends MergeCase { @Test public void test() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); dropTableIfPresent("NEW_TABLE"); assertTokensAndExecute(0, 0); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java index a54e3930bd..7126b51f6c 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/CreateTableToModelIT.java @@ -155,7 +155,7 @@ public void testAddTableCaseSensitive() throws Exception { reverseTokens.add(token.createReverse(mergerFactory())); } } - execute(filterEmpty(reverseTokens)); + execute(filterNotValid(reverseTokens)); ObjEntity objEntity1 = null; for (ObjEntity candidate : map.getObjEntities()) { @@ -270,7 +270,7 @@ public void testAddTableCaseSensitiveWithRelationship() throws Exception { reverseTokens.add(token.createReverse(mergerFactory())); } } - execute(filterEmpty(reverseTokens)); + execute(filterNotValid(reverseTokens)); ObjEntity objEntity1 = null; ObjEntity objEntity2 = null; diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java index c32f73b049..c70dab6816 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropColumnToModelIT.java @@ -38,6 +38,7 @@ import org.apache.cayenne.map.ObjAttribute; import org.apache.cayenne.map.ObjEntity; import org.apache.cayenne.map.ObjRelationship; +import org.junit.Assume; import org.junit.Test; public class DropColumnToModelIT extends MergeCase { @@ -102,6 +103,7 @@ public void testSimpleColumn() throws Exception { @Test public void testRemoveFKColumnWithoutRelationshipInDb() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_TABLE2"); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java index 286cfc2035..731c166a7e 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/merge/token/model/DropRelationshipToModelIT.java @@ -44,6 +44,7 @@ public class DropRelationshipToModelIT extends MergeCase { @Test public void testForeignKey() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); dropTableIfPresent("NEW_TABLE"); dropTableIfPresent("NEW_TABLE2"); 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 1828dc9cd6..2e512fe5f5 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 @@ -25,6 +25,7 @@ import org.apache.cayenne.dba.TypesMapping; import org.apache.cayenne.map.DbAttribute; import org.apache.cayenne.map.DbEntity; +import org.junit.Assume; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -36,6 +37,7 @@ public class AttributeLoaderIT extends BaseLoaderIT { @Test public void testAttributeLoad() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); createDbEntities(); AttributeLoader loader = new AttributeLoader(adapter, EMPTY_CONFIG, new DefaultDbLoaderDelegate()); @@ -79,6 +81,7 @@ public void testAttributeLoad() throws Exception { @Test public void testAttributeLoadTypes() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsColumnTypeReengineering()); DatabaseMetaData metaData = connection.getMetaData(); DbLoaderDelegate delegate = new DefaultDbLoaderDelegate(); diff --git a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java index 49f0163f79..b71e355925 100644 --- a/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java +++ b/cayenne-dbsync/src/test/java/org/apache/cayenne/dbsync/reverse/dbload/DbLoaderIT.java @@ -34,6 +34,7 @@ import org.apache.cayenne.unit.di.server.ServerCaseDataSourceFactory; import org.apache.cayenne.unit.di.server.UseServerRuntime; import org.junit.After; +import org.junit.Assume; import org.junit.Before; import org.junit.Test; @@ -72,6 +73,7 @@ public class DbLoaderIT extends ServerCase { */ @Test public void testSimpleLoad() throws Exception { + Assume.assumeTrue(accessStackAdapter.supportsFKConstraints()); DbLoader loader = createDbLoader(true, true); DataMap loaded = loader.load(); assertNotNull(loaded); diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/SQLiteUnitDbAdapter.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/SQLiteUnitDbAdapter.java index dd0e663e32..34afa4e686 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/SQLiteUnitDbAdapter.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/SQLiteUnitDbAdapter.java @@ -49,4 +49,8 @@ public boolean supportsAllAnySome() { public boolean supportsEscapeInLike() { return false; } + + public boolean onlyGenericNumberType() { + return true; + } } diff --git a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java index 9c8186c649..67da6cc123 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/unit/di/server/ServerCaseDataSourceInfoProvider.java @@ -111,7 +111,7 @@ public ServerCaseDataSourceInfoProvider(@Inject Map tokensToMigrate = tokens.getSelectedTokens(); diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/AdapterMapping.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/AdapterMapping.java index 36b59a594a..79cd78f887 100644 --- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/AdapterMapping.java +++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/util/AdapterMapping.java @@ -88,7 +88,7 @@ protected void initDefaults() { adapterToJDBCURLMap.put(OpenBaseAdapter.class.getName(), "jdbc:openbase://localhost/database"); adapterToJDBCURLMap.put(SQLServerAdapter.class.getName(), "jdbc:sqlserver://localhost:1433;databaseName=database;SelectMethod=cursor"); - adapterToJDBCURLMap.put(SQLiteAdapter.class.getName(), "jdbc:sqlite:testdb"); + adapterToJDBCURLMap.put(SQLiteAdapter.class.getName(), "jdbc:sqlite:testdb?limit_compound_select=0"); adapterToJDBCURLMap.put(FirebirdAdapter.class.getName(), "jdbc:firebirdsql:localhost/3050:database.fdb"); // TODO: embedded Derby Mode... change to client-server once we figure diff --git a/pom.xml b/pom.xml index 102e5e348a..3826c895bc 100644 --- a/pom.xml +++ b/pom.xml @@ -1618,7 +1618,7 @@ org.xerial sqlite-jdbc - 3.25.2 + 3.36.0.2 test From 2d6f474eddfc5e851e13549359e95c3ff45a2023 Mon Sep 17 00:00:00 2001 From: Oleg Khodokevich Date: Tue, 1 Feb 2022 16:56:16 +0300 Subject: [PATCH 5/5] Was deleted github-actions-demo --- .github/workflows/github-actions-demo.yml | 66 ----------------------- 1 file changed, 66 deletions(-) delete mode 100644 .github/workflows/github-actions-demo.yml diff --git a/.github/workflows/github-actions-demo.yml b/.github/workflows/github-actions-demo.yml deleted file mode 100644 index fcac50548e..0000000000 --- a/.github/workflows/github-actions-demo.yml +++ /dev/null @@ -1,66 +0,0 @@ -# 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. - -name: cayenne - -on: [push, pull_request] - -jobs: - test: - runs-on: ubuntu-latest - name: JDK ${{ matrix.java }}, DB ${{ matrix.db-profile }} - continue-on-error: true - strategy: - matrix: - java: [8, 11, 16-ea] - db-profile: [hsql, h2, derby, mysql-tc, postgres-tc, sqlserver-tc] - - steps: - - name: Checkout repository - uses: actions/checkout@v2 - - - name: Set up java ${{ matrix.java }} - uses: actions/setup-java@v1 - with: - java-version: ${{ matrix.java }} - - - uses: actions/cache@v2 - with: - path: $HOME/.m2 - key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }} - restore-keys: ${{ runner.os }}-m2 - - - name: Set up DB ${{ matrix.db-profile }} - run: mvn verify -q -DcayenneTestConnection=${{ matrix.db-profile }} -DcayenneLogLevel=ERROR -Dhttp.keepAlive=false -Dmaven.wagon.http.pool=false - -# deploy: -# runs-on: ubuntu-latest -# needs: test -# # if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'apache/cayenne' }} -# # env: -# # SNAPSHOT_REPO_USERNAME: ${{ secrets.SNAPSHOT_REPO_USERNAME }} -# # SNAPSHOT_REPO_PASSWORD: ${{ secrets.SNAPSHOT_REPO_PASSWORD }} -# env: -# GITHUB_TOKEN: ${{ secrets.MY_GITHUB_TOKEN }} -# GITHUB_USERNAME: KravchenkoAS -# steps: -# - name: Checkout repository -# uses: actions/checkout@v1 -# - name: Set up java 8 -# uses: actions/setup-java@v1 -# with: -# java-version: 8 -# - name: Deploy -# run: mvn deploy -DskipTests --settings .github/workflows/.settings.xml \ No newline at end of file