You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2016/09/29 17:38:59 UTC
[13/15] cayenne git commit: CAY-2116 Split schema synchronization
code in a separate module
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..c2f96ce
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DefaultMergerTokenFactory.java
@@ -0,0 +1,181 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.AddColumnToModel;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToModel;
+import org.apache.cayenne.dbsync.merge.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.CreateTableToModel;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToModel;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToModel;
+import org.apache.cayenne.dbsync.merge.DropTableToDb;
+import org.apache.cayenne.dbsync.merge.DropTableToModel;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToModel;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToModel;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToModel;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToModel;
+import org.apache.cayenne.dbsync.merge.SetValueForNullToDb;
+import org.apache.cayenne.dbsync.merge.ValueForNullProvider;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collection;
+
+/**
+ * @since 4.0
+ */
+public class DefaultMergerTokenFactory implements MergerTokenFactory {
+
+ @Override
+ public MergerToken createCreateTableToModel(DbEntity entity) {
+ return new CreateTableToModel(entity);
+ }
+
+ @Override
+ public MergerToken createCreateTableToDb(DbEntity entity) {
+ return new CreateTableToDb(entity);
+ }
+
+ @Override
+ public MergerToken createDropTableToModel(DbEntity entity) {
+ return new DropTableToModel(entity);
+ }
+
+ @Override
+ public MergerToken createDropTableToDb(DbEntity entity) {
+ return new DropTableToDb(entity);
+ }
+
+ @Override
+ public MergerToken createAddColumnToModel(DbEntity entity, DbAttribute column) {
+ return new AddColumnToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
+ return new AddColumnToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createDropColumnToModel(DbEntity entity, DbAttribute column) {
+ return new DropColumnToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetNotNullToModel(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToModel(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToModel(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column);
+ }
+
+ @Override
+ public MergerToken createSetValueForNullToDb(DbEntity entity, DbAttribute column, ValueForNullProvider valueForNullProvider) {
+ return new SetValueForNullToDb(entity, column, valueForNullProvider);
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToModel(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew) {
+ return new SetColumnTypeToModel(entity, columnOriginal, columnNew);
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew);
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ return new AddRelationshipToDb(entity, rel);
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ return new AddRelationshipToModel(entity, rel);
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel) {
+ return new DropRelationshipToDb(entity, rel);
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToModel(DbEntity entity, DbRelationship rel) {
+ return new DropRelationshipToModel(entity, rel);
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName);
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToModel(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToModel(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java
new file mode 100644
index 0000000..398d5cc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/DerbyMergerTokenFactory.java
@@ -0,0 +1,85 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class DerbyMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://db.apache.org/derby/manuals/reference/sqlj26.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" SET DATA TYPE ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NOT NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
+ }
+
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
new file mode 100644
index 0000000..4368977
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/FirebirdMergerTokenFactory.java
@@ -0,0 +1,91 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class FirebirdMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy quoting = adapter.getQuotingStrategy();
+ return Collections.singletonList("ALTER TABLE " + quoting.quotedFullyQualifiedName(getEntity())
+ + " DROP " + quoting.quotedName(getColumn()));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ String entityName = context.quotedFullyQualifiedName(getEntity()) ;
+ String columnName = context.quotedName(getColumn());
+ // Firebird doesn't support ALTER TABLE table_name ALTER column_name SET NOT NULL
+ // but this might be achived by modyfication of system tables
+ return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = 1 "+
+ "WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ String entityName = context.quotedFullyQualifiedName(getEntity()) ;
+ String columnName = context.quotedName(getColumn());
+ // Firebird doesn't support ALTER TABLE table_name ALTER column_name DROP NOT NULL
+ // but this might be achived by modyfication system tables
+ return Collections.singletonList(String.format("UPDATE RDB$RELATION_FIELDS SET RDB$NULL_FLAG = NULL "+
+ " WHERE RDB$FIELD_NAME = '%s' AND RDB$RELATION_NAME = '%s'", columnName, entityName));
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..8acafc3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/H2MergerTokenFactory.java
@@ -0,0 +1,82 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 3.0
+ */
+public class H2MergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " ALTER COLUMN " + getColumn().getName() + " SET NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..15cfa18
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/HSQLMergerTokenFactory.java
@@ -0,0 +1,82 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class HSQLMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(getEntity())
+ + " ALTER COLUMN " + context.quotedName(getColumn()) + " NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(DbEntity entity, Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew, String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(entity, primaryKeyOriginal, primaryKeyNew, detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(DbAdapter adapter, List<String> sqls) {
+ sqls.add("ALTER TABLE " + adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
new file mode 100644
index 0000000..19d2860
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/IngresMergerTokenFactory.java
@@ -0,0 +1,224 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+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 java.util.Collections;
+import java.util.List;
+
+public class IngresMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(final DbEntity entity, DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder buf = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ buf.append("ALTER TABLE ");
+ buf.append(context.quotedFullyQualifiedName(getEntity()));
+ buf.append(" DROP COLUMN ");
+ buf.append(context.quotedName(getColumn()));
+ buf.append(" RESTRICT ");
+
+ return Collections.singletonList(buf.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createAddRelationshipToDb(DbEntity entity, final DbRelationship rel) {
+ return new AddRelationshipToDb(entity, rel) {
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ if (!rel.isToMany() && rel.isToPK() && !rel.isToDependentPK()) {
+
+ DbEntity source = (DbEntity) rel.getSourceEntity();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ StringBuilder buf = new StringBuilder();
+ StringBuilder refBuf = new StringBuilder();
+
+ buf.append("ALTER TABLE ");
+ buf.append(context.quotedFullyQualifiedName(source));
+
+ // requires the ADD CONSTRAINT statement
+ buf.append(" ADD CONSTRAINT ");
+ String name = "U_" + rel.getSourceEntity().getName() + "_"
+ + (long) (System.currentTimeMillis() / (Math.random() * 100000));
+
+ buf.append(context.quotedIdentifier(rel.getSourceEntity(), name));
+ buf.append(" FOREIGN KEY (");
+
+ boolean first = true;
+ for (DbJoin join : rel.getJoins()) {
+ if (!first) {
+ buf.append(", ");
+ refBuf.append(", ");
+ } else
+ first = false;
+
+ buf.append(context.quotedSourceName(join));
+ refBuf.append(context.quotedTargetName(join));
+ }
+
+ buf.append(") REFERENCES ");
+ buf.append(context.quotedFullyQualifiedName((DbEntity) rel.getTargetEntity()));
+ buf.append(" (");
+ buf.append(refBuf.toString());
+ buf.append(')');
+
+ // also make sure we delete dependent FKs
+ buf.append(" ON DELETE CASCADE");
+
+ String fksql = buf.toString();
+
+ if (fksql != null) {
+ return Collections.singletonList(fksql);
+ }
+ }
+
+ return Collections.emptyList();
+
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ /*
+ * TODO: we generate this query as in ingres db documentation,
+ * but unfortunately ingres don't support it
+ */
+
+ StringBuilder sqlBuffer = new StringBuilder();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(getEntity().getFullyQualifiedName());
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
+
+ if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
+ sqlBuffer.append("(");
+ sqlBuffer.append(getColumn().getMaxLength());
+ sqlBuffer.append(")");
+ }
+
+ sqlBuffer.append(" NOT NULL");
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ sqlBuffer.append(adapter.externalTypesForJdbcType(getColumn().getType())[0]);
+
+ if (adapter.typeSupportsLength(getColumn().getType()) && getColumn().getMaxLength() > 0) {
+ sqlBuffer.append("(");
+ sqlBuffer.append(getColumn().getMaxLength());
+ sqlBuffer.append(")");
+ }
+
+ sqlBuffer.append(" WITH NULL");
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(final DbEntity entity, DbRelationship rel) {
+
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ String fkName = getFkName();
+
+ if (fkName == null) {
+ return Collections.emptyList();
+ }
+
+ StringBuilder buf = new StringBuilder();
+ buf.append("ALTER TABLE ");
+ buf.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ buf.append(" DROP CONSTRAINT ");
+ buf.append(fkName);
+ buf.append(" CASCADE ");
+
+ return Collections.singletonList(buf.toString());
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..46b6ef3
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactory.java
@@ -0,0 +1,88 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.ValueForNullProvider;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+
+import java.util.Collection;
+
+public interface MergerTokenFactory {
+
+ MergerToken createCreateTableToModel(DbEntity entity);
+
+ MergerToken createCreateTableToDb(DbEntity entity);
+
+ MergerToken createDropTableToModel(DbEntity entity);
+
+ MergerToken createDropTableToDb(DbEntity entity);
+
+ MergerToken createAddColumnToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createAddColumnToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createDropColumnToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetNotNullToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetAllowNullToModel(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column);
+
+ MergerToken createSetValueForNullToDb(DbEntity entity,
+ DbAttribute column,
+ ValueForNullProvider valueForNullProvider);
+
+ MergerToken createSetColumnTypeToModel(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew);
+
+ MergerToken createSetColumnTypeToDb(
+ DbEntity entity,
+ DbAttribute columnOriginal,
+ DbAttribute columnNew);
+
+ MergerToken createAddRelationshipToDb(DbEntity entity, DbRelationship rel);
+
+ MergerToken createAddRelationshipToModel(DbEntity entity, DbRelationship rel);
+
+ MergerToken createDropRelationshipToDb(DbEntity entity, DbRelationship rel);
+
+ MergerToken createDropRelationshipToModel(DbEntity entity, DbRelationship rel);
+
+ MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName);
+
+ MergerToken createSetPrimaryKeyToModel(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName);
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
new file mode 100644
index 0000000..8d5b573
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MergerTokenFactoryProvider.java
@@ -0,0 +1,36 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.PerAdapterProvider;
+import org.apache.cayenne.dbsync.CayenneDbSyncModule;
+import org.apache.cayenne.di.Inject;
+
+import java.util.Map;
+
+/**
+ * @since 4.0
+ */
+public class MergerTokenFactoryProvider extends PerAdapterProvider<MergerTokenFactory> {
+
+ public MergerTokenFactoryProvider(@Inject(CayenneDbSyncModule.MERGER_FACTORIES_MAP) Map<String,
+ MergerTokenFactory> perAdapterValues, @Inject MergerTokenFactory defaultValue) {
+ super(perAdapterValues, defaultValue);
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..2193446
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/MySQLMergerTokenFactory.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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.dbsync.merge.SetPrimaryKeyToDb;
+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.Collections;
+import java.util.List;
+
+public class MySQLMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetNotNullToDb(
+ final DbEntity entity,
+ final DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" CHANGE ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(
+ final DbEntity entity,
+ final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" CHANGE ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+ sqlBuffer.append(" ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(
+ final DbEntity entity,
+ DbRelationship rel) {
+
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ String fkName = getFkName();
+
+ if (fkName == null) {
+ return Collections.emptyList();
+ }
+ QuotingStrategy context = adapter.getQuotingStrategy();
+
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ return Collections.singletonList("ALTER TABLE " + context.quotedFullyQualifiedName(entity) + " DROP FOREIGN KEY " + fkName);
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetPrimaryKeyToDb(
+ DbEntity entity,
+ Collection<DbAttribute> primaryKeyOriginal,
+ Collection<DbAttribute> primaryKeyNew,
+ String detectedPrimaryKeyName) {
+ return new SetPrimaryKeyToDb(
+ entity,
+ primaryKeyOriginal,
+ primaryKeyNew,
+ detectedPrimaryKeyName) {
+
+ @Override
+ protected void appendDropOriginalPrimaryKeySQL(
+ DbAdapter adapter,
+ List<String> sqls) {
+ sqls.add("ALTER TABLE "
+ + adapter.getQuotingStrategy()
+ .quotedFullyQualifiedName(getEntity())
+ + " DROP PRIMARY KEY");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
new file mode 100644
index 0000000..7235f6b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OpenBaseMergerTokenFactory.java
@@ -0,0 +1,143 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dbsync.merge.CreateTableToDb;
+import org.apache.cayenne.dbsync.merge.DropRelationshipToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class OpenBaseMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createCreateTableToDb(DbEntity entity) {
+ return new CreateTableToDb(entity) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+ // create table first as OpenBase adapter created primary key in its
+ // getPkGenerator().createAutoPkStatements
+ sqls.add(adapter.createTable(getEntity()));
+ sqls.addAll(adapter.getPkGenerator().createAutoPkStatements(
+ Collections.singletonList(getEntity())));
+ return sqls;
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createDropRelationshipToDb(
+ final DbEntity entity,
+ final DbRelationship rel) {
+ return new DropRelationshipToDb(entity, rel) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+
+ // FK_NAME form jdbc metadata seem to be wrong. It contain a column name
+ // and not the 'relationshipName'
+ // TODO: tell openbase developer mail list
+
+ DbEntity source = getEntity();
+ DbEntity dest = rel.getTargetEntity();
+
+ // only use the first. See adapter
+ // TODO: can we be sure this is the first and same as used by the adapter?
+ DbJoin join = rel.getJoins().get(0);
+
+ // see comment in adapter for why source and dest is switched around..
+
+ return Collections.singletonList("delete from _SYS_RELATIONSHIP where "
+ + " source_table = '" + dest.getFullyQualifiedName() + "'"
+ + " and source_column = '" + join.getTargetName() + "'"
+ + " and dest_table = '" + source.getFullyQualifiedName() + "'"
+ + " and dest_column = '" + join.getSourceName() + "'");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ final DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ List<String> sqls = new ArrayList<String>();
+
+ if (columnOriginal.getMaxLength() != columnNew.getMaxLength()) {
+ sqls.add("ALTER TABLE "
+ + entity.getFullyQualifiedName()
+ + " COLUMN "
+ + columnNew.getName()
+ + " SET LENGTH "
+ + columnNew.getMaxLength());
+ }
+
+ return sqls;
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " COLUMN " + getColumn().getName() + " SET NOT NULL");
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ return Collections.singletonList("ALTER TABLE " + getEntity().getFullyQualifiedName()
+ + " COLUMN " + getColumn().getName() + " SET NULL");
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
new file mode 100644
index 0000000..2c4032b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/OracleMergerTokenFactory.java
@@ -0,0 +1,111 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+
+public class OracleMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(column));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" MODIFY ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
+
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" MODIFY ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
new file mode 100644
index 0000000..935ecfb
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/PostgresMergerTokenFactory.java
@@ -0,0 +1,49 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.QuotingStrategy;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+
+public class PostgresMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy quotingStrategy) {
+ // http://www.postgresql.org/docs/8.2/static/sql-altertable.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(quotingStrategy.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER ");
+ sqlBuffer.append(quotingStrategy.quotedName(columnNew));
+ sqlBuffer.append(" TYPE ");
+ }
+ };
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
new file mode 100644
index 0000000..768b957
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SQLServerMergerTokenFactory.java
@@ -0,0 +1,112 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+public class SQLServerMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ALTER COLUMN ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createAddColumnToDb(final DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://msdn2.microsoft.com/en-us/library/ms190273.aspx
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" ADD ");
+ sqlBuffer.append(context.quotedName(column));
+ sqlBuffer.append(" ");
+ }
+ };
+ }
+
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, final DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, final DbAttribute column) {
+
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(adapter.getQuotingStrategy().quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ALTER COLUMN ");
+
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
new file mode 100644
index 0000000..f295305
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/merge/factory/SybaseMergerTokenFactory.java
@@ -0,0 +1,166 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.dba.DbAdapter;
+import org.apache.cayenne.dba.QuotingStrategy;
+import org.apache.cayenne.dbsync.merge.AddColumnToDb;
+import org.apache.cayenne.dbsync.merge.DropColumnToDb;
+import org.apache.cayenne.dbsync.merge.MergerToken;
+import org.apache.cayenne.dbsync.merge.SetAllowNullToDb;
+import org.apache.cayenne.dbsync.merge.SetColumnTypeToDb;
+import org.apache.cayenne.dbsync.merge.SetNotNullToDb;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @since 3.0
+ */
+public class SybaseMergerTokenFactory extends DefaultMergerTokenFactory {
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createAddColumnToDb(DbEntity entity, final DbAttribute column) {
+ return new AddColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ StringBuffer sqlBuffer = new StringBuffer();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" ADD ");
+ boolean magnatory = column.isMandatory();
+ column.setMandatory(false);
+ adapter.createTableAppendColumn(sqlBuffer, column);
+ if(magnatory){
+ column.setMandatory(magnatory);
+ }
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createDropColumnToDb(DbEntity entity, DbAttribute column) {
+ return new DropColumnToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuilder sqlBuffer = new StringBuilder();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(getEntity()));
+ sqlBuffer.append(" DROP ");
+ sqlBuffer.append(context.quotedName(getColumn()));
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetNotNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetNotNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+
+ StringBuffer sqlBuffer = createStringQuery(
+ adapter,
+ getEntity(),
+ getColumn());
+
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetAllowNullToDb(DbEntity entity, DbAttribute column) {
+ return new SetAllowNullToDb(entity, column) {
+
+ @Override
+ public List<String> createSql(DbAdapter adapter) {
+ StringBuffer sqlBuffer = createStringQuery(
+ adapter,
+ getEntity(),
+ getColumn());
+ return Collections.singletonList(sqlBuffer.toString());
+ }
+ };
+ }
+
+ /**
+ * @since 3.0
+ */
+ @Override
+ public MergerToken createSetColumnTypeToDb(
+ final DbEntity entity,
+ DbAttribute columnOriginal,
+ final DbAttribute columnNew) {
+
+ return new SetColumnTypeToDb(entity, columnOriginal, columnNew) {
+
+ @Override
+ protected void appendPrefix(StringBuffer sqlBuffer, QuotingStrategy context) {
+ // http://dev.mysql.com/tech-resources/articles/mysql-cluster-50.html
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ sqlBuffer.append(context.quotedName(columnNew));
+ sqlBuffer.append(" ");
+ }
+
+ };
+ }
+
+ private static StringBuffer createStringQuery(
+ DbAdapter adapter,
+ DbEntity entity,
+ DbAttribute column) {
+ StringBuffer sqlBuffer = new StringBuffer();
+ QuotingStrategy context = adapter.getQuotingStrategy();
+ sqlBuffer.append("ALTER TABLE ");
+ sqlBuffer.append(context.quotedFullyQualifiedName(entity));
+ sqlBuffer.append(" MODIFY ");
+ adapter.createTableAppendColumn(sqlBuffer, column);
+
+ return sqlBuffer;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
new file mode 100644
index 0000000..2bb55c0
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesBaseLoader.java
@@ -0,0 +1,107 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.reverse;
+
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.dba.TypesMapping;
+import org.apache.cayenne.map.DbAttribute;
+import org.apache.cayenne.map.DbEntity;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Set;
+
+/**
+* @since 4.0.
+*/
+public abstract class DbAttributesBaseLoader implements DbAttributesLoader {
+ private final String catalog;
+ private final String schema;
+
+ private final DatabaseMetaData metaData;
+ private final DbAdapter adapter;
+
+ public DbAttributesBaseLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter) {
+ this.catalog = catalog;
+ this.schema = schema;
+ this.metaData = metaData;
+ this.adapter = adapter;
+ }
+
+ protected DbAttribute loadDbAttribute(Set<String> columns, ResultSet rs) throws SQLException {
+
+ // gets attribute's (column's) information
+ int columnType = rs.getInt("DATA_TYPE");
+
+ // ignore precision of non-decimal columns
+ int decimalDigits = -1;
+ if (TypesMapping.isDecimal(columnType)) {
+ decimalDigits = rs.getInt("DECIMAL_DIGITS");
+ if (rs.wasNull()) {
+ decimalDigits = -1;
+ }
+ }
+
+ // create attribute delegating this task to adapter
+ DbAttribute attr = adapter.buildAttribute(
+ rs.getString("COLUMN_NAME"),
+ rs.getString("TYPE_NAME"),
+ columnType,
+ rs.getInt("COLUMN_SIZE"),
+ decimalDigits,
+ rs.getBoolean("NULLABLE"));
+
+ if (columns.contains("IS_AUTOINCREMENT")) {
+ String autoIncrement = rs.getString("IS_AUTOINCREMENT");
+ if ("YES".equals(autoIncrement)) {
+ attr.setGenerated(true);
+ }
+ }
+ return attr;
+ }
+
+ @Override
+ public void loadDbAttributes(DbEntity entity) {
+ for (DbAttribute attr : loadDbAttributes(entity.getName())) {
+ attr.setEntity(entity);
+
+ // override existing attributes if it comes again
+ if (entity.getAttribute(attr.getName()) != null) {
+ entity.removeAttribute(attr.getName());
+ }
+ entity.addAttribute(attr);
+ }
+ }
+
+ protected abstract List<DbAttribute> loadDbAttributes(String tableName);
+
+ protected String getCatalog() {
+ return catalog;
+ }
+
+ protected String getSchema() {
+ return schema;
+ }
+
+ protected DatabaseMetaData getMetaData() {
+ return metaData;
+ }
+}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
new file mode 100644
index 0000000..6658cdc
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesLoader.java
@@ -0,0 +1,43 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.reverse;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Interface responsible for attributes loading. Several options possible here
+ * 1) load attributes for each table separately
+ * 2) load attributes for schema and group it by table names
+ *
+ * here is a trade of between count of queries and amount af calculation.
+ *
+ *
+ * @since 4.0
+ */
+public interface DbAttributesLoader {
+
+ // TODO use instant field for logging
+ Log LOGGER = LogFactory.getLog(DbTableLoader.class);
+
+ void loadDbAttributes(DbEntity entity);
+
+}
+
http://git-wip-us.apache.org/repos/asf/cayenne/blob/2f7b1d53/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
new file mode 100644
index 0000000..83ce60b
--- /dev/null
+++ b/cayenne-dbsync/src/main/java/org/apache/cayenne/dbsync/reverse/DbAttributesPerSchemaLoader.java
@@ -0,0 +1,130 @@
+/*****************************************************************
+ * 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
+ *
+ * http://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.reverse;
+
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cayenne.dbsync.reverse.filters.PatternFilter;
+import org.apache.cayenne.dbsync.reverse.filters.TableFilter;
+import org.apache.cayenne.dba.DbAdapter;
+import org.apache.cayenne.map.DbAttribute;
+
+/**
+ * Load all attributes for schema and return it for each table
+ * */
+public class DbAttributesPerSchemaLoader extends DbAttributesBaseLoader {
+
+ private final TableFilter filter;
+
+ private Map<String, List<DbAttribute>> attributes;
+
+ public DbAttributesPerSchemaLoader(String catalog, String schema, DatabaseMetaData metaData, DbAdapter adapter,
+ TableFilter filter) {
+ super(catalog, schema, metaData, adapter);
+
+ this.filter = filter;
+ }
+
+ private Map<String, List<DbAttribute>> loadDbAttributes() throws SQLException {
+ Map<String, List<DbAttribute>> attributes = new HashMap<>();
+
+ try (ResultSet rs = getMetaData().getColumns(getCatalog(), getSchema(), "%", "%");) {
+ Set<String> columns = new HashSet<String>();
+
+ while (rs.next()) {
+ if (columns.isEmpty()) {
+ ResultSetMetaData rsMetaData = rs.getMetaData();
+ for (int i = 1; i <= rsMetaData.getColumnCount(); i++) {
+ columns.add(rsMetaData.getColumnLabel(i));
+ }
+ }
+
+ // for a reason not quiet apparent to me, Oracle sometimes
+ // returns duplicate record sets for the same table, messing up
+ // table
+ // names. E.g. for the system table "WK$_ATTR_MAPPING" columns
+ // are
+ // returned twice - as "WK$_ATTR_MAPPING" and
+ // "WK$$_ATTR_MAPPING"... Go figure
+ String tableName = rs.getString("TABLE_NAME");
+ String columnName = rs.getString("COLUMN_NAME");
+
+ PatternFilter columnFilter = filter.isIncludeTable(tableName);
+ /*
+ * Here is possible optimization if filter will contain
+ * map<tableName, columnFilter> we can replace it after tables
+ * loading since already done pattern matching once and exactly
+ * know all tables that we want to process
+ */
+ if (columnFilter == null || !columnFilter.isInclude(columnName)) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Skip column '" + tableName + "." + columnName + "' (Path: " + getCatalog() + "/"
+ + getSchema() + "; Filter: " + columnFilter + ")");
+ }
+ continue;
+ }
+
+ List<DbAttribute> attrs = attributes.get(tableName);
+ if (attrs == null) {
+ attrs = new LinkedList<DbAttribute>();
+
+ attributes.put(tableName, attrs);
+ }
+
+ attrs.add(loadDbAttribute(columns, rs));
+ }
+ }
+
+ return attributes;
+ }
+
+ @Override
+ protected List<DbAttribute> loadDbAttributes(String tableName) {
+ Map<String, List<DbAttribute>> attributes = getAttributes();
+ if (attributes != null) {
+ List<DbAttribute> dbAttributes = attributes.get(tableName);
+ if (dbAttributes != null) {
+ return dbAttributes;
+ }
+ }
+
+ return new LinkedList<DbAttribute>();
+ }
+
+ public Map<String, List<DbAttribute>> getAttributes() {
+ if (attributes == null) {
+ try {
+ attributes = loadDbAttributes();
+ } catch (SQLException e) {
+ LOGGER.error(e);
+ attributes = new HashMap<>();
+ }
+ }
+ return attributes;
+ }
+}