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 2014/12/09 09:22:12 UTC
[1/2] cayenne git commit: CAY-1976 Slow performance of DbMerger
Repository: cayenne
Updated Branches:
refs/heads/master 4e88f9afd -> c9793921b
CAY-1976 Slow performance of DbMerger
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/f3457df8
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/f3457df8
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/f3457df8
Branch: refs/heads/master
Commit: f3457df851a9432b4476245b5674342777414a32
Parents: 2d8ffba
Author: alexkolonitsky <Al...@gmail.com>
Authored: Mon Dec 8 19:52:31 2014 +0300
Committer: alexkolonitsky <Al...@gmail.com>
Committed: Mon Dec 8 19:52:31 2014 +0300
----------------------------------------------------------------------
.../org/apache/cayenne/access/DbLoader.java | 500 ++++++++++---------
.../loader/ManyToManyCandidateEntity.java | 3 +-
.../cayenne/access/loader/filters/DbPath.java | 6 +
.../apache/cayenne/map/naming/ExportedKey.java | 111 +++-
.../java/org/apache/cayenne/merge/DbMerger.java | 48 +-
.../org/apache/cayenne/access/DbLoaderIT.java | 26 +-
.../access/loader/filters/DbPathTest.java | 18 +
.../map/naming/LegacyNameGeneratorTest.java | 4 +-
.../merge/DropRelationshipToModelIT.java | 30 +-
.../org/apache/cayenne/merge/MergeCase.java | 24 +-
.../apache/cayenne/merge/MergerFactoryIT.java | 47 +-
.../cayenne/tools/dbimport/DbImportAction.java | 3 +-
.../map/naming/DefaultNameGeneratorTest.java | 6 +-
.../tools/dbimport/DbImportActionTest.java | 6 +-
.../InferRelationshipsControllerBase.java | 2 +-
.../dialog/objentity/ObjRelationshipInfo.java | 8 +-
16 files changed, 464 insertions(+), 378 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
index d759213..5537ac9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
@@ -26,13 +26,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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 java.util.TreeSet;
-import org.apache.cayenne.CayenneException;
import org.apache.cayenne.access.loader.DbLoaderConfiguration;
import org.apache.cayenne.access.loader.ManyToManyCandidateEntity;
import org.apache.cayenne.access.loader.filters.EntityFilters;
@@ -48,7 +47,6 @@ import org.apache.cayenne.map.DbJoin;
import org.apache.cayenne.map.DbRelationship;
import org.apache.cayenne.map.DbRelationshipDetected;
import org.apache.cayenne.map.DetectedDbEntity;
-import org.apache.cayenne.map.Entity;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.Procedure;
import org.apache.cayenne.map.ProcedureParameter;
@@ -74,12 +72,6 @@ public class DbLoader {
public static final String WILDCARD = "%";
public static final String WILDCARD_PATTERN = ".*";
- /**
- * CAY-479 - need to track which entities which are skipped during loading from db since it it already present in
- * dataMap and haven't marked for overriding so that relationships to non-skipped entities can be loaded
- */
- private Set<DbEntity> skippedEntities = new HashSet<DbEntity>();
-
private final Connection connection;
private final DbAdapter adapter;
private final DbLoaderDelegate delegate;
@@ -223,19 +215,31 @@ public class DbLoader {
* @return
* @since 3.2
*/
- public List<DbEntity> getTables(DbLoaderConfiguration config, String[] types)
+ public Map<DbPath, Map<String, DbEntity>> getTables(DbLoaderConfiguration config, String[] types)
throws SQLException {
+ if (types == null || types.length == 0) {
+ types = getDefaultTableTypes();
+ }
- List<DbEntity> tables = new LinkedList<DbEntity>();
+ Map<DbPath, Map<String, DbEntity>> tables = new HashMap<DbPath, Map<String, DbEntity>>();
FiltersConfig filters = config.getFiltersConfig();
for (DbPath path : filters.pathsForQueries()) {
- tables.addAll(getDbEntities(filters, path, types));
+ tables.put(path, getDbEntities(filters, path, types));
}
return tables;
}
- private List<DbEntity> getDbEntities(FiltersConfig filters, DbPath dbPath, String[] types) throws SQLException {
+ /**
+ *
+ * @param filters
+ * @param dbPath
+ * @param types
+ * @return Map<TableName, DbEntity>
+ *
+ * @throws SQLException
+ */
+ private Map<String, DbEntity> getDbEntities(FiltersConfig filters, DbPath dbPath, String[] types) throws SQLException {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Read tables: catalog=" + dbPath.catalog + ", schema=" + dbPath.schema + ", types="
+ Arrays.toString(types));
@@ -243,7 +247,7 @@ public class DbLoader {
ResultSet rs = getMetaData().getTables(dbPath.catalog, dbPath.schema, WILDCARD, types);
- List<DbEntity> tables = new ArrayList<DbEntity>();
+ Map<String, DbEntity> tables = new HashMap<String, DbEntity>();
try {
while (rs.next()) {
// Oracle 9i and newer has a nifty recycle bin feature... but we don't
@@ -265,7 +269,7 @@ public class DbLoader {
table.setSchema(schema);
if (filters.filter(new DbPath(catalog, schema)).tableFilter().isInclude(table)) {
- tables.add(table);
+ tables.put(name, table);
}
}
} finally {
@@ -284,81 +288,48 @@ public class DbLoader {
* The list of org.apache.cayenne.ashwood.dbutil.Table objects
* for which DbEntities must be created. @return false if loading must be immediately aborted.
*/
- public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, Collection<? extends DbEntity> tables) throws SQLException {
+ public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, Map<DbPath, Map<String, DbEntity>> tables) throws SQLException {
/** List of db entities to process. */
+
List<DbEntity> dbEntityList = new ArrayList<DbEntity>();
- for (DbEntity dbEntity : tables) {
-
- // Check if there already is a DbEntity under such name
- // if so, consult the delegate what to do
- DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
- if (oldEnt != null) {
- if (delegate == null) {
- break; // no delegate, don't know what to do, cancel import
- // TODO continue?
+ for (Map.Entry<DbPath, Map<String, DbEntity>> tablesMap : tables.entrySet()) {
+ for (DbEntity dbEntity : tablesMap.getValue().values()) {
+
+ // Check if there already is a DbEntity under such name
+ // if so, consult the delegate what to do
+ DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
+ if (oldEnt != null) {
+ map.removeDbEntity(oldEnt.getName(), true);
}
+ map.addDbEntity(dbEntity);
- try {
- if (delegate.overwriteDbEntity(oldEnt)) {
- LOGGER.debug("Overwrite: " + oldEnt.getName());
- map.removeDbEntity(oldEnt.getName(), true);
- delegate.dbEntityRemoved(oldEnt);
- } else {
- LOGGER.debug("Keep old: " + oldEnt.getName());
-
- // cay-479 - need to track entities that were not loaded for
- // relationships exported to entities that were
- skippedEntities.add(oldEnt);
- continue;
- }
- } catch (CayenneException ex) {
- LOGGER.debug("Load canceled.");
-
- return null; // cancel immediately
+ // notify delegate
+ if (delegate != null) {
+ delegate.dbEntityAdded(dbEntity);
}
- }
-
-
-
- map.addDbEntity(dbEntity);
- // notify delegate
- if (delegate != null) {
- delegate.dbEntityAdded(dbEntity);
+ // delegate might have thrown this entity out... so check if it is still
+ // around before continuing processing
+ if (map.getDbEntity(dbEntity.getName()) == dbEntity) {
+ dbEntityList.add(dbEntity);
+ }
}
- loadDbAttributes(config.getFiltersConfig(), dbEntity);
- // delegate might have thrown this entity out... so check if it is still
- // around before continuing processing
- if (map.getDbEntity(dbEntity.getName()) == dbEntity) {
- dbEntityList.add(dbEntity);
- }
- }
+ loadDbAttributes(config.getFiltersConfig(), tablesMap.getKey(), tablesMap.getValue());
- // get primary keys for each table and store it in dbEntity
- getPrimaryKeysForEachTableAndStoreItInDbEntity(map, tables);
-
- // cay-479 - iterate skipped DbEntities to populate exported keys
- for (DbEntity skippedEntity : skippedEntities) {
- loadDbRelationships(map, skippedEntity, config);
+ // get primary keys for each table and store it in dbEntity
+ getPrimaryKeyForTable(tablesMap.getValue());
}
return dbEntityList;
-
}
- private void getPrimaryKeysForEachTableAndStoreItInDbEntity(DataMap map, Collection<? extends DbEntity> tables)
- throws SQLException {
-
- for (DbEntity dbEntity : map.getDbEntities()) {
- if (!tables.contains(dbEntity)) { // TODO is it ok? equals is not overridden
- continue;
- }
-
+ private void getPrimaryKeyForTable(Map<String, DbEntity> tables) throws SQLException {
+ for (DbEntity dbEntity : tables.values()) {
ResultSet rs = getMetaData().getPrimaryKeys(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName());
try {
while (rs.next()) {
- String columnName = rs.getString(4); // COLUMN_NAME
+ String columnName = rs.getString("COLUMN_NAME");
DbAttribute attribute = dbEntity.getAttribute(columnName);
if (attribute != null) {
@@ -370,10 +341,11 @@ public class DbLoader {
LOGGER.warn("Can't locate attribute for primary key: " + columnName);
}
- String pkName = rs.getString(6); // PK_NAME
+ String pkName = rs.getString("PK_NAME");
if (pkName != null && dbEntity instanceof DetectedDbEntity) {
((DetectedDbEntity) dbEntity).setPrimaryKeyName(pkName);
}
+
}
} finally {
rs.close();
@@ -381,8 +353,8 @@ public class DbLoader {
}
}
- private void loadDbAttributes(FiltersConfig filters, DbEntity dbEntity) throws SQLException {
- ResultSet rs = getMetaData().getColumns(dbEntity.getCatalog(), dbEntity.getSchema(), dbEntity.getName(), "%");
+ private void loadDbAttributes(FiltersConfig filters, DbPath path, Map<String, DbEntity> entities) throws SQLException {
+ ResultSet rs = getMetaData().getColumns(path.catalog, path.schema, WILDCARD, WILDCARD);
try {
while (rs.next()) {
@@ -390,25 +362,30 @@ public class DbLoader {
// 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");
- if (!dbEntity.getName().equals(tableName)) {
- LOGGER.info("Incorrectly returned columns for '" + tableName + ", skipping.");
+ DbEntity dbEntity = entities.get(tableName);
+ if (dbEntity == null) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Skip column for '" + tableName + "." + rs.getString("COLUMN_NAME") + ".");
+ }
continue;
}
DbAttribute attr = loadDbAttribute(rs);
attr.setEntity(dbEntity);
- DbPath path = new DbPath(dbEntity.getCatalog(), dbEntity.getSchema(), tableName);
Filter<DbAttribute> filter = filters.filter(path).columnFilter();
if (!filter.isInclude(attr)) {
if (LOGGER.isDebugEnabled()) {
- LOGGER.debug("Importing: attribute '" + attr.getEntity().getName() + "." + attr.getName()
- + "' is skipped (Path: " + path + "; Filter: " + filter + ")");
+ LOGGER.debug("Skip column for '" + attr.getEntity().getName() + "." + attr.getName()
+ + "' (Path: " + path + "; Filter: " + filter + ")");
}
continue;
}
+ // override existing attributes if it comes again
+ if (dbEntity.getAttribute(attr.getName()) != null) {
+ dbEntity.removeAttribute(attr.getName());
+ }
dbEntity.addAttribute(attr);
}
} finally {
@@ -498,110 +475,137 @@ public class DbLoader {
return new EntityMergeSupport(map, nameGenerator, !creatingMeaningfulPK);
}
- /** Loads database relationships into a DataMap. */
- protected void loadDbRelationships(DataMap map, DbLoaderConfiguration config, Iterable<DbEntity> entities) throws SQLException {
- for (DbEntity pkEntity : entities) {
- loadDbRelationships(map, pkEntity, config);
- }
- }
-
- protected void loadDbRelationships(DataMap map, DbEntity entity, DbLoaderConfiguration config) throws SQLException {
+ protected void loadDbRelationships(DbLoaderConfiguration config, Map<DbPath, Map<String, DbEntity>> tables) throws SQLException {
// Get all the foreign keys referencing this table
- ResultSet rs;
- try {
- rs = getMetaData().getExportedKeys(entity.getCatalog(), entity.getSchema(), entity.getName());
- } catch (SQLException cay182Ex) {
- // Sybase-specific - the line above blows on VIEWS, see CAY-182.
- LOGGER.info("Error getting relationships for '" + entity.getName() + "', ignoring.");
- return;
+ for (Map.Entry<DbPath, Map<String, DbEntity>> pathEntry : tables.entrySet()) {
+ Map<String, Set<ExportedKey>> keys = loadExportedKeys(config, pathEntry.getKey(), pathEntry.getValue());
+ for (Map.Entry<String, Set<ExportedKey>> entry : keys.entrySet()) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Process keys for: " + entry.getKey());
+ }
+
+ Set<ExportedKey> exportedKeys = entry.getValue();
+ ExportedKey key = exportedKeys.iterator().next();
+ if (key == null) {
+ throw new IllegalStateException();
+ }
+
+ DbEntity pkEntity = pathEntry.getValue().get(key.getPKTableName());
+ if (pkEntity == null) {
+ skipRelationLog(key, key.getPKTableName());
+ continue;
+ }
+
+ DbEntity fkEntity = pathEntry.getValue().get(key.getFKTableName());
+ if (fkEntity == null) {
+ skipRelationLog(key, key.getFKTableName());
+ continue;
+ }
+
+ DbRelationship forwardRelationship = new DbRelationship(generateName(pkEntity, key, true));
+ forwardRelationship.setSourceEntity(pkEntity);
+ forwardRelationship.setTargetEntity(fkEntity);
+
+ DbRelationshipDetected reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
+ reverseRelationship.setFkName(key.getFKName());
+ reverseRelationship.setSourceEntity(fkEntity);
+ reverseRelationship.setTargetEntity(pkEntity);
+ reverseRelationship.setToMany(false);
+ fkEntity.addRelationship(reverseRelationship);
+
+ boolean toPK = createAndAppendJoins(exportedKeys, pkEntity, fkEntity, forwardRelationship, reverseRelationship);
+
+ forwardRelationship.setToDependentPK(toPK);
+
+ boolean isOneToOne = toPK && fkEntity.getPrimaryKeys().size()
+ == forwardRelationship.getJoins().size();
+
+ forwardRelationship.setToMany(!isOneToOne);
+ forwardRelationship.setName(generateName(pkEntity, key, !isOneToOne));
+ pkEntity.addRelationship(forwardRelationship);
+ }
}
+ }
- try {
- // these will be initialized every time a new target entity is found
- // in the result set (which should be ordered by table name among other things)
- DbRelationship forwardRelationship = null;
- DbRelationshipDetected reverseRelationship = null;
- DbEntity fkEntity = null;
- ExportedKey key = null;
+ private boolean createAndAppendJoins(Set<ExportedKey> exportedKeys, DbEntity pkEntity, DbEntity fkEntity, DbRelationship forwardRelationship, DbRelationshipDetected reverseRelationship) {
+ boolean toPK = true;
+ for (ExportedKey exportedKey : exportedKeys) {
+ // Create and append joins
+ String pkName = exportedKey.getPKColumnName();
+ String fkName = exportedKey.getFKColumnName();
+
+ // skip invalid joins...
+ DbAttribute pkAtt = pkEntity.getAttribute(pkName);
+ if (pkAtt == null) {
+ LOGGER.info("no attribute for declared primary key: " + pkName);
+ continue;
+ }
- while (rs.next()) {
- key = ExportedKey.extractData(rs);
+ DbAttribute fkAtt = fkEntity.getAttribute(fkName);
+ if (fkAtt == null) {
+ LOGGER.info("no attribute for declared foreign key: " + fkName);
+ continue;
+ }
- short keySeq = rs.getShort("KEY_SEQ");
- if (keySeq == 1) {
+ forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
+ reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
- if (forwardRelationship != null) {
- postProcessMasterDbRelationship(forwardRelationship, key);
- forwardRelationship = null;
- }
+ if (!pkAtt.isPrimaryKey()) {
+ toPK = false;
+ }
+ }
+ return toPK;
+ }
- // start new entity
- String fkEntityName = key.getFKTableName();
+ private Map<String, Set<ExportedKey>> loadExportedKeys(DbLoaderConfiguration config, DbPath dbPath, Map<String, DbEntity> tables) throws SQLException {
+ Map<String, Set<ExportedKey>> keys = new HashMap<String, Set<ExportedKey>>();
- fkEntity = map.getDbEntity(fkEntityName);
- DbPath path = new DbPath(entity.getCatalog(), entity.getSchema(), entity.getName());
- if (!config.getFiltersConfig().filter(path).tableFilter().isInclude(fkEntity)) {
- continue;
- }
+ for (DbEntity dbEntity : tables.values()) {
+ ResultSet rs;
+ try {
+ rs = getMetaData().getExportedKeys(dbPath.catalog, dbPath.schema, dbEntity.getName());
+ } catch (SQLException cay182Ex) {
+ // Sybase-specific - the line above blows on VIEWS, see CAY-182.
+ LOGGER.info("Error getting relationships for '" + dbPath + "', ignoring. "
+ + cay182Ex.getMessage(), cay182Ex);
+ return new HashMap<String, Set<ExportedKey>>();
+ }
+ try {
+ while (rs.next()) {
+ ExportedKey key = ExportedKey.extractData(rs);
+
+ DbEntity fkEntity = tables.get(key.getFKTableName());
if (fkEntity == null) {
- LOGGER.info("FK warning: no entity found for name '" + fkEntityName + "'");
- } else if (skippedEntities.contains(entity) && skippedEntities.contains(fkEntity)) {
- // cay-479 - don't doLoad relationships between two skipped entities.
+ skipRelationLog(key, key.getFKTableName());
continue;
- } else {
- // init relationship
- forwardRelationship = new DbRelationship(generateName(entity, key, true));
- forwardRelationship.setSourceEntity(entity);
- forwardRelationship.setTargetEntity(fkEntity);
- entity.addRelationship(forwardRelationship);
-
- reverseRelationship = new DbRelationshipDetected(generateName(fkEntity, key, false));
- reverseRelationship.setFkName(key.getFKName());
- reverseRelationship.setToMany(false);
- reverseRelationship.setSourceEntity(fkEntity);
- reverseRelationship.setTargetEntity(entity);
- fkEntity.addRelationship(reverseRelationship);
}
- }
-
- if (fkEntity != null) {
- // Create and append joins
- String pkName = key.getPKColumnName();
- String fkName = key.getFKColumnName();
-
- // skip invalid joins...
- DbAttribute pkAtt = entity.getAttribute(pkName);
- if (pkAtt == null) {
- LOGGER.info("no attribute for declared primary key: " + pkName);
+ DbPath path = new DbPath(fkEntity.getCatalog(), fkEntity.getSchema(), fkEntity.getName());
+ if (!config.getFiltersConfig().filter(path).tableFilter().isInclude(fkEntity)) {
continue;
}
- DbAttribute fkAtt = fkEntity.getAttribute(fkName);
- if (fkAtt == null) {
- LOGGER.info("no attribute for declared foreign key: " + fkName);
- continue;
- }
+ Set<ExportedKey> exportedKeys = keys.get(key.getStrKey());
+ if (exportedKeys == null) {
+ exportedKeys = new TreeSet<ExportedKey>();
- if (forwardRelationship != null) {
- forwardRelationship.addJoin(new DbJoin(forwardRelationship, pkName, fkName));
- }
- if (reverseRelationship != null) {
- reverseRelationship.addJoin(new DbJoin(reverseRelationship, fkName, pkName));
+ keys.put(key.getStrKey(), exportedKeys);
}
-
+ exportedKeys.add(key);
}
- }
- if (forwardRelationship != null) {
- postProcessMasterDbRelationship(forwardRelationship, key);
- forwardRelationship = null;
+ } finally {
+ rs.close();
}
-
- } finally {
- rs.close();
}
+ return keys;
+ }
+
+ private void skipRelationLog(ExportedKey key, String tableName) {
+ // if (LOGGER.isDebugEnabled()) {
+ LOGGER.info("Skip relation: '" + key + "' because table '" + tableName + "' not found");
+ // }
}
private String generateName(DbEntity entity, ExportedKey key, boolean toMany) {
@@ -615,29 +619,7 @@ public class DbLoader {
* called on relationships from PK to FK, not the reverse ones.
*/
protected void postProcessMasterDbRelationship(DbRelationship relationship, ExportedKey key) {
- boolean toPK = true;
- List<DbJoin> joins = relationship.getJoins();
-
- for (DbJoin join : joins) {
- if (!join.getTarget().isPrimaryKey()) {
- toPK = false;
- break;
- }
-
- }
-
- relationship.setToDependentPK(toPK);
- relationship.setToMany(!(toPK && relationship.getTargetEntity().getPrimaryKeys().size() == joins.size()));
- // if this is really to-one we need to rename the relationship
- if (!relationship.isToMany()) {
- Entity source = relationship.getSourceEntity();
- source.removeRelationship(relationship.getName());
- relationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.dbRelationship, source,
- nameGenerator.createDbRelationshipName(key, false)));
-
- source.addRelationship(relationship);
- }
}
/**
@@ -731,8 +713,8 @@ public class DbLoader {
config.setFiltersConfig(new FiltersConfig(new EntityFilters(
new DbPath(null, schemaPattern), transformPatternToFilter(tablePattern), TRUE, NULL)));
config.setTableTypes(tableTypes);
-
- load(dataMap, config);
+
+ load(dataMap, config, tableTypes);
return dataMap;
}
@@ -753,21 +735,35 @@ public class DbLoader {
*
* @since 4.0
*/
- public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+ public void load(DataMap dataMap, DbLoaderConfiguration config, String... tableTypes) throws SQLException {
- String[] tableTypes = config.getTableTypes() == null ? this.getDefaultTableTypes() : config.getTableTypes();
- List<DbEntity> entities = loadDbEntities(dataMap, config, getTables(config, tableTypes));
+ Map<DbPath, Map<String, DbEntity>> tables = getTables(config, tableTypes);
+ List<DbEntity> entities = loadDbEntities(dataMap, config, tables);
- if (entities != null) {
- loadDbRelationships(dataMap, config, entities);
- loadObjEntities(dataMap, config, entities);
+ if (entities != null) {
+ loadDbRelationships(config, tables);
- flattenManyToManyRelationships(dataMap);
- fireObjEntitiesAddedEvents(dataMap);
- }
+ loadObjEntities(dataMap, config, entities);
+ flattenManyToManyRelationships(dataMap);
+ fireObjEntitiesAddedEvents(dataMap);
+ }
+ }
- loadProcedures(dataMap, config);
- }
+ /**
+ * Performs database reverse engineering to match the specified catalog,
+ * schema, table name and table type patterns and fills the specified
+ * DataMap object with DB and object mapping info.
+ *
+ * @since 3.2
+ */
+ public DataMap load(DbLoaderConfiguration config) throws SQLException {
+
+ DataMap dataMap = new DataMap();
+ load(dataMap, config, config.getTableTypes());
+ loadProcedures(dataMap, config);
+
+ return dataMap;
+ }
/**
* Loads database stored procedures into the DataMap.
@@ -809,7 +805,7 @@ public class DbLoader {
return procedures;
}
- loadProceduresColumns(procedures);
+ loadProceduresColumns(config, procedures);
for (Procedure procedure : procedures.values()) {
dataMap.addProcedure(procedure);
@@ -818,65 +814,75 @@ public class DbLoader {
return procedures;
}
- private void loadProceduresColumns(Map<String, Procedure> procedures) throws SQLException {
- ResultSet columnsRS = getMetaData().getProcedureColumns(null, null, null, null); // TODO catalog, schema
- try {
- while (columnsRS.next()) {
-
- String schema = columnsRS.getString("PROCEDURE_SCHEM");
- String name = columnsRS.getString("PROCEDURE_NAME");
- String key = (schema == null ? "" : schema + '.') + name ;
- Procedure procedure = procedures.get(key);
- if (procedure == null) {
- continue;
- }
-
- String columnName = columnsRS.getString("COLUMN_NAME");
+ private void loadProceduresColumns(DbLoaderConfiguration config, Map<String, Procedure> procedures) throws SQLException {
+ for (DbPath dbPath : config.getFiltersConfig().pathsForQueries()) {
+ ResultSet columnsRS = getMetaData().getProcedureColumns(dbPath.catalog, dbPath.schema, null, null);
+ try {
+ while (columnsRS.next()) {
- // skip ResultSet columns, as they are not described in Cayenne procedures yet...
- short type = columnsRS.getShort("COLUMN_TYPE");
- if (type == DatabaseMetaData.procedureColumnResult) {
- LOGGER.debug("skipping ResultSet column: " + key + "." + columnName);
- }
+ String schema = columnsRS.getString("PROCEDURE_SCHEM");
+ String name = columnsRS.getString("PROCEDURE_NAME");
+ String key = (schema == null ? "" : schema + '.') + name ;
+ Procedure procedure = procedures.get(key);
+ if (procedure == null) {
+ continue;
+ }
- if (columnName == null) {
- if (type == DatabaseMetaData.procedureColumnReturn) {
- LOGGER.debug("null column name, assuming result column: " + key);
- columnName = "_return_value";
- procedure.setReturningValue(true);
- } else {
- LOGGER.info("invalid null column name, skipping column : " + key);
+ ProcedureParameter column = loadProcedureParams(columnsRS, key, procedure);
+ if (column == null) {
continue;
}
+ procedure.addCallParameter(column);
}
+ } finally {
+ columnsRS.close();
+ }
+ }
+ }
- int columnType = columnsRS.getInt("DATA_TYPE");
+ private ProcedureParameter loadProcedureParams(ResultSet columnsRS, String key, Procedure procedure) throws SQLException {
+ String columnName = columnsRS.getString("COLUMN_NAME");
- // ignore precision of non-decimal columns
- int decimalDigits = -1;
- if (TypesMapping.isDecimal(columnType)) {
- decimalDigits = columnsRS.getShort("SCALE");
- if (columnsRS.wasNull()) {
- decimalDigits = -1;
- }
- }
+ // skip ResultSet columns, as they are not described in Cayenne procedures yet...
+ short type = columnsRS.getShort("COLUMN_TYPE");
+ if (type == DatabaseMetaData.procedureColumnResult) {
+ LOGGER.debug("skipping ResultSet column: " + key + "." + columnName);
+ }
- ProcedureParameter column = new ProcedureParameter(columnName);
- int direction = getDirection(type);
- if (direction != -1) {
- column.setDirection(direction);
- }
+ if (columnName == null) {
+ if (type == DatabaseMetaData.procedureColumnReturn) {
+ LOGGER.debug("null column name, assuming result column: " + key);
+ columnName = "_return_value";
+ procedure.setReturningValue(true);
+ } else {
+ LOGGER.info("invalid null column name, skipping column : " + key);
+ return null;
+ }
+ }
- column.setType(columnType);
- column.setMaxLength(columnsRS.getInt("LENGTH"));
- column.setPrecision(decimalDigits);
+ int columnType = columnsRS.getInt("DATA_TYPE");
- column.setProcedure(procedure);
- procedure.addCallParameter(column);
+ // ignore precision of non-decimal columns
+ int decimalDigits = -1;
+ if (TypesMapping.isDecimal(columnType)) {
+ decimalDigits = columnsRS.getShort("SCALE");
+ if (columnsRS.wasNull()) {
+ decimalDigits = -1;
}
- } finally {
- columnsRS.close();
}
+
+ ProcedureParameter column = new ProcedureParameter(columnName);
+ int direction = getDirection(type);
+ if (direction != -1) {
+ column.setDirection(direction);
+ }
+
+ column.setType(columnType);
+ column.setMaxLength(columnsRS.getInt("LENGTH"));
+ column.setPrecision(decimalDigits);
+
+ column.setProcedure(procedure);
+ return column;
}
private static int getDirection(short type) {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
index 6e392d8..792c8a8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/ManyToManyCandidateEntity.java
@@ -109,7 +109,8 @@ public class ManyToManyCandidateEntity {
null,
rel2.getTargetEntity().getName(),
rel2.getTargetAttributes().iterator().next().getName(),
- null);
+ null,
+ (short) 1);
ObjRelationship newRelationship = new ObjRelationship();
newRelationship.setName(DefaultUniqueNameGenerator.generate(NameCheckers.objRelationship, srcEntity,
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
index 813ce94..eb4a863 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/loader/filters/DbPath.java
@@ -18,6 +18,8 @@
****************************************************************/
package org.apache.cayenne.access.loader.filters;
+import org.apache.cayenne.map.DbEntity;
+
import java.util.regex.Pattern;
/**
@@ -150,4 +152,8 @@ public class DbPath implements Comparable<DbPath> {
return null;
}
}
+
+ public static DbPath build(DbEntity entity) {
+ return new DbPath(entity.getCatalog(), entity.getSchema(), entity.getName());
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
index 1c1c885..42697fe 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/naming/ExportedKey.java
@@ -18,6 +18,10 @@
****************************************************************/
package org.apache.cayenne.map.naming;
+import org.apache.cayenne.util.EqualsBuilder;
+import org.apache.cayenne.util.HashCodeBuilder;
+import org.apache.commons.lang.builder.CompareToBuilder;
+
import java.sql.ResultSet;
import java.sql.SQLException;
@@ -26,45 +30,49 @@ import java.sql.SQLException;
* in database. It can be used for creating names for relationships
*
*/
-public class ExportedKey {
+public class ExportedKey implements Comparable {
/**
* Name of source table
*/
- String pkTable;
-
+ public final String pkTable;
+
/**
* Name of source column
*/
- String pkColumn;
-
+ public final String pkColumn;
+
/**
* Name of destination table
*/
- String fkTable;
+ public final String fkTable;
/**
* Name of destination column
*/
- String fkColumn;
+ public final String fkColumn;
/**
* Name of foreign key (might be null)
*/
- String fkName;
-
+ public final String fkName;
+
/**
* Name of primary key (might be null)
*/
- String pkName;
-
+ public final String pkName;
+
+
+ public final short keySeq;
+
public ExportedKey(String pkTable, String pkColumn, String pkName,
- String fkTable, String fkColumn, String fkName) {
+ String fkTable, String fkColumn, String fkName, short keySeq) {
this.pkTable = pkTable;
this.pkColumn = pkColumn;
this.pkName = pkName;
this.fkTable = fkTable;
this.fkColumn = fkColumn;
this.fkName = fkName;
+ this.keySeq = keySeq;
}
/**
@@ -75,16 +83,15 @@ public class ExportedKey {
* DataBaseMetaData.getExportedKeys(...)
*/
public static ExportedKey extractData(ResultSet rs) throws SQLException {
- ExportedKey key = new ExportedKey(
+ return new ExportedKey(
rs.getString("PKTABLE_NAME"),
rs.getString("PKCOLUMN_NAME"),
rs.getString("PK_NAME"),
rs.getString("FKTABLE_NAME"),
rs.getString("FKCOLUMN_NAME"),
- rs.getString("FK_NAME")
+ rs.getString("FK_NAME"),
+ rs.getShort("KEY_SEQ")
);
-
- return key;
}
/**
@@ -128,4 +135,76 @@ public class ExportedKey {
public String getFKName() {
return fkName;
}
+
+ public short getKeySeq() {
+ return keySeq;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (obj == this) {
+ return true;
+ }
+ if (obj.getClass() != getClass()) {
+ return false;
+ }
+ ExportedKey rhs = (ExportedKey) obj;
+ return new EqualsBuilder()
+ .append(this.pkTable, rhs.pkTable)
+ .append(this.pkColumn, rhs.pkColumn)
+ .append(this.fkTable, rhs.fkTable)
+ .append(this.fkColumn, rhs.fkColumn)
+ .append(this.fkName, rhs.fkName)
+ .append(this.pkName, rhs.pkName)
+ .append(this.keySeq, rhs.keySeq)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder()
+ .append(pkTable)
+ .append(pkColumn)
+ .append(fkTable)
+ .append(fkColumn)
+ .append(fkName)
+ .append(pkName)
+ .append(keySeq)
+ .toHashCode();
+ }
+
+ @Override
+ public int compareTo(Object obj) {
+ if (obj == null || !obj.getClass().equals(getClass())) {
+ throw new IllegalArgumentException();
+ }
+ if (obj == this) {
+ return 0;
+ }
+
+ ExportedKey rhs = (ExportedKey) obj;
+ return new CompareToBuilder()
+ .append(pkTable, rhs.pkTable)
+ .append(pkName, rhs.pkName)
+ .append(fkTable, rhs.fkTable)
+ .append(fkName, rhs.fkName)
+ .append(keySeq, rhs.keySeq)
+ .append(pkColumn, rhs.pkColumn)
+ .append(fkColumn, rhs.fkColumn)
+ .toComparison();
+ }
+
+ @Override
+ public String toString() {
+ return getStrKey() + " # " + keySeq
+ + "(" + pkColumn + " <- " + fkColumn + ")";
+ }
+
+ public String getStrKey() {
+ return pkTable + "." + pkName + " <- " + fkTable + "." + fkName;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
index f036511..ef93589 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/merge/DbMerger.java
@@ -36,6 +36,9 @@ import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.DbLoader;
import org.apache.cayenne.access.loader.DbLoaderConfiguration;
import org.apache.cayenne.access.loader.DefaultDbLoaderDelegate;
+import org.apache.cayenne.access.loader.NameFilter;
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.map.Attribute;
import org.apache.cayenne.map.DataMap;
@@ -67,14 +70,6 @@ public class DbMerger {
}
/**
- * A method that return true if the given table name should be included. The default
- * implementation include all tables.
- */
- public boolean includeTableName(String tableName) {
- return true;
- }
-
- /**
* Create and return a {@link List} of {@link MergerToken}s to alter the given
* {@link DataNode} to match the given {@link DataMap}
*/
@@ -87,7 +82,7 @@ public class DbMerger {
* {@link DataNode} to match the given {@link DataMap}
*/
public List<MergerToken> createMergeTokens(DbLoader dbLoader, DataMap existing, DbLoaderConfiguration config) {
- return createMergeTokens(existing, loadDataMapFromDb(dbLoader, config));
+ return createMergeTokens(existing, loadDataMapFromDb(dbLoader, config), config.getFiltersConfig());
}
/**
@@ -95,18 +90,18 @@ public class DbMerger {
* {@link DataNode} to match the given {@link DataMap}
*/
public List<MergerToken> createMergeTokens(DataSource dataSource, DbAdapter adapter, DataMap existingDataMap, DbLoaderConfiguration config) {
- return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter, config));
+ return createMergeTokens(existingDataMap, loadDataMapFromDb(dataSource, adapter, config), config.getFiltersConfig());
}
/**
* Create and return a {@link List} of {@link MergerToken}s to alter the given
* {@link DataNode} to match the given {@link DataMap}
*/
- public List<MergerToken> createMergeTokens(DataMap existing, DataMap loadedFomDb) {
+ public List<MergerToken> createMergeTokens(DataMap existing, DataMap loadedFomDb, FiltersConfig filtersConfig) {
loadedFomDb.setQuotingSQLIdentifiers(existing.isQuotingSQLIdentifiers());
- List<MergerToken> tokens = createMergeTokens(existing.getDbEntities(), loadedFomDb.getDbEntities());
+ List<MergerToken> tokens = createMergeTokens(filter(existing, filtersConfig), loadedFomDb.getDbEntities());
// sort. use a custom Comparator since only toDb tokens are comparable by now
@@ -126,6 +121,16 @@ public class DbMerger {
return tokens;
}
+ private Collection<DbEntity> filter(DataMap existing, FiltersConfig filtersConfig) {
+ Collection<DbEntity> existingFiltered = new LinkedList<DbEntity>();
+ for (DbEntity entity : existing.getDbEntities()) {
+ if (filtersConfig.filter(DbPath.build(entity)).tableFilter().isInclude(entity)) {
+ existingFiltered.add(entity);
+ }
+ }
+ return existingFiltered;
+ }
+
private DataMap loadDataMapFromDb(DataSource dataSource, DbAdapter adapter, DbLoaderConfiguration config) {
Connection conn = null;
try {
@@ -151,14 +156,13 @@ public class DbMerger {
}
private DataMap loadDataMapFromDb(DbLoader dbLoader, DbLoaderConfiguration config) {
- DataMap detectedDataMap = new DataMap();
try {
- dbLoader.load(detectedDataMap, config);
+ return dbLoader.load(config);
} catch (SQLException e) {
// TODO log
}
- return detectedDataMap;
+ return new DataMap();
}
/**
@@ -175,12 +179,6 @@ public class DbMerger {
for (DbEntity dbEntity : existing) {
String tableName = dbEntity.getName();
- if (!includeTableName(tableName)) {
- // TODO we have to cut this entities in db loader
- // TODO log
- continue;
- }
-
// look for table
DbEntity detectedEntity = findDbEntity(loadedFromDb, tableName);
if (detectedEntity == null) {
@@ -207,10 +205,6 @@ public class DbMerger {
// drop table
// TODO: support drop table. currently, too many tables are marked for drop
for (DbEntity e : dbEntitiesToDrop) {
- if (!includeTableName(e.getName())) {
- continue;
- }
-
tokens.add(factory.createDropTableToDb(e));
}
@@ -320,10 +314,6 @@ public class DbMerger {
List<MergerToken> tokens = new LinkedList<MergerToken>();
for (DbRelationship rel : dbEntity.getRelationships()) {
- if (!includeTableName(rel.getTargetEntityName())) {
- continue;
- }
-
if (findDbRelationship(detectedEntity, rel) == null) {
AddRelationshipToDb token = (AddRelationshipToDb)
factory.createAddRelationshipToDb(dbEntity, rel);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
index b6ba66e..40347be 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DbLoaderIT.java
@@ -19,11 +19,8 @@
package org.apache.cayenne.access;
-import java.sql.Types;
-import java.util.Collection;
-import java.util.List;
-
import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.filters.DbPath;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
@@ -45,13 +42,11 @@ import org.junit.Test;
import java.sql.Types;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
public class DbLoaderIT extends ServerCase {
@@ -104,7 +99,8 @@ public class DbLoaderIT extends ServerCase {
String tableLabel = adapter.tableTypeForTable();
- List<DbEntity> tables = loader.getTables(new DbLoaderConfiguration(), new String[] { tableLabel });
+ Collection<DbEntity> tables = loader.getTables(new DbLoaderConfiguration(), new String[] { tableLabel })
+ .values().iterator().next().values();
assertNotNull(tables);
@@ -128,7 +124,7 @@ public class DbLoaderIT extends ServerCase {
loader.setCreatingMeaningfulPK(true);
- List<DbEntity> testLoader = loader.getTables(CONFIG, tableLabel);
+ Map<DbPath, Map<String, DbEntity>> testLoader = loader.getTables(CONFIG, tableLabel);
if (testLoader.isEmpty()) {
testLoader = loader.getTables(CONFIG, tableLabel);
}
@@ -171,7 +167,13 @@ public class DbLoaderIT extends ServerCase {
}
// *** TESTING THIS ***
- loader.loadDbRelationships(map, CONFIG, entities);
+ HashMap<DbPath, Map<String, DbEntity>> tables = new HashMap<DbPath, Map<String, DbEntity>>();
+ HashMap<String, DbEntity> value = new HashMap<String, DbEntity>();
+ for (DbEntity e : entities) {
+ value.put(e.getName(), e);
+ }
+ tables.put(new DbPath(), value);
+ loader.loadDbRelationships(CONFIG, tables);
if (supportsFK) {
Collection<DbRelationship> rels = getDbEntity(map, "ARTIST").getRelationships();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
index 60d4933..2781ea6 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/access/loader/filters/DbPathTest.java
@@ -21,6 +21,9 @@ package org.apache.cayenne.access.loader.filters;
import org.junit.Test;
+import java.util.Set;
+import java.util.TreeSet;
+
import static org.apache.cayenne.access.loader.filters.FiltersFactory.path;
import static org.junit.Assert.*;
@@ -72,4 +75,19 @@ public class DbPathTest {
assertEquals(path1, path1.merge(path2));
assertEquals(path1, path2.merge(path1));
}
+
+ @Test
+ public void testEquals() throws Exception {
+ Set<DbPath> pathes = new TreeSet<DbPath>();
+ pathes.add(path("q", "w"));
+ pathes.add(path("q", null));
+ pathes.add(path("q", ""));
+ pathes.add(path("", ""));
+ pathes.add(path("q", "w"));
+ pathes.add(path("q", "w"));
+ pathes.add(path("q", "w"));
+ pathes.add(path("q", "w"));
+
+ assertEquals(4, pathes.size());
+ }
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/map/naming/LegacyNameGeneratorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/map/naming/LegacyNameGeneratorTest.java b/cayenne-server/src/test/java/org/apache/cayenne/map/naming/LegacyNameGeneratorTest.java
index 133c176..7773f28 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/map/naming/LegacyNameGeneratorTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/map/naming/LegacyNameGeneratorTest.java
@@ -32,12 +32,12 @@ public class LegacyNameGeneratorTest {
LegacyNameGenerator strategy = new LegacyNameGenerator();
ExportedKey key = new ExportedKey("ARTIST", "ARTIST_ID", null,
- "PAINTING", "ARTIST_ID", null);
+ "PAINTING", "ARTIST_ID", null, (short) 1);
assertEquals(strategy.createDbRelationshipName(key, false), "toArtist");
assertEquals(strategy.createDbRelationshipName(key, true), "paintingArray");
key = new ExportedKey("PERSON", "PERSON_ID", null,
- "PERSON", "MOTHER_ID", null);
+ "PERSON", "MOTHER_ID", null, (short) 1);
assertEquals(strategy.createDbRelationshipName(key, false), "toPerson");
assertEquals(strategy.createDbRelationshipName(key, true), "personArray");
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
index 7f08a0e..e235109 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/DropRelationshipToModelIT.java
@@ -125,21 +125,21 @@ public class DropRelationshipToModelIT extends MergeCase {
assertSame(objRel1To2, objRel2To1.getReverseRelationship());
assertSame(objRel2To1, objRel1To2.getReverseRelationship());
- // remove relationship and fk from model, merge to db and read to model
- dbEntity2.removeRelationship(rel2To1.getName());
- dbEntity1.removeRelationship(rel1To2.getName());
- dbEntity2.removeAttribute(e2col2.getName());
- List<MergerToken> tokens = createMergeTokens();
- assertTokens(tokens, 2, 1);
- for (MergerToken token : tokens) {
- if (token.getDirection().isToDb()) {
- execute(token);
- }
- }
- assertTokensAndExecute(0, 0);
- dbEntity2.addRelationship(rel2To1);
- dbEntity1.addRelationship(rel1To2);
- dbEntity2.addAttribute(e2col2);
+ // remove relationship and fk from model, merge to db and read to model
+ dbEntity2.removeRelationship(rel2To1.getName());
+ dbEntity1.removeRelationship(rel1To2.getName());
+ dbEntity2.removeAttribute(e2col2.getName());
+ List<MergerToken> tokens = createMergeTokens();
+ assertTokens(tokens, 3, 0);
+ for (MergerToken token : tokens) {
+ if (token.getDirection().isToDb()) {
+ execute(token);
+ }
+ }
+ assertTokensAndExecute(0, 0);
+ dbEntity2.addRelationship(rel2To1);
+ dbEntity1.addRelationship(rel1To2);
+ dbEntity2.addAttribute(e2col2);
// try do use the merger to remove the relationship in the model
tokens = createMergeTokens();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
index 8c999db..258f8a9 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergeCase.java
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.merge;
+import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
import static org.junit.Assert.assertEquals;
import java.sql.Connection;
@@ -29,6 +30,9 @@ import java.util.List;
import org.apache.cayenne.access.DataNode;
import org.apache.cayenne.access.loader.DbLoaderConfiguration;
+import org.apache.cayenne.access.loader.filters.DbPath;
+import org.apache.cayenne.access.loader.filters.EntityFilters;
+import org.apache.cayenne.access.loader.filters.FiltersConfig;
import org.apache.cayenne.configuration.server.ServerRuntime;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.di.Inject;
@@ -71,8 +75,6 @@ public abstract class MergeCase extends ServerCase {
protected DataMap map;
- private static List<String> TABLE_NAMES = Arrays.asList("ARTIST", "PAINTING", "NEW_TABLE", "NEW_TABLE2");
-
@Override
public void cleanUpDB() throws Exception {
dbHelper.update("ARTGROUP").set("PARENT_GROUP_ID", null, Types.INTEGER).execute();
@@ -100,19 +102,15 @@ public abstract class MergeCase extends ServerCase {
}
protected DbMerger createMerger(MergerFactory mergerFactory, ValueForNullProvider valueForNullProvider) {
- return new DbMerger(mergerFactory, valueForNullProvider) {
-
- @Override
- public boolean includeTableName(String tableName) {
- return TABLE_NAMES.contains(tableName.toUpperCase());
- }
- };
+ return new DbMerger(mergerFactory, valueForNullProvider);
}
- protected List<MergerToken> createMergeTokens() {
- return createMerger(node.getAdapter().mergerFactory())
- .createMergeTokens(node, map, new DbLoaderConfiguration());
- }
+ protected List<MergerToken> createMergeTokens() {
+ DbLoaderConfiguration loaderConfiguration = new DbLoaderConfiguration();
+ loaderConfiguration.setFiltersConfig(new FiltersConfig(new EntityFilters(DbPath.EMPTY, include("ARTIST|GALLERY|PAINTING|NEW_TABLE2?"), TRUE, TRUE)));
+
+ return createMerger(node.getAdapter().mergerFactory()).createMergeTokens(node, map, loaderConfiguration);
+ }
/**
* Remote binary pk {@link DbEntity} for {@link DbAdapter} not supporting
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
index 6deaaa3..409f1c9 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/merge/MergerFactoryIT.java
@@ -187,19 +187,9 @@ public class MergerFactoryIT extends MergeCase {
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("ARTIST_ID", Types.BIGINT, dbEntity);
- column3.setMandatory(false);
- dbEntity.addAttribute(column3);
+ 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);
@@ -229,7 +219,8 @@ public class MergerFactoryIT extends MergeCase {
dbEntity.removeRelationship(r1.getName());
artistDbEntity.removeRelationship(r2.getName());
resolver.refreshMappingCache();
- assertTokensAndExecute(1, 1);
+ assertTokensAndExecute(2, 0);
+// assertTokensAndExecute(1, 1);
assertTokensAndExecute(0, 0);
// clear up
@@ -251,20 +242,9 @@ public class MergerFactoryIT extends MergeCase {
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("ARTIST_ID", Types.BIGINT, dbEntity);
- column3.setMandatory(false);
- dbEntity.addAttribute(column3);
+ 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);
@@ -297,7 +277,7 @@ public class MergerFactoryIT extends MergeCase {
dbEntity.removeRelationship(r1.getName());
artistDbEntity.removeRelationship(r2.getName());
resolver.refreshMappingCache();
- assertTokensAndExecute(1, 1);
+ assertTokensAndExecute(2, 0);
assertTokensAndExecute(0, 0);
// clear up
@@ -311,4 +291,13 @@ public class MergerFactoryIT extends MergeCase {
assertTokensAndExecute(1, 0);
assertTokensAndExecute(0, 0);
}
+
+ private static DbAttribute attr(DbEntity dbEntity, String name, int type, boolean mandatory, boolean primaryKey) {
+ DbAttribute column1 = new DbAttribute(name, type, dbEntity);
+ column1.setMandatory(mandatory);
+ column1.setPrimaryKey(primaryKey);
+
+ dbEntity.addAttribute(column1);
+ return column1;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
index 8499b20..e3c54d5 100644
--- a/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
+++ b/cayenne-tools/src/main/java/org/apache/cayenne/tools/dbimport/DbImportAction.java
@@ -105,7 +105,8 @@ public class DbImportAction {
} else {
MergerFactory mergerFactory = adapter.mergerFactory();
- List<MergerToken> mergeTokens = new DbMerger(mergerFactory).createMergeTokens(existing, loadedFomDb);
+ List<MergerToken> mergeTokens = new DbMerger(mergerFactory).createMergeTokens(existing, loadedFomDb,
+ config.getDbLoaderConfig().getFiltersConfig());
if (mergeTokens.isEmpty()) {
logger.info("No changes to import.");
return;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-tools/src/test/java/org/apache/cayenne/map/naming/DefaultNameGeneratorTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/map/naming/DefaultNameGeneratorTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/map/naming/DefaultNameGeneratorTest.java
index 74fe191..fe5ed37 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/map/naming/DefaultNameGeneratorTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/map/naming/DefaultNameGeneratorTest.java
@@ -32,17 +32,17 @@ public class DefaultNameGeneratorTest {
DefaultNameGenerator strategy = new DefaultNameGenerator();
ExportedKey key = new ExportedKey("ARTIST", "ARTIST_ID", null,
- "PAINTING", "ARTIST_ID", null);
+ "PAINTING", "ARTIST_ID", null, (short) 1);
assertEquals(strategy.createDbRelationshipName(key, false), "artist");
assertEquals(strategy.createDbRelationshipName(key, true), "paintings");
key = new ExportedKey("PERSON", "PERSON_ID", null,
- "PERSON", "MOTHER_ID", null);
+ "PERSON", "MOTHER_ID", null, (short) 1);
assertEquals(strategy.createDbRelationshipName(key, false), "mother");
assertEquals(strategy.createDbRelationshipName(key, true), "people");
key = new ExportedKey("PERSON", "PERSON_ID", null,
- "ADDRESS", "SHIPPING_ADDRESS_ID", null);
+ "ADDRESS", "SHIPPING_ADDRESS_ID", null, (short) 1);
assertEquals(strategy.createDbRelationshipName(key, false), "shippingAddress");
assertEquals(strategy.createDbRelationshipName(key, true), "addresses");
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
----------------------------------------------------------------------
diff --git a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
index a2fb0f1..018ebb8 100644
--- a/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
+++ b/cayenne-tools/src/test/java/org/apache/cayenne/tools/dbimport/DbImportActionTest.java
@@ -88,7 +88,7 @@ public class DbImportActionTest {
DbLoader dbLoader = new DbLoader(null, null, null) {
@Override
- public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+ public void load(DataMap dataMap, DbLoaderConfiguration config, String ... tables) throws SQLException {
new DataMapBuilder(dataMap).withDbEntities(2).build();
}
@@ -129,7 +129,7 @@ public class DbImportActionTest {
public void testImportWithFieldChanged() throws Exception {
DbLoader dbLoader = new DbLoader(null, null, null) {
@Override
- public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+ public void load(DataMap dataMap, DbLoaderConfiguration config, String ... tables) throws SQLException {
new DataMapBuilder(dataMap).with(
dbEntity("ARTGROUP").attributes(
dbAttr("GROUP_ID").typeInt().primaryKey(),
@@ -198,7 +198,7 @@ public class DbImportActionTest {
public void testImportWithoutChanges() throws Exception {
DbLoader dbLoader = new DbLoader(null, null, null) {
@Override
- public void load(DataMap dataMap, DbLoaderConfiguration config) throws SQLException {
+ public void load(DataMap dataMap, DbLoaderConfiguration config, String ... tables) throws SQLException {
new DataMapBuilder(dataMap).with(
dbEntity("ARTGROUP").attributes(
dbAttr("NAME").typeVarchar(100).mandatory()
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
index aec9ee3..7956a66 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/autorelationship/InferRelationshipsControllerBase.java
@@ -220,7 +220,7 @@ public class InferRelationshipsControllerBase extends CayenneController {
String pkColumn,
String fkTable,
String fkColumn) {
- return new ExportedKey(pkTable, pkColumn, null, fkTable, fkColumn, null);
+ return new ExportedKey(pkTable, pkColumn, null, fkTable, fkColumn, null, (short) 1);
}
public List<InferredRelationship> getSelectedEntities() {
http://git-wip-us.apache.org/repos/asf/cayenne/blob/f3457df8/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
----------------------------------------------------------------------
diff --git a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
index 4db2356..14cbe94 100644
--- a/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
+++ b/modeler/cayenne-modeler/src/main/java/org/apache/cayenne/modeler/dialog/objentity/ObjRelationshipInfo.java
@@ -346,12 +346,8 @@ public class ObjRelationshipInfo extends CayenneController implements TreeSelect
.getInstance()
.getLastUsedStrategies()
.get(0)).createDbRelationshipName(
- new ExportedKey(targetModel.getSource().getName(),
- null,
- null,
- targetModel.getTarget().getName(),
- null,
- null),
+ new ExportedKey(targetModel.getSource().getName(), null, null,
+ targetModel.getTarget().getName(), null, null, (short) 1),
targetModel.isToMany()));
// note: NamedObjectFactory doesn't set source or target, just the name
[2/2] cayenne git commit: CAY-1976 Slow performance of DbMerger
Posted by aa...@apache.org.
CAY-1976 Slow performance of DbMerger
Merge branch '46'
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c9793921
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c9793921
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c9793921
Branch: refs/heads/master
Commit: c9793921b1bbdc7b26f808d7bdcee6085226b6ea
Parents: 4e88f9a f3457df
Author: aadamchik <aa...@apache.org>
Authored: Tue Dec 9 11:13:56 2014 +0300
Committer: aadamchik <aa...@apache.org>
Committed: Tue Dec 9 11:21:48 2014 +0300
----------------------------------------------------------------------
.../org/apache/cayenne/access/DbLoader.java | 500 ++++++++++---------
.../loader/ManyToManyCandidateEntity.java | 3 +-
.../cayenne/access/loader/filters/DbPath.java | 6 +
.../apache/cayenne/map/naming/ExportedKey.java | 111 +++-
.../java/org/apache/cayenne/merge/DbMerger.java | 48 +-
.../org/apache/cayenne/access/DbLoaderIT.java | 26 +-
.../access/loader/filters/DbPathTest.java | 18 +
.../map/naming/LegacyNameGeneratorTest.java | 4 +-
.../merge/DropRelationshipToModelIT.java | 30 +-
.../org/apache/cayenne/merge/MergeCase.java | 24 +-
.../apache/cayenne/merge/MergerFactoryIT.java | 47 +-
.../cayenne/tools/dbimport/DbImportAction.java | 3 +-
.../map/naming/DefaultNameGeneratorTest.java | 6 +-
.../tools/dbimport/DbImportActionTest.java | 6 +-
.../InferRelationshipsControllerBase.java | 2 +-
.../dialog/objentity/ObjRelationshipInfo.java | 8 +-
16 files changed, 464 insertions(+), 378 deletions(-)
----------------------------------------------------------------------