/** * Overrides the parent implementation to provide a more efficient mechanism for generating * primary keys, while generating the primary key support on the fly. * * @param count the batch size * @param entity the entity requesting primary keys * @param channel open JDBCChannel * @return NSArray of NSDictionary where each dictionary corresponds to a unique primary key value */ public NSArray newPrimaryKeys(int count, EOEntity entity, JDBCChannel channel) { if (isPrimaryKeyGenerationNotSupported(entity)) { return null; } EOAttribute attribute = (EOAttribute) entity.primaryKeyAttributes().lastObject(); String attrName = attribute.name(); boolean isIntType = "i".equals(attribute.valueType()); NSMutableArray results = new NSMutableArray(count); String sequenceName = sequenceNameForEntity(entity); DB2Expression expression = new DB2Expression(entity); boolean succeeded = false; for (int tries = 0; !succeeded && tries < 2; tries++) { while (results.count() < count) { try { StringBuffer sql = new StringBuffer(); sql.append("SELECT "); sql.append("next value for " + sequenceName + " AS KEY"); sql.append(" from sysibm.sysdummy1"); expression.setStatement(sql.toString()); channel.evaluateExpression(expression); try { NSDictionary row; while ((row = channel.fetchRow()) != null) { Enumeration pksEnum = row.allValues().objectEnumerator(); while (pksEnum.hasMoreElements()) { Number pkObj = (Number) pksEnum.nextElement(); Number pk; if (isIntType) { pk = Integer.valueOf(pkObj.intValue()); } else { pk = Long.valueOf(pkObj.longValue()); } results.addObject(new NSDictionary(pk, attrName)); } } } finally { channel.cancelFetch(); } succeeded = true; } catch (JDBCAdaptorException ex) { throw ex; } } } if (results.count() != count) { throw new IllegalStateException( "Unable to generate primary keys from the sequence for " + entity + "."); } return results; }
// ENHANCEME: Could also place a sha hash of the blowfish key in the form values so we can know if // we are using // the correct key for decryption. public static String encodeEnterpriseObjectsPrimaryKeyForUrl( NSArray eos, String separator, boolean encrypt) { // Array of objects to be encoded NSMutableArray encoded = new NSMutableArray(); // If the separator is not specified, default to the one given at class init if (separator == null) separator = entityNameSeparator(); // Add the separator if needed if (isSpecifySeparatorInURL()) encoded.addObject("sep=" + separator); int c = 1; // Iterate through the objects for (Enumeration e = eos.objectEnumerator(); e.hasMoreElements(); ) { EOEnterpriseObject eo = (EOEnterpriseObject) e.nextElement(); // Get the primary key of the object NSArray pkValues = ERXEOControlUtilities.primaryKeyArrayForObject(eo); if (pkValues == null && eo instanceof ERXGeneratesPrimaryKeyInterface) { NSDictionary pkDict = ((ERXGeneratesPrimaryKeyInterface) eo).primaryKeyDictionary(false); if (pkDict != null) pkValues = pkDict.allValues(); } if (pkValues == null) throw new RuntimeException("Primary key is null for object: " + eo); String pk = pkValues.componentsJoinedByString(AttributeValueSeparator); // Get the EncodedEntityName of the object String encodedEntityName = entityNameEncode(eo); // Add the result to the list of encoded objects encoded.addObject( encodedEntityName + separator + (encrypt ? "E" : "") + c++ + "=" + (encrypt ? ERXCrypto.blowfishEncode(pk) : pk)); } // Return the result as an url-encoded string return encoded.componentsJoinedByString("&"); }