Re: Batch inserts
Re: Batch inserts
- Subject: Re: Batch inserts
- From: Kieran Kelleher <email@hidden>
- Date: Wed, 19 Dec 2007 14:45:36 -0500
### Eclipse Workspace Patch 1.0
#P ERExtensions
Index: Sources/er/extensions/ERXEOAccessUtilities.java
===================================================================
RCS file: /cvsroot/wonder/Wonder/Common/Frameworks/ERExtensions/Sources/er/extensions/ERXEOAccessUtilities.java,v
retrieving revision 1.94
diff -u -r1.94 ERXEOAccessUtilities.java
--- Sources/er/extensions/ERXEOAccessUtilities.java 2 Dec 2007 16:12:44 -0000 1.94
+++ Sources/er/extensions/ERXEOAccessUtilities.java 19 Dec 2007 19:44:48 -0000
@@ -60,14 +60,14 @@
public class ERXEOAccessUtilities {
/** logging support */
public static final Logger log = Logger.getLogger(ERXEOAccessUtilities.class);
-
+
/** SQL logger */
private static Logger sqlLoggingLogger = null;
/**
* Finds an entity that is contained in a string. This is used a lot in
* DirectToWeb. Example: "ListAllStudios"=>Studio
- *
+ *
* @param ec
* editing context
* @param string
@@ -105,7 +105,7 @@
/**
* Method used to determine if a given entity is a shared entity.
- *
+ *
* @param ec
* editing context
* @param entityName
@@ -121,7 +121,7 @@
/**
* Convenience method to get the next unique ID from a sequence.
- *
+ *
* @param ec
* editing context
* @param modelName
@@ -136,8 +136,8 @@
// around at
// the adaptor level and see if we can't find something better.
public static Number getNextValFromSequenceNamed(EOEditingContext ec, String modelName, String sequenceName) {
- EODatabaseContext dbContext = EOUtilities.databaseContextForModelNamed(ec, modelName);
- return ERXSQLHelper.newSQLHelper(dbContext).getNextValFromSequenceNamed(ec, modelName, sequenceName);
+ EODatabaseContext dbContext = EOUtilities.databaseContextForModelNamed(ec, modelName);
+ return ERXSQLHelper.newSQLHelper(dbContext).getNextValFromSequenceNamed(ec, modelName, sequenceName);
}
/**
@@ -145,7 +145,7 @@
* the {@link com.webobjects.eoaccess.EOUtilities EOUtilities}
* <code>rawRowsForSQL</code> in that it can be used with other statements
* besides just SELECT without throwing exceptions.
- *
+ *
* @param ec
* editing context that determines which model group and database
* context to use.
@@ -169,7 +169,7 @@
* the {@link com.webobjects.eoaccess.EOUtilities EOUtilities}
* <code>rawRowsForSQL</code> in that it can be used with other statements
* besides just SELECT without throwing exceptions.
- *
+ *
* @param ec
* editing context that determines which model group and database
* context to use.
@@ -193,12 +193,12 @@
/**
* Creates the SQL which is used by the provides EOFetchSpecification.
- *
+ *
* @param ec
* the EOEditingContext
* @param spec
* the EOFetchSpecification in question
- *
+ *
* @return the SQL which the EOFetchSpecification would use
*/
public static String sqlForFetchSpecification(EOEditingContext ec, EOFetchSpecification spec) {
@@ -207,7 +207,7 @@
/**
* Returns the raw rows for the given EOSQLExpression.
- *
+ *
* @param ec
* the EOEditingContext
* @param spec
@@ -216,7 +216,7 @@
* the name of the model in question
* @param expression
* the EOSQLExpression in question
- *
+ *
* @return array of dictionaries
*/
public static NSArray rawRowsForSQLExpression(EOEditingContext ec, String modelName, EOSQLExpression expression) {
@@ -246,7 +246,7 @@
/**
* Creates the SQL which is used by the provided EOFetchSpecification,
* limited by the given range.
- *
+ *
* @param ec
* the EOEditingContext
* @param spec
@@ -256,7 +256,7 @@
* @param end
* end of rows to fetch (-1 if not used)
* @deprecated
- *
+ *
* @return the EOSQLExpression which the EOFetchSpecification would use
*/
public static EOSQLExpression sqlExpressionForFetchSpecification(EOEditingContext ec, EOFetchSpecification spec, long start, long end) {
@@ -269,7 +269,7 @@
/**
* Returns the number of rows the supplied EOFetchSpecification would
* return.
- *
+ *
* @param ec
* the EOEditingContext
* @param spec
@@ -278,9 +278,9 @@
* @deprecated
*/
public static int rowCountForFetchSpecification(EOEditingContext ec, EOFetchSpecification spec) {
- EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, spec.entityName());
- EOModel model = entity.model();
- return ERXSQLHelper.newSQLHelper(ec, model.name()).rowCountForFetchSpecification(ec, spec);
+ EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, spec.entityName());
+ EOModel model = entity.model();
+ return ERXSQLHelper.newSQLHelper(ec, model.name()).rowCountForFetchSpecification(ec, spec);
}
/**
@@ -288,7 +288,7 @@
* If ec is null, it will try to get at the session via thread storage and
* use its defaultEditingContext. This is here now so we can remove the
* delgate in ERXApplication.
- *
+ *
* @param ec
* editing context used to locate the model group (can be null)
*/
@@ -311,7 +311,7 @@
/**
* Similar to the helper in EUUtilities, but allows for null editingContext.
- *
+ *
* @param ec
* editing context used to locate the model group (can be null)
* @param entityName
@@ -325,7 +325,7 @@
/**
* Creates an aggregate integer attribute for a given function name. These can then
* be used to query on when using raw rows.
- *
+ *
* @param ec
* editing context used to locate the model group
* @param function
@@ -337,13 +337,13 @@
* @return aggregate function attribute
*/
public static EOAttribute createAggregateAttribute(EOEditingContext ec, String function, String attributeName, String entityName) {
- return ERXEOAccessUtilities.createAggregateAttribute(ec, function, attributeName, entityName, Number.class, "i");
+ return ERXEOAccessUtilities.createAggregateAttribute(ec, function, attributeName, entityName, Number.class, "i");
}
-
+
/**
* Creates an aggregate attribute for a given function name. These can then
* be used to query on when using raw rows.
- *
+ *
* @param ec
* editing context used to locate the model group
* @param function
@@ -353,7 +353,7 @@
* @param entityName
* name of the entity
* @param valueClass the java class of this attribute's values
- * @param valueType the EOAttribute value type
+ * @param valueType the EOAttribute value type
* @return aggregate function attribute
*/
public static EOAttribute createAggregateAttribute(EOEditingContext ec, String function, String attributeName, String entityName, Class valueClass, String valueType) {
@@ -375,7 +375,7 @@
aggregate.setColumnName("p_object" + function + "Attribute");
aggregate.setClassName(valueClass.getName());
if (valueType != null) {
- aggregate.setValueType(valueType);
+ aggregate.setValueType(valueType);
}
aggregate.setReadFormat(function + "(t0." + attribute.columnName() + ")");
return aggregate;
@@ -383,30 +383,30 @@
/** oracle 9 has a maximum length of 30 characters for table names, column names and constraint names
* Foreign key constraint names are defined like this from the plugin:<br/><br/>
- *
+ *
* TABLENAME_FOEREIGNKEYNAME_FK <br/><br/>
- *
+ *
* The whole statement looks like this:<br/><br/>
- *
+ *
* ALTER TABLE [TABLENAME] ADD CONSTRAINT [CONSTRAINTNAME] FOREIGN KEY ([FK]) REFERENCES [DESTINATION_TABLE] ([PK]) DEFERRABLE INITIALLY DEFERRED
- *
+ *
* THIS means that the tablename and the columnname together cannot
* be longer than 26 characters.<br/><br/>
- *
+ *
* This method checks each foreign key constraint name and if it is longer than 30 characters its replaced
* with a unique name.
- *
+ *
* @see createSchemaSQLForEntitiesInModelWithNameAndOptions
*/
public static String createSchemaSQLForEntitiesInModelWithNameAndOptionsForOracle9(NSArray entities, String modelName, NSDictionary optionsCreate) {
EODatabaseContext dc = EOUtilities.databaseContextForModelNamed(ERXEC.newEditingContext(), modelName);
return ERXSQLHelper.newSQLHelper(dc).createSchemaSQLForEntitiesInModelWithNameAndOptions(entities, modelName, optionsCreate);
}
-
+
/**
* creates SQL to create tables for the specified Entities. This can be used
* with EOUtilities rawRowsForSQL method to create the tables.
- *
+ *
* @param entities
* a NSArray containing the entities for which create table
* statements should be generated or null if all entitites in the
@@ -428,7 +428,7 @@
* <li>EOSchemaGeneration.DropDatabaseKey</li>
* <br/><br>
* Possible values are <code>YES</code> and <code>NO</code>
- *
+ *
* @return a <code>String</code> containing SQL statements to create
* tables
* @deprecated
@@ -437,10 +437,10 @@
EODatabaseContext dc = EOUtilities.databaseContextForModelNamed(ERXEC.newEditingContext(), modelName);
return ERXSQLHelper.newSQLHelper(dc).createSchemaSQLForEntitiesInModelWithNameAndOptions(entities, modelName, optionsCreate);
}
-
+
/**
* Creates the schema sql for a set of entities.
- *
+ *
* @param entities the entities to create sql for
* @param databaseContext the database context to use
* @param optionsCreate the options (@see createSchemaSQLForEntitiesInModelWithNameAndOptions)
@@ -448,13 +448,13 @@
* @deprecated
*/
public static String createSchemaSQLForEntitiesWithOptions(NSArray entities, EODatabaseContext databaseContext, NSDictionary optionsCreate) {
- return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesWithOptions(entities, databaseContext, optionsCreate);
+ return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesWithOptions(entities, databaseContext, optionsCreate);
}
-
+
/**
* creates SQL to create tables for the specified Entities. This can be used
* with EOUtilities rawRowsForSQL method to create the tables.
- *
+ *
* @param entities
* a NSArray containing the entities for which create table
* statements should be generated or null if all entitites in the
@@ -474,20 +474,20 @@
* </ul>
* <br/><br>
* Possible values are <code>YES</code> and <code>NO</code>
- *
+ *
* @return a <code>String</code> containing SQL statements to create
* tables
* @deprecated
*/
public static String createSchemaSQLForEntitiesInModelWithName(NSArray entities, String modelName) {
- EODatabaseContext databaseContext = EOUtilities.databaseContextForModelNamed(ERXEC.newEditingContext(), modelName);
- return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesInModelWithName(entities, modelName);
+ EODatabaseContext databaseContext = EOUtilities.databaseContextForModelNamed(ERXEC.newEditingContext(), modelName);
+ return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesInModelWithName(entities, modelName);
}
/**
* creates SQL to create tables for the specified Entities. This can be used
* with EOUtilities rawRowsForSQL method to create the tables.
- *
+ *
* @param entities
* a NSArray containing the entities for which create table
* statements should be generated or null if all entitites in the
@@ -502,7 +502,7 @@
* @deprecated
*/
public static String createSchemaSQLForEntitiesInDatabaseContext(NSArray entities, EODatabaseContext databaseContext, boolean create, boolean drop) {
- return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesInDatabaseContext(entities, databaseContext, create, drop);
+ return ERXSQLHelper.newSQLHelper(databaseContext).createSchemaSQLForEntitiesInDatabaseContext(entities, databaseContext, create, drop);
}
/**
@@ -521,7 +521,7 @@
public static String createIndexSQLForEntities(NSArray entities) {
return createIndexSQLForEntities(entities, null);
}
-
+
/**
* @deprecated
*/
@@ -554,7 +554,7 @@
/**
* Returns true if the exception is an optimistic locking exception.
- *
+ *
* @param exception
* the exception as recieved from saveChanges()
* @return true if the error could be handled.
@@ -581,27 +581,27 @@
*/
//CHECKME ak is this description correct?
public static NSArray snapshotsForObjectsFromRelationshipNamed(NSArray eos, String relKey) {
- NSMutableArray result = new NSMutableArray();
- if (eos.count() > 0) {
- EOEnterpriseObject eo = (EOEnterpriseObject)eos.lastObject();
- String entityName = eo.entityName();
- EOEditingContext ec = eo.editingContext();
- EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, entityName);
- EORelationship relationship = entity.relationshipNamed(relKey);
- if(relationship.sourceAttributes().count() == 1) {
- EOAttribute attribute = (EOAttribute) relationship.sourceAttributes().lastObject();
- EODatabaseContext context = EOUtilities.databaseContextForModelNamed(ec, entity.model().name());
- String name = attribute.name();
- for (Enumeration e = eos.objectEnumerator(); e.hasMoreElements();) {
- EOEnterpriseObject target = (EOEnterpriseObject) e.nextElement();
- Object value = (context.snapshotForGlobalID(ec.globalIDForObject(target))).valueForKey(name);
- result.addObject(value);
- }
- } else {
- throw new IllegalArgumentException("Has more than one relationship attribute: " + relKey);
- }
- }
- return result;
+ NSMutableArray result = new NSMutableArray();
+ if (eos.count() > 0) {
+ EOEnterpriseObject eo = (EOEnterpriseObject)eos.lastObject();
+ String entityName = eo.entityName();
+ EOEditingContext ec = eo.editingContext();
+ EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, entityName);
+ EORelationship relationship = entity.relationshipNamed(relKey);
+ if(relationship.sourceAttributes().count() == 1) {
+ EOAttribute attribute = (EOAttribute) relationship.sourceAttributes().lastObject();
+ EODatabaseContext context = EOUtilities.databaseContextForModelNamed(ec, entity.model().name());
+ String name = attribute.name();
+ for (Enumeration e = eos.objectEnumerator(); e.hasMoreElements();) {
+ EOEnterpriseObject target = (EOEnterpriseObject) e.nextElement();
+ Object value = (context.snapshotForGlobalID(ec.globalIDForObject(target))).valueForKey(name);
+ result.addObject(value);
+ }
+ } else {
+ throw new IllegalArgumentException("Has more than one relationship attribute: " + relKey);
+ }
+ }
+ return result;
}
/**
@@ -611,7 +611,7 @@
* the same method that EOF uses by default for generating primary keys. See
* {@link ERXGeneratesPrimaryKeyInterface}for more information about using
* a newly created dictionary as the primary key for an enterprise object.
- *
+ *
* @param ec
* editing context
* @param entityName
@@ -619,32 +619,32 @@
* @return a dictionary containing a new primary key for the given entity.
*/
public static NSDictionary primaryKeyDictionaryForEntity(EOEditingContext ec, String entityName) {
- EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, entityName);
- EODatabaseContext dbContext = EODatabaseContext.registeredDatabaseContextForModel(entity.model(), ec);
- NSDictionary primaryKey = null;
- dbContext.lock();
- try {
- EOAdaptorChannel adaptorChannel = dbContext.availableChannel().adaptorChannel();
- if (!adaptorChannel.isOpen()) {
- adaptorChannel.openChannel();
- }
- NSArray arr = adaptorChannel.primaryKeysForNewRowsWithEntity(1, entity);
- if (arr != null) {
- primaryKey = (NSDictionary) arr.lastObject();
- } else {
- log.warn("Could not get primary key for entity: " + entityName + " exception");
- }
- } catch (Exception e) {
- log.error("Caught exception when generating primary key for entity: " + entityName + " exception: " + e, e);
- } finally {
- dbContext.unlock();
- }
- return primaryKey;
+ EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, entityName);
+ EODatabaseContext dbContext = EODatabaseContext.registeredDatabaseContextForModel(entity.model(), ec);
+ NSDictionary primaryKey = null;
+ dbContext.lock();
+ try {
+ EOAdaptorChannel adaptorChannel = dbContext.availableChannel().adaptorChannel();
+ if (!adaptorChannel.isOpen()) {
+ adaptorChannel.openChannel();
+ }
+ NSArray arr = adaptorChannel.primaryKeysForNewRowsWithEntity(1, entity);
+ if (arr != null) {
+ primaryKey = (NSDictionary) arr.lastObject();
+ } else {
+ log.warn("Could not get primary key for entity: " + entityName + " exception");
+ }
+ } catch (Exception e) {
+ log.error("Caught exception when generating primary key for entity: " + entityName + " exception: " + e, e);
+ } finally {
+ dbContext.unlock();
+ }
+ return primaryKey;
}
-
+
/**
* Creates an array containing all of the primary keys of the given objects.
- *
+ *
* @param eos
* array of enterprise objects
*/
@@ -672,7 +672,7 @@
/**
* Creates an array of relationships and attributes from the given keypath to give to the
* EOSQLExpression method <code>sqlStringForAttributePath</code>. If the last element is a
- * relationship, then the relationship's source attribute will get chosen. As such, this can only
+ * relationship, then the relationship's source attribute will get chosen. As such, this can only
* work for single-value relationships in the last element.
* @param entity
* @param keyPath
@@ -686,9 +686,9 @@
part = parts[i];
EORelationship relationship = entity.anyRelationshipNamed(part);
if(relationship == null) {
- // CHECKME AK: it would probably be better to return null
- // to indocate that this is not a valid path?
- return NSArray.EmptyArray;
+ // CHECKME AK: it would probably be better to return null
+ // to indocate that this is not a valid path?
+ return NSArray.EmptyArray;
}
entity = relationship.destinationEntity();
result.addObject(relationship);
@@ -701,9 +701,9 @@
throw new IllegalArgumentException("Last element is not an attribute nor a relationship: " + keyPath);
}
if (relationship.isFlattened()) {
- NSArray path = attributePathForKeyPath(entity, relationship.definition());
- result.addObjectsFromArray(path);
- return result;
+ NSArray path = attributePathForKeyPath(entity, relationship.definition());
+ result.addObjectsFromArray(path);
+ return result;
} else {
attribute = ((EOJoin) relationship.joins().lastObject()).sourceAttribute();
}
@@ -717,12 +717,12 @@
* @deprecated
*/
public static String sqlWhereClauseStringForKey(EOSQLExpression e, String key, NSArray valueArray) {
- return ERXSQLHelper.newSQLHelper(e).sqlWhereClauseStringForKey(e, key, valueArray);
+ return ERXSQLHelper.newSQLHelper(e).sqlWhereClauseStringForKey(e, key, valueArray);
}
/**
* Returns the database context for an EO.
- *
+ *
* @param eo the EO to get a database context for
* @return the eo's database context
*/
@@ -732,11 +732,11 @@
EODatabaseContext databaseContext = (EODatabaseContext) osc.objectStoreForObject(eo);
return databaseContext;
}
-
+
/**
* Returns the database context for the given entity in the given
* EOObjectStoreCoordinator
- *
+ *
* @param entityName
* @param osc
* @return
@@ -750,7 +750,7 @@
/**
* Closes the (JDBC) Connection from all database channels for the specified
* EOObjectStoreCoordinator
- *
+ *
* @param osc,
* the EOObjectStoreCoordinator from which the (JDBC)Connections
* should be closed
@@ -769,7 +769,7 @@
EODatabaseChannel dbch = (EODatabaseChannel) channels.objectAtIndex(j);
if (!dbch.adaptorChannel().adaptorContext().hasOpenTransaction()) {
dbch.adaptorChannel().closeChannel();
-
+
} else {
log.warn("could not close Connection from " + dbch + " because its EOAdaptorContext "
+ dbch.adaptorChannel().adaptorContext() + " had open Transactions");
@@ -791,7 +791,7 @@
* @return
*/
private static Set _keysWithWarning = Collections.synchronizedSet(new HashSet());
-
+
public static EOEntity destinationEntityForKeyPath(EOEntity entity, String keyPath) {
if(keyPath == null || keyPath.length() == 0) {
return entity;
@@ -802,12 +802,12 @@
EORelationship rel = entity.anyRelationshipNamed(key);
if(rel == null) {
if(entity.anyAttributeNamed(key) == null) {
- if(key.indexOf("@") != 0) {
- if(!_keysWithWarning.contains(key + "-" + entity)) {
- _keysWithWarning.add(key + "-" + entity);
- log.warn("No relationship or attribute <" + key + "> in entity: " + entity);
- }
- }
+ if(key.indexOf("@") != 0) {
+ if(!_keysWithWarning.contains(key + "-" + entity)) {
+ _keysWithWarning.add(key + "-" + entity);
+ log.warn("No relationship or attribute <" + key + "> in entity: " + entity);
+ }
+ }
}
return null;
}
@@ -817,13 +817,13 @@
}
/** Returns the EOEntity for the provided EOEnterpriseObject if one exists
- *
+ *
* @param eo the EOEnterpriseObject
* @return the EOEntity from the EOEnterpriseObject
*/
public static EOEntity entityForEo(EOEnterpriseObject eo) {
EOClassDescription classDesc = eo.classDescription();
-
+
if (classDesc instanceof EOEntityClassDescription)
return ((EOEntityClassDescription)classDesc).entity();
return null;
@@ -838,18 +838,18 @@
NSArray cpNames = entity.classPropertyNames();
if (includeAttributes) {
- for (int i = attributes.count(); i-- > 0;) {
- EOAttribute att = (EOAttribute) attributes.objectAtIndex(i);
- String name = att.name();
- if (cpNames.containsObject(name) && !parentAttributeNames.containsObject(name)) {
- ret.addObject(att);
- }
- }
+ for (int i = attributes.count(); i-- > 0;) {
+ EOAttribute att = (EOAttribute) attributes.objectAtIndex(i);
+ String name = att.name();
+ if (cpNames.containsObject(name) && !parentAttributeNames.containsObject(name)) {
+ ret.addObject(att);
+ }
+ }
}
-
+
NSArray parentRelationships = (NSArray) entity.parentEntity().relationships().valueForKey("name");
NSArray relationships = entity.relationships();
-
+
for (int i = relationships.count(); i-- > 0;) {
EORelationship element = (EORelationship) relationships.objectAtIndex(i);
if ((element.isToMany() && includeToManyRelationships)
@@ -864,7 +864,7 @@
}
public static NSArray externalNamesForEntity(EOEntity entity, boolean includeParentEntities) {
- if (includeParentEntities) {
+ if (includeParentEntities) {
entity = rootEntityForEntity(entity);
}
NSMutableArray entityNames = new NSMutableArray();
@@ -875,7 +875,7 @@
entityNames.addObjectsFromArray(names);
}
}
- entityNames.addObject(entity.externalName());
+ entityNames.addObject(entity.externalName());
return ERXArrayUtilities.arrayWithoutDuplicates(entityNames);
}
@@ -928,96 +928,96 @@
}
}
if (ERXStats.isTrackingStatistics()) {
- String statement = expression.statement();
- // AK: special postgres data PK handling
- statement = statement.replaceAll("decode\\(.*?\\)", "?");
- // IN's can be quite long and are normally not bound
- statement = statement.replaceAll(" IN \\(.*?\\)", " IN ([removed])");
- statement = statement.replaceAll("([a-zA-Z0-9_\\.]+)\\s+IN \\(.*?\\)(\\s+OR\\s+\\1\\s+IN \\(.*?\\))+", " IN ([multi removed])");
- // the cols are always the same, replace with *
- statement = statement.replaceAll("((t0|T0)\\.[a-zA-Z0-9_]+\\,\\s*)*(t0|T0)\\.[a-zA-Z0-9_\\.]+\\s+FROM\\s+", "t0.* FROM ");
- ERXStats.addDurationForKey(millisecondsNeeded, entityName + ": " +statement);
+ String statement = expression.statement();
+ // AK: special postgres data PK handling
+ statement = statement.replaceAll("decode\\(.*?\\)", "?");
+ // IN's can be quite long and are normally not bound
+ statement = statement.replaceAll(" IN \\(.*?\\)", " IN ([removed])");
+ statement = statement.replaceAll("([a-zA-Z0-9_\\.]+)\\s+IN \\(.*?\\)(\\s+OR\\s+\\1\\s+IN \\(.*?\\))+", " IN ([multi removed])");
+ // the cols are always the same, replace with *
+ statement = statement.replaceAll("((t0|T0)\\.[a-zA-Z0-9_]+\\,\\s*)*(t0|T0)\\.[a-zA-Z0-9_\\.]+\\s+FROM\\s+", "t0.* FROM ");
+ ERXStats.addDurationForKey(millisecondsNeeded, entityName + ": " +statement);
}
if (needsLog) {
String logString = createLogString(channel, expression, millisecondsNeeded);
- if (logString.length() > maxLength) {
- logString = logString.substring(0, maxLength);
- }
+ if (logString.length() > maxLength) {
+ logString = logString.substring(0, maxLength);
+ }
if (millisecondsNeeded > errorMilliseconds) {
- sqlLoggingLogger.error(logString, new RuntimeException("Statement running too long"));
- } else if (millisecondsNeeded > warnMilliseconds) {
- sqlLoggingLogger.warn(logString);
- } else if (millisecondsNeeded > infoMilliseconds) {
- if (sqlLoggingLogger.isInfoEnabled()) {
- sqlLoggingLogger.info(logString);
- }
- } else if (millisecondsNeeded > debugMilliseconds) {
- if (sqlLoggingLogger.isDebugEnabled()) {
- sqlLoggingLogger.debug(logString);
- }
- }
+ sqlLoggingLogger.error(logString, new RuntimeException("Statement running too long"));
+ } else if (millisecondsNeeded > warnMilliseconds) {
+ sqlLoggingLogger.warn(logString);
+ } else if (millisecondsNeeded > infoMilliseconds) {
+ if (sqlLoggingLogger.isInfoEnabled()) {
+ sqlLoggingLogger.info(logString);
+ }
+ } else if (millisecondsNeeded > debugMilliseconds) {
+ if (sqlLoggingLogger.isDebugEnabled()) {
+ sqlLoggingLogger.debug(logString);
+ }
+ }
}
}
}
- public static String createLogString(EOAdaptorChannel channel, EOSQLExpression expression, long millisecondsNeeded) {
+ public static String createLogString(EOAdaptorChannel channel, EOSQLExpression expression, long millisecondsNeeded) {
String entityName = (expression.entity() != null ? expression.entity().name() : "Unknown");
- String description = "\"" + entityName + "\"@" + channel.adaptorContext().hashCode() + " expression took "
- + millisecondsNeeded + " ms: " + expression.statement();
- StringBuffer sb = new StringBuffer();
- NSArray variables = expression.bindVariableDictionaries();
- int cnt = variables != null ? variables.count() : 0;
- if (cnt > 0) {
- sb.append(" withBindings: ");
- for (int i = 0; i < cnt; i++) {
- NSDictionary nsdictionary = (NSDictionary) variables.objectAtIndex(i);
- Object obj = nsdictionary.valueForKey("BindVariableValue");
- String attributeName = (String) nsdictionary.valueForKey("BindVariableName");
- if (obj instanceof String) {
- obj = EOSQLExpression.sqlStringForString((String) obj);
- } else if (obj instanceof NSData) {
- // ak: this is just for logging, however we would
- // like to get readable data
- // in particular for PKs and with postgres this
- // works.
- // plain EOF is broken, though
- try {
- if (((NSData) obj).length() < 50) {
- obj = expression.sqlStringForData((NSData) obj);
- }
- } catch (ArrayIndexOutOfBoundsException ex) {
- // ignore, this is a bug in EOF
- }
- if (obj instanceof NSData) {
- // produces very yucky output
- obj = obj.toString();
- }
- } else {
- if (expression.entity() != null) {
- EOAttribute attribute = expression.entity().anyAttributeNamed(attributeName);
- if (attribute != null) {
- obj = expression.formatValueForAttribute(obj, attribute);
- }
- }
- }
- if (i != 0)
- sb.append(", ");
- sb.append(i + 1);
- sb.append(":");
- sb.append(obj);
- sb.append("[");
- sb.append(attributeName);
- sb.append("]");
- }
- }
- description = description + sb.toString();
-
- return description;
- }
-
-
+ String description = "\"" + entityName + "\"@" + channel.adaptorContext().hashCode() + " expression took "
+ + millisecondsNeeded + " ms: " + expression.statement();
+ StringBuffer sb = new StringBuffer();
+ NSArray variables = expression.bindVariableDictionaries();
+ int cnt = variables != null ? variables.count() : 0;
+ if (cnt > 0) {
+ sb.append(" withBindings: ");
+ for (int i = 0; i < cnt; i++) {
+ NSDictionary nsdictionary = (NSDictionary) variables.objectAtIndex(i);
+ Object obj = nsdictionary.valueForKey("BindVariableValue");
+ String attributeName = (String) nsdictionary.valueForKey("BindVariableName");
+ if (obj instanceof String) {
+ obj = EOSQLExpression.sqlStringForString((String) obj);
+ } else if (obj instanceof NSData) {
+ // ak: this is just for logging, however we would
+ // like to get readable data
+ // in particular for PKs and with postgres this
+ // works.
+ // plain EOF is broken, though
+ try {
+ if (((NSData) obj).length() < 50) {
+ obj = expression.sqlStringForData((NSData) obj);
+ }
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ // ignore, this is a bug in EOF
+ }
+ if (obj instanceof NSData) {
+ // produces very yucky output
+ obj = obj.toString();
+ }
+ } else {
+ if (expression.entity() != null) {
+ EOAttribute attribute = expression.entity().anyAttributeNamed(attributeName);
+ if (attribute != null) {
+ obj = expression.formatValueForAttribute(obj, attribute);
+ }
+ }
+ }
+ if (i != 0)
+ sb.append(", ");
+ sb.append(i + 1);
+ sb.append(":");
+ sb.append(obj);
+ sb.append("[");
+ sb.append(attributeName);
+ sb.append("]");
+ }
+ }
+ description = description + sb.toString();
+
+ return description;
+ }
+
+
/**
* Creates an AND qualifier of EOKeyValueQualifiers for every keypath in the given array of attributes.
* @param keys
@@ -1042,7 +1042,7 @@
/**
* Filters a list of relationships for only the ones that
- * have a given EOAttribute as a source attribute.
+ * have a given EOAttribute as a source attribute.
* @param attrib EOAttribute to filter source attributes of
* relationships.
* @param rels array of EORelationship objects.
@@ -1111,7 +1111,7 @@
EOEditingContext ec = eo.editingContext();
NSArray keys = changedValues.allKeys();
NSMutableSet relationships = new NSMutableSet();
-
+
for (int i=0; i<keys.count(); i++) {
String key = (String)keys.objectAtIndex(i);
EOAttribute attrib = entity.attributeNamed(key);
@@ -1147,10 +1147,10 @@
}
}
}
-
+
/**
* Deals with the nitty-gritty of direct row manipulation by
- * correctly opening, closing, locking and unlocking the
+ * correctly opening, closing, locking and unlocking the
* needed EOF objects for direct row manipulation. Wraps the
* actions in a transaction.
* The API is not really finalized, if someone has a better idea
@@ -1158,7 +1158,7 @@
* @author ak
*/
public static abstract class ChannelAction {
-
+
protected abstract int doPerform(EOAdaptorChannel channel);
public int perform(EOEditingContext ec, String modelName) {
@@ -1182,7 +1182,7 @@
} catch(RuntimeException ex) {
channel.adaptorContext().rollbackTransaction();
throw ex;
- }
+ }
} finally {
if(!wasOpen) {
channel.closeChannel();
@@ -1197,15 +1197,15 @@
}
/**
- * Deletes rows described by the qualifier. Note that the values and the qualifier need to be on an attribute
- * and not on a relationship level. I.e. you need to give relationshipForeignKey = pk of object instead of
+ * Deletes rows described by the qualifier. Note that the values and the qualifier need to be on an attribute
+ * and not on a relationship level. I.e. you need to give relationshipForeignKey = pk of object instead of
* relatedObject = object
* @param ec
* @param entityName
* @param qualifier
* @return
*/
- public static int deleteRowsDescribedByQualifier(EOEditingContext ec, String entityName,
+ public static int deleteRowsDescribedByQualifier(EOEditingContext ec, String entityName,
final EOQualifier qualifier) {
final EOEntity entity = entityNamed(ec, entityName);
ChannelAction action = new ChannelAction() {
@@ -1217,8 +1217,8 @@
}
/**
- * Updates rows described by the qualifier. Note that the values and the qualifier need to be on an attribute
- * and not on a relationship level. I.e. you need to give relationshipForeignKey = pk of object instead of
+ * Updates rows described by the qualifier. Note that the values and the qualifier need to be on an attribute
+ * and not on a relationship level. I.e. you need to give relationshipForeignKey = pk of object instead of
* relatedObject = object. The newValues dictionaries also holds foreign keys, not objects.
* @param ec
* @param entityName
@@ -1226,7 +1226,7 @@
* @param newValues
* @return
*/
- public static int updateRowsDescribedByQualifier(EOEditingContext ec, String entityName,
+ public static int updateRowsDescribedByQualifier(EOEditingContext ec, String entityName,
final EOQualifier qualifier, final NSDictionary newValues) {
final EOEntity entity = entityNamed(ec, entityName);
ChannelAction action = new ChannelAction() {
@@ -1236,7 +1236,7 @@
};
return action.perform(ec, entity.model().name());
}
-
+
/**
* Tries to get the plugin name for a JDBC based model.
* @param model
@@ -1251,43 +1251,43 @@
if ("JDBC".equals(model.adaptorName())) {
NSDictionary connectionDictionary = model.connectionDictionary();
if (connectionDictionary != null) {
- pluginName = guessPluginNameForConnectionDictionary(connectionDictionary);
+ pluginName = guessPluginNameForConnectionDictionary(connectionDictionary);
}
}
return pluginName;
}
-
+
/**
* Tries to get the plugin name for a connection dictionary.
* @param connectionDictionary the connectionDictionary to guess a plugin name for
* @return the plugin name
*/
public static String guessPluginNameForConnectionDictionary(NSDictionary connectionDictionary) {
- String pluginName = null;
- String jdbcUrl = (String) connectionDictionary.objectForKey("URL");
- if (jdbcUrl != null) {
- pluginName = (String) connectionDictionary.objectForKey("plugin");
- if (pluginName == null || pluginName.trim().length() == 0) {
- pluginName = JDBCPlugIn.plugInNameForURL(jdbcUrl);
- if (pluginName == null) {
- // AK: this is a hack that is totally bogus....
- int firstColon = jdbcUrl.indexOf(':');
- int secondColon = jdbcUrl.indexOf(':', firstColon + 1);
- if (firstColon != -1 && secondColon != -1) {
- pluginName = jdbcUrl.substring(firstColon + 1, secondColon);
- }
- } else {
- pluginName = ERXStringUtilities.lastPropertyKeyInKeyPath(pluginName);
- pluginName = pluginName.replaceFirst("PlugIn", "");
- }
- }
- }
+ String pluginName = null;
+ String jdbcUrl = (String) connectionDictionary.objectForKey("URL");
+ if (jdbcUrl != null) {
+ pluginName = (String) connectionDictionary.objectForKey("plugin");
+ if (pluginName == null || pluginName.trim().length() == 0) {
+ pluginName = JDBCPlugIn.plugInNameForURL(jdbcUrl);
+ if (pluginName == null) {
+ // AK: this is a hack that is totally bogus....
+ int firstColon = jdbcUrl.indexOf(':');
+ int secondColon = jdbcUrl.indexOf(':', firstColon + 1);
+ if (firstColon != -1 && secondColon != -1) {
+ pluginName = jdbcUrl.substring(firstColon + 1, secondColon);
+ }
+ } else {
+ pluginName = ERXStringUtilities.lastPropertyKeyInKeyPath(pluginName);
+ pluginName = pluginName.replaceFirst("PlugIn", "");
+ }
+ }
+ }
if (pluginName != null && pluginName.trim().length() == 0) {
pluginName = null;
}
return pluginName;
}
-
+
/**
* Returns a new fetch spec by morphing sort oderings containing the keys <code>foo.name</code>
* returning <code>foo.name_de</code> where appropriate.
@@ -1304,7 +1304,7 @@
String key = item.key();
NSArray path = NSArray.componentsSeparatedByString(key, ".");
if(path.count() > 1) {
- String prefix = "";
+ String prefix = "";
String attributeName = (String) path.lastObject();
EOEntity entity = ERXEOAccessUtilities.entityNamed(ec, fetchSpecification.entityName());
for (int i = 0; i < path.count() - 1; i++) {
@@ -1314,12 +1314,12 @@
prefix += part + ".";
}
if(entity.attributeNamed(attributeName) == null) {
- EOClassDescription cd = entity.classDescriptionForInstances();
+ EOClassDescription cd = entity.classDescriptionForInstances();
if(cd instanceof ERXEntityClassDescription) {
- String localizedKey = ((ERXEntityClassDescription)cd).localizedKey(attributeName);
- if(localizedKey != null) {
+ String localizedKey = ((ERXEntityClassDescription)cd).localizedKey(attributeName);
+ if(localizedKey != null) {
item = new EOSortOrdering(prefix + localizedKey, item.selector());
- }
+ }
}
}
}
@@ -1329,10 +1329,10 @@
}
return fetchSpecification;
}
-
+
/**
* Batch fetch a relationship, optionally skipping any relationship that has already faulted in its to-many relationship.
- *
+ *
* @param databaseContext the database context to fetch in
* @param entityName the name of the entity to fetch on
* @param relationshipName the name of the relationship in that entity to fetch
@@ -1341,14 +1341,14 @@
* @param skipFaultedRelationships if true, skip any object whose relationship has already been faulted
*/
public static void batchFetchRelationship(EODatabaseContext databaseContext, String entityName, String relationshipName, NSArray objects, EOEditingContext editingContext, boolean skipFaultedRelationships) {
- EOEntity entity = EOModelGroup.defaultGroup().entityNamed(entityName);
- EORelationship relationship = entity.relationshipNamed(relationshipName);
- ERXEOAccessUtilities.batchFetchRelationship(databaseContext, relationship, objects, editingContext, skipFaultedRelationships);
+ EOEntity entity = EOModelGroup.defaultGroup().entityNamed(entityName);
+ EORelationship relationship = entity.relationshipNamed(relationshipName);
+ ERXEOAccessUtilities.batchFetchRelationship(databaseContext, relationship, objects, editingContext, skipFaultedRelationships);
}
-
+
/**
* Batch fetch a relationship, optionally skipping any relationship that has already faulted in its to-many relationship.
- *
+ *
* @param databaseContext the database context to fetch in
* @param relationship the relationship to fetch
* @param objects the objects to fetch the relationship on
@@ -1356,150 +1356,248 @@
* @param skipFaultedRelationships if true, skip any object whose relationship has already been faulted
*/
public static void batchFetchRelationship(EODatabaseContext databaseContext, EORelationship relationship, NSArray objects, EOEditingContext editingContext, boolean skipFaultedRelationships) {
- NSArray objectsToBatchFetch;
- if (skipFaultedRelationships && relationship.isToMany()) {
- NSMutableArray objectsWithUnfaultedRelationships = new NSMutableArray();
- String relationshipName = relationship.name();
- Enumeration objectsEnum = objects.objectEnumerator();
- while (objectsEnum.hasMoreElements()) {
- EOEnterpriseObject object = (EOEnterpriseObject)objectsEnum.nextElement();
- Object relationshipValue = object.storedValueForKey(relationshipName);
- if (EOFaultHandler.isFault(relationshipValue)) {
- objectsWithUnfaultedRelationships.addObject(object);
- }
- }
- objectsToBatchFetch = objectsWithUnfaultedRelationships;
- }
- else {
- objectsToBatchFetch = objects;
- }
- if (objects.count() > 0) {
- databaseContext.batchFetchRelationship(relationship, objectsToBatchFetch, editingContext);
- }
+ NSArray objectsToBatchFetch;
+ if (skipFaultedRelationships && relationship.isToMany()) {
+ NSMutableArray objectsWithUnfaultedRelationships = new NSMutableArray();
+ String relationshipName = relationship.name();
+ Enumeration objectsEnum = objects.objectEnumerator();
+ while (objectsEnum.hasMoreElements()) {
+ EOEnterpriseObject object = (EOEnterpriseObject)objectsEnum.nextElement();
+ Object relationshipValue = object.storedValueForKey(relationshipName);
+ if (EOFaultHandler.isFault(relationshipValue)) {
+ objectsWithUnfaultedRelationships.addObject(object);
+ }
+ }
+ objectsToBatchFetch = objectsWithUnfaultedRelationships;
+ }
+ else {
+ objectsToBatchFetch = objects;
+ }
+ if (objects.count() > 0) {
+ databaseContext.batchFetchRelationship(relationship, objectsToBatchFetch, editingContext);
+ }
+ }
+
+ /**
+ * In a multi-OSC or multi-instance scenario, when there are bugs, it is possible for the snapshots to become out of
+ * sync with the database. It is useful to have some way to determine when exactly this condition occurs for writing
+ * test cases.
+ *
+ * @return a set of strings that describe the mismatches that occurred
+ */
+ public static NSSet verifyAllSnapshots() {
+ NSMutableSet mismatches = new NSMutableSet();
+ NSMutableSet verifiedDatabases = new NSMutableSet();
+ EOEditingContext editingContext = ERXEC.newEditingContext();
+ EOModelGroup modelGroup = EOModelGroup.defaultGroup();
+ Enumeration modelsEnum = modelGroup.models().objectEnumerator();
+ while (modelsEnum.hasMoreElements()) {
+ EOModel model = (EOModel) modelsEnum.nextElement();
+ EODatabaseContext databaseContext = null;
+ try {
+ databaseContext = EODatabaseContext.registeredDatabaseContextForModel(model, editingContext);
+ }
+ catch (IllegalStateException e) {
+ log.warn("Model " + model.name() + " failed: " + e.getMessage());
+ }
+ if (databaseContext != null) {
+ databaseContext.lock();
+ try {
+ EODatabase database = databaseContext.database();
+ if (!verifiedDatabases.containsObject(database)) {
+ Enumeration gidEnum = database.snapshots().keyEnumerator();
+ while (gidEnum.hasMoreElements()) {
+ EOGlobalID gid = (EOGlobalID) gidEnum.nextElement();
+ if (gid instanceof EOKeyGlobalID) {
+ EOEnterpriseObject eo = null;
+ EOKeyGlobalID keyGID = (EOKeyGlobalID) gid;
+ String entityName = keyGID.entityName();
+ EOEntity entity = modelGroup.entityNamed(entityName);
+ NSDictionary snapshot = database.snapshotForGlobalID(gid);
+ if (snapshot != null) {
+ EOQualifier gidQualifier = entity.qualifierForPrimaryKey(entity.primaryKeyForGlobalID(gid));
+ EOFetchSpecification gidFetchSpec = new EOFetchSpecification(entityName, gidQualifier, null);
+
+ NSMutableDictionary databaseSnapshotClone;
+ NSMutableDictionary memorySnapshotClone = snapshot.mutableClone();
+ EOAdaptorContext context;
+ EOAdaptorChannel channel = databaseContext.availableChannel().adaptorChannel();
+ channel.openChannel();
+ channel.selectAttributes(entity.attributesToFetch(), gidFetchSpec, false, entity);
+ NSDictionary nextRow;
+ try {
+ databaseSnapshotClone = channel.fetchRow().mutableClone();
+ }
+ finally {
+ channel.cancelFetch();
+ }
+ // gidFetchSpec.setRefreshesRefetchedObjects(true);
+ // NSArray databaseEOs = editingContext.objectsWithFetchSpecification(gidFetchSpec);
+ if (databaseSnapshotClone == null) {
+ mismatches.addObject(gid + " was deleted in the database, but the snapshot still exists: " + memorySnapshotClone);
+ }
+ else {
+ // NSMutableDictionary refreshedSnapshotClone =
+ // database.snapshotForGlobalID(gid).mutableClone();
+ ERXDictionaryUtilities.removeMatchingEntries(memorySnapshotClone, databaseSnapshotClone);
+ if (databaseSnapshotClone.count() > 0 || memorySnapshotClone.count() > 0) {
+ mismatches.addObject(gid + " doesn't match the database: original = " + memorySnapshotClone + "; database = " + databaseSnapshotClone);
+ }
+ eo = (EOEnterpriseObject) editingContext.objectsWithFetchSpecification(gidFetchSpec).objectAtIndex(0);
+ }
+ }
+
+ if (eo != null) {
+ Enumeration relationshipsEnum = entity.relationships().objectEnumerator();
+ while (relationshipsEnum.hasMoreElements()) {
+ EORelationship relationship = (EORelationship) relationshipsEnum.nextElement();
+ String relationshipName = relationship.name();
+ NSArray originalDestinationGIDs = database.snapshotForSourceGlobalID(keyGID, relationshipName);
+ if (originalDestinationGIDs != null) {
+ NSMutableArray newDestinationGIDs = new NSMutableArray();
+ EOQualifier qualifier = relationship.qualifierWithSourceRow(database.snapshotForGlobalID(keyGID));
+ EOFetchSpecification relationshipFetchSpec = new EOFetchSpecification(entityName, qualifier, null);
+ EOAdaptorChannel channel = databaseContext.availableChannel().adaptorChannel();
+ channel.openChannel();
+ try {
+ channel.selectAttributes(relationship.destinationEntity().attributesToFetch(), relationshipFetchSpec, false, relationship.destinationEntity());
+ NSDictionary nextRow;
+ NSDictionary destinationSnapshot = null;
+ do {
+ destinationSnapshot = channel.fetchRow();
+ if (destinationSnapshot != null) {
+ EOGlobalID destinationGID = relationship.destinationEntity().globalIDForRow(destinationSnapshot);
+ newDestinationGIDs.addObject(destinationGID);
+ }
+ else {
+ destinationSnapshot = null;
+ }
+ }
+ while (destinationSnapshot != null);
+ }
+ finally {
+ channel.cancelFetch();
+ }
+
+ NSArray objectsNotInDatabase = ERXArrayUtilities.arrayMinusArray(originalDestinationGIDs, newDestinationGIDs);
+ if (objectsNotInDatabase.count() > 0) {
+ mismatches.addObject(gid + "." + relationshipName + " has entries not in the database: " + objectsNotInDatabase);
+ }
+ NSArray objectsNotInMemory = ERXArrayUtilities.arrayMinusArray(newDestinationGIDs, originalDestinationGIDs);
+ if (objectsNotInMemory.count() > 0) {
+ mismatches.addObject(gid + "." + relationshipName + " is missing entries in the database: " + objectsNotInMemory);
+ }
+ }
+ }
+ }
+ }
+ }
+ verifiedDatabases.addObject(database);
+ }
+ }
+ finally {
+ databaseContext.unlock();
+ }
+ }
+ }
+ return mismatches;
}
-
- /**
- * In a multi-OSC or multi-instance scenario, when there are bugs, it is possible for the snapshots to become out of
- * sync with the database. It is useful to have some way to determine when exactly this condition occurs for writing
- * test cases.
- *
- * @return a set of strings that describe the mismatches that occurred
- */
- public static NSSet verifyAllSnapshots() {
- NSMutableSet mismatches = new NSMutableSet();
- NSMutableSet verifiedDatabases = new NSMutableSet();
- EOEditingContext editingContext = ERXEC.newEditingContext();
- EOModelGroup modelGroup = EOModelGroup.defaultGroup();
- Enumeration modelsEnum = modelGroup.models().objectEnumerator();
- while (modelsEnum.hasMoreElements()) {
- EOModel model = (EOModel) modelsEnum.nextElement();
- EODatabaseContext databaseContext = null;
- try {
- databaseContext = EODatabaseContext.registeredDatabaseContextForModel(model, editingContext);
- }
- catch (IllegalStateException e) {
- log.warn("Model " + model.name() + " failed: " + e.getMessage());
- }
- if (databaseContext != null) {
- databaseContext.lock();
- try {
- EODatabase database = databaseContext.database();
- if (!verifiedDatabases.containsObject(database)) {
- Enumeration gidEnum = database.snapshots().keyEnumerator();
- while (gidEnum.hasMoreElements()) {
- EOGlobalID gid = (EOGlobalID) gidEnum.nextElement();
- if (gid instanceof EOKeyGlobalID) {
- EOEnterpriseObject eo = null;
- EOKeyGlobalID keyGID = (EOKeyGlobalID) gid;
- String entityName = keyGID.entityName();
- EOEntity entity = modelGroup.entityNamed(entityName);
- NSDictionary snapshot = database.snapshotForGlobalID(gid);
- if (snapshot != null) {
- EOQualifier gidQualifier = entity.qualifierForPrimaryKey(entity.primaryKeyForGlobalID(gid));
- EOFetchSpecification gidFetchSpec = new EOFetchSpecification(entityName, gidQualifier, null);
-
- NSMutableDictionary databaseSnapshotClone;
- NSMutableDictionary memorySnapshotClone = snapshot.mutableClone();
- EOAdaptorContext context;
- EOAdaptorChannel channel = databaseContext.availableChannel().adaptorChannel();
- channel.openChannel();
- channel.selectAttributes(entity.attributesToFetch(), gidFetchSpec, false, entity);
- NSDictionary nextRow;
- try {
- databaseSnapshotClone = channel.fetchRow().mutableClone();
- }
- finally {
- channel.cancelFetch();
- }
- // gidFetchSpec.setRefreshesRefetchedObjects(true);
- // NSArray databaseEOs = editingContext.objectsWithFetchSpecification(gidFetchSpec);
- if (databaseSnapshotClone == null) {
- mismatches.addObject(gid + " was deleted in the database, but the snapshot still exists: " + memorySnapshotClone);
- }
- else {
- // NSMutableDictionary refreshedSnapshotClone =
- // database.snapshotForGlobalID(gid).mutableClone();
- ERXDictionaryUtilities.removeMatchingEntries(memorySnapshotClone, databaseSnapshotClone);
- if (databaseSnapshotClone.count() > 0 || memorySnapshotClone.count() > 0) {
- mismatches.addObject(gid + " doesn't match the database: original = " + memorySnapshotClone + "; database = " + databaseSnapshotClone);
- }
- eo = (EOEnterpriseObject) editingContext.objectsWithFetchSpecification(gidFetchSpec).objectAtIndex(0);
- }
- }
-
- if (eo != null) {
- Enumeration relationshipsEnum = entity.relationships().objectEnumerator();
- while (relationshipsEnum.hasMoreElements()) {
- EORelationship relationship = (EORelationship) relationshipsEnum.nextElement();
- String relationshipName = relationship.name();
- NSArray originalDestinationGIDs = database.snapshotForSourceGlobalID(keyGID, relationshipName);
- if (originalDestinationGIDs != null) {
- NSMutableArray newDestinationGIDs = new NSMutableArray();
- EOQualifier qualifier = relationship.qualifierWithSourceRow(database.snapshotForGlobalID(keyGID));
- EOFetchSpecification relationshipFetchSpec = new EOFetchSpecification(entityName, qualifier, null);
- EOAdaptorChannel channel = databaseContext.availableChannel().adaptorChannel();
- channel.openChannel();
- try {
- channel.selectAttributes(relationship.destinationEntity().attributesToFetch(), relationshipFetchSpec, false, relationship.destinationEntity());
- NSDictionary nextRow;
- NSDictionary destinationSnapshot = null;
- do {
- destinationSnapshot = channel.fetchRow();
- if (destinationSnapshot != null) {
- EOGlobalID destinationGID = relationship.destinationEntity().globalIDForRow(destinationSnapshot);
- newDestinationGIDs.addObject(destinationGID);
- }
- else {
- destinationSnapshot = null;
- }
- }
- while (destinationSnapshot != null);
- }
- finally {
- channel.cancelFetch();
- }
-
- NSArray objectsNotInDatabase = ERXArrayUtilities.arrayMinusArray(originalDestinationGIDs, newDestinationGIDs);
- if (objectsNotInDatabase.count() > 0) {
- mismatches.addObject(gid + "." + relationshipName + " has entries not in the database: " + objectsNotInDatabase);
- }
- NSArray objectsNotInMemory = ERXArrayUtilities.arrayMinusArray(newDestinationGIDs, originalDestinationGIDs);
- if (objectsNotInMemory.count() > 0) {
- mismatches.addObject(gid + "." + relationshipName + " is missing entries in the database: " + objectsNotInMemory);
- }
- }
- }
- }
- }
- }
- verifiedDatabases.addObject(database);
- }
- }
- finally {
- databaseContext.unlock();
- }
- }
- }
- return mismatches;
- }
-}
\ No newline at end of file
+
+ /**
+ * @param ec an EOEditingContext
+ * @param count the number of primary keys you want EOF to generate
+ * @param entityName the Entity for whom the primary keys are generated
+ * @return the array of primary keys generated by the EOAdaptorChannel
+ * @see com.webobjects.eoaccess.EOAdaptorChannel#primaryKeysForNewRowsWithEntity(int, EOEntity)
+ * @author kieran
+ */
+ public static NSArray primaryKeysForNewRowsWithEntity(EOEditingContext ec, int count, String entityName) {
+ EOEntity entity = entityNamed(ec, entityName);
+ String modelName = entity.model().name();
+ NSArray primaryKeysArray = null;
+
+ boolean wasOpen = true;
+ EOAdaptorChannel channel = null;
+ int rows = 0;
+ ec.lock();
+ try {
+ EODatabaseContext dbc = EOUtilities.databaseContextForModelNamed(ec, modelName);
+ dbc.lock();
+ try {
+ channel = dbc.availableChannel().adaptorChannel();
+ wasOpen = channel.isOpen();
+ if(!wasOpen) {
+ channel.openChannel();
+ }
+ channel.adaptorContext().beginTransaction();
+ try {
+ primaryKeysArray = channel.primaryKeysForNewRowsWithEntity(count, entity);
+ channel.adaptorContext().commitTransaction();
+ } catch(RuntimeException ex) {
+ channel.adaptorContext().rollbackTransaction();
+ throw ex;
+ }
+ } finally {
+ if(!wasOpen) {
+ channel.closeChannel();
+ }
+ dbc.unlock();
+ }
+ } finally {
+ ec.unlock();
+ }
+ return primaryKeysArray;
+ }
+
+ /**
+ * Inserts a raw row. You are responsible to ensure it has a new valid primary key
+ * and that the dictionary contains valid attribute keys and valid values.
+ * There is no editing context or validation going on here.
+ * This is suitable only for massive bulk inserts where regular convenient EOF
+ * creation and saving in editing contexts does not meet the performance requirements.
+ * This should only be used where profiling shows that you need to go to this extreme.
+ * @see EOAdaptorChannel#insertRow(NSDictionary, EOEntity)
+ * @param ec
+ * @param rawRow
+ * @param entityName
+ * @return 1
+ * @author kieran
+ */
+ public static int insertRawRowForEntity(EOEditingContext ec, NSDictionary rawRow, String entityName){
+ EOEntity entity = entityNamed(ec, entityName);
+ String modelName = entity.model().name();
+
+ boolean wasOpen = true;
+ EOAdaptorChannel channel = null;
+ int rows = 0;
+ ec.lock();
+ try {
+ EODatabaseContext dbc = EOUtilities.databaseContextForModelNamed(ec, modelName);
+ dbc.lock();
+ try {
+ channel = dbc.availableChannel().adaptorChannel();
+ wasOpen = channel.isOpen();
+ if(!wasOpen) {
+ channel.openChannel();
+ }
+ channel.adaptorContext().beginTransaction();
+ try {
+ channel.insertRow(rawRow, entity);
+ channel.adaptorContext().commitTransaction();
+ } catch(RuntimeException ex) {
+ channel.adaptorContext().rollbackTransaction();
+ throw ex;
+ }
+ } finally {
+ if(!wasOpen) {
+ channel.closeChannel();
+ }
+ dbc.unlock();
+ }
+ } finally {
+ ec.unlock();
+ }
+ // TODO : The JDBCChannel concrete subclass has a rowsProcessedCount, so perhaps use that
+ return 1;
+ }
+}
On Dec 19, 2007, at 2:20 PM, Mike Schrag wrote:
HTH, Kieran
*cough*submittoWonder*cough*
ms
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Webobjects-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden