// [PJYF Nov 5 2004] // This is major Hack to generate a diffenrent bind dictionary for update and insert form the // one for select and delete public void addUpdateListAttribute(EOAttribute attribute, Object value) { String attributeName = this.sqlStringForAttribute(attribute); String attributeValue = this.sqlStringForForInsertOrUpdateValue(value, attribute.name()); attributeValue = this.formatSQLString(attributeValue, attribute.writeFormat()); this.appendItemToListString( _NSStringUtilities.concat(attributeName, " = ", attributeValue), this._listString()); }
/* * [PJYF Oct 19 2004] * This is a bad hack to get WO to create indes for external keys. * We use the primary key constrain generation to create our indexes. * But we need to be carefull not to overwrite previous constrains * */ protected boolean isSinglePrimaryKeyAttribute(EOAttribute attribute) { if (attribute == null) return false; EOEntity entity = (EOEntity) attribute.entity(); if ((entity == null) || entity.isAbstractEntity() || (entity.externalName() == null)) return false; NSArray primaryKeyAttributes = entity.primaryKeyAttributes(); if (primaryKeyAttributes.count() != 1) return false; return attribute.name().equals(((EOAttribute) primaryKeyAttributes.lastObject()).name()); }
/** * 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; }
// [PJYF Oct 19 2004] // We need to prepend the question mark with a type attribute to get the jdbc driver to do the // right thing. // only for B (Binary) public NSMutableDictionary bindVariableDictionaryForAttribute( EOAttribute attribute, Object value) { String prepend = ""; String externalType = (attribute.externalType() != null ? attribute.externalType().toLowerCase() : ""); if ("binary".equals(externalType)) { prepend = "B"; } return new NSMutableDictionary( new Object[] {attribute.name(), prepend + "?", attribute, value}, new Object[] { BindVariableNameKey, BindVariablePlaceHolderKey, BindVariableAttributeKey, BindVariableValueKey }); }
// Shameless stolen from PostresqlSynchronizationFactory - davidleber // // I blame statementstToConvertColumnType for not taking a damn EOAttribute for // having to steal this from EOSQLExpression public String columnTypeStringForAttribute(EOAttribute attribute) { if (attribute.precision() != 0) { String precision = String.valueOf(attribute.precision()); String scale = String.valueOf(attribute.scale()); return _NSStringUtilities.concat(attribute.externalType(), "(", precision, ",", scale, ")"); } if (attribute.width() != 0) { String width = String.valueOf(attribute.width()); return _NSStringUtilities.concat(attribute.externalType(), "(", width, ")"); } return attribute.externalType(); }
/** * Generates an NSDictionary representing primary key values, both simple and compound. If values * are encrypted we try to create the correct attribute value type. Supported types are: strings, * numbers, timestamps and custom attributes with a factory method using a string argument. * * @param value the primary key value, either a single value or a collection * @param entity the entity used to gather primary key information * @param isEncrypted yes/no * @return a dictionary with primary key values */ private static NSDictionary processPrimaryKeyValue( String value, EOEntity entity, boolean isEncrypted) { NSArray pkAttributeNames = entity.primaryKeyAttributeNames(); try { pkAttributeNames = pkAttributeNames.sortedArrayUsingComparator(NSComparator.AscendingStringComparator); } catch (NSComparator.ComparisonException ex) { log.error("Unable to sort attribute names: " + ex); throw new NSForwardException(ex); } NSArray values = isEncrypted ? NSArray.componentsSeparatedByString( ERXCrypto.blowfishDecode(value).trim(), AttributeValueSeparator) : NSArray.componentsSeparatedByString(value, AttributeValueSeparator); int attrCount = pkAttributeNames.count(); NSMutableDictionary result = new NSMutableDictionary(attrCount); for (int i = 0; i < attrCount; i++) { String currentAttributeName = (String) pkAttributeNames.objectAtIndex(i); EOAttribute currentAttribute = entity.attributeNamed(currentAttributeName); Object currentValue = values.objectAtIndex(i); switch (currentAttribute.adaptorValueType()) { case 3: NSTimestampFormatter tsf = new NSTimestampFormatter(); try { currentValue = tsf.parseObject((String) currentValue); } catch (java.text.ParseException ex) { log.error("Error while trying to parse: " + currentValue); throw new NSForwardException(ex); } case 1: if (currentAttribute.valueFactoryMethodName() != null) { currentValue = currentAttribute.newValueForString((String) currentValue); } case 0: currentValue = new java.math.BigDecimal((String) currentValue); } result.setObjectForKey(currentValue, currentAttributeName); } return result; }
@Override public NSArray<EOSQLExpression> statementsToRenameColumnNamed( String columnName, String tableName, String newName, EOSchemaGenerationOptions options) { EOAttribute attribute = attributeInEntityWithColumnName(entityForTableName(tableName), newName); String nullStatement = attribute.allowsNull() ? " NULL" : " NOT NULL"; String externalType = columnTypeStringForAttribute(attribute); return new NSArray<EOSQLExpression>( _expressionForString( (new StringBuilder()) .append("ALTER TABLE ") .append(formatTableName(tableName)) .append(" CHANGE ") .append(formatColumnName(columnName)) .append(" ") .append(formatColumnName(newName)) .append(" ") .append(externalType) .append(nullStatement) .toString())); }
@Override public NSArray<EOSQLExpression> statementsToInsertColumnForAttribute( EOAttribute attribute, EOSchemaGenerationOptions options) { String columnCreationClause = _columnCreationClauseForAttribute(attribute); return new NSArray<EOSQLExpression>( _expressionForString( (new StringBuilder()) .append("ALTER TABLE ") .append(attribute.entity().externalName()) .append(_alterPhraseInsertionClausePrefixAtIndex(0)) .append(columnCreationClause) .toString())); }
public EOSchemaSynchronizationColumnChanges objectStoreChangesFromAttributeToAttribute( EOAttribute schemaAttribute, EOAttribute modelAttribute) { EOSchemaSynchronizationColumnChanges objectStoreChanges = super.objectStoreChangesFromAttributeToAttribute(schemaAttribute, modelAttribute); if (objectStoreChanges.valueForKey("precision") != null || objectStoreChanges.valueForKey("scale") != null) { objectStoreChanges.clearPrecision(); objectStoreChanges.clearScale(); } if (!modelAttribute.externalType().equals(schemaAttribute.externalType())) { if (modelAttribute.externalType().equals("varchar") && schemaAttribute.externalType().equals("char")) objectStoreChanges.clearExternalType(); } else { if (schemaAttribute.externalType().equals("object") && objectStoreChanges.valueForKey("width") != null) objectStoreChanges.clearWidth(); } if ((modelAttribute.externalType().equals("char") || modelAttribute.externalType().equals("varchar")) && modelAttribute.width() == 1024 && schemaAttribute.width() == 1023) objectStoreChanges.clearWidth(); return objectStoreChanges; }
public NSArray primaryKeyConstraintStatementsForEntityGroup(NSArray entityGroup) { if (entityGroup == null) return NSArray.EmptyArray; NSMutableDictionary columnNameDictionary = new NSMutableDictionary(); NSMutableArray primaryKeyConstraintExpressions = new NSMutableArray(); for (Enumeration enumerator = entityGroup.objectEnumerator(); enumerator.hasMoreElements(); ) { EOEntity entity = (EOEntity) enumerator.nextElement(); String tableName = entity.externalName(); NSArray primaryKeyAttributes = entity.primaryKeyAttributes(); boolean singlePrimaryKey = primaryKeyAttributes.count() == 1; if ((tableName != null) && (!"".equals(tableName)) && (primaryKeyAttributes.count() > 0)) { NSArray expressions = super.primaryKeyConstraintStatementsForEntityGroup(entityGroup); if ((expressions != null) && (expressions.count() > 0)) primaryKeyConstraintExpressions.addObjectsFromArray(expressions); for (Enumeration attributeEnumerator = primaryKeyAttributes.objectEnumerator(); attributeEnumerator.hasMoreElements(); ) { String columnName = ((EOAttribute) attributeEnumerator.nextElement()).columnName(); columnNameDictionary.setObjectForKey( columnName, entity.externalName() + "." + columnName); EOSQLExpression expression = this._expressionForString( "create " + (singlePrimaryKey ? "unique" : "") + " index " + entity.externalName() + " " + columnName); if (expression != null) primaryKeyConstraintExpressions.addObject(expression); } } } for (Enumeration enumerator = entityGroup.objectEnumerator(); enumerator.hasMoreElements(); ) { EOEntity entity = (EOEntity) enumerator.nextElement(); String tableName = entity.externalName(); if ((tableName != null) && (!"".equals(tableName))) { for (Enumeration relationshipEnumerator = entity.relationships().objectEnumerator(); relationshipEnumerator.hasMoreElements(); ) { EORelationship relationship = (EORelationship) relationshipEnumerator.nextElement(); if (!relationship.isFlattened()) { NSArray destinationAttributes = relationship.destinationAttributes(); // First exclude all the destination entity primary keys for (Enumeration attributeEnumerator = relationship.destinationEntity().primaryKeyAttributes().objectEnumerator(); attributeEnumerator.hasMoreElements(); ) { EOAttribute attribute = (EOAttribute) attributeEnumerator.nextElement(); columnNameDictionary.setObjectForKey( attribute.columnName(), relationship.destinationEntity().externalName() + "." + attribute.columnName()); } // Then deal with our end of things for (Enumeration attributeEnumerator = relationship.sourceAttributes().objectEnumerator(); attributeEnumerator.hasMoreElements(); ) { EOAttribute attribute = (EOAttribute) attributeEnumerator.nextElement(); if ((!this.isSinglePrimaryKeyAttribute(attribute)) && (columnNameDictionary.objectForKey(tableName + "." + attribute.columnName()) != null)) { columnNameDictionary.setObjectForKey( attribute.columnName(), tableName + "." + attribute.columnName()); EOSQLExpression expression = this._expressionForString( "create index " + tableName + " " + attribute.columnName()); if (expression != null) primaryKeyConstraintExpressions.addObject(expression); } } // Then deal with the other side if (entity.model() == relationship.destinationEntity().model()) { for (Enumeration attributeEnumerator = relationship.destinationAttributes().objectEnumerator(); attributeEnumerator.hasMoreElements(); ) { EOAttribute attribute = (EOAttribute) attributeEnumerator.nextElement(); String destinationTableName = relationship.destinationEntity().externalName(); if ((destinationTableName != null) && (!"".equals(destinationTableName))) { if ((!this.isSinglePrimaryKeyAttribute(attribute)) && (columnNameDictionary.objectForKey( destinationTableName + "." + attribute.columnName()) != null)) { columnNameDictionary.setObjectForKey( attribute.columnName(), destinationTableName + "." + attribute.columnName()); EOSQLExpression expression = this._expressionForString( "create index " + destinationTableName + " " + attribute.columnName()); if (expression != null) primaryKeyConstraintExpressions.addObject(expression); } if ((!relationship.isCompound()) && (relationship.sourceAttributes().count() == 1) && (relationship.destinationAttributes().count() == 1)) { String semantics; switch (relationship.joinSemantic()) { case EORelationship.FullOuterJoin: // '\001' case EORelationship.LeftOuterJoin: // '\002' case EORelationship.RightOuterJoin: // '\003' semantics = "*"; break; default: semantics = "="; break; } String sourceColumn = ((EOAttribute) relationship.sourceAttributes().objectAtIndex(0)) .columnName(); String destinationColumn = ((EOAttribute) relationship.destinationAttributes().objectAtIndex(0)) .columnName(); EOSQLExpression expression = this._expressionForString( "delete from _SYS_RELATIONSHIP where relationshipName = '" + relationship.name() + "' and source_table = '" + tableName + "' "); if (expression != null) primaryKeyConstraintExpressions.addObject(expression); expression = this._expressionForString( "insert into _SYS_RELATIONSHIP (relationshipName, source_table, source_column, dest_table, dest_column, operator, one_to_many) values ('" + relationship.name() + "','" + tableName + "','" + sourceColumn + "','" + destinationTableName + "','" + destinationColumn + "','" + semantics + "'," + (relationship.isToMany() ? 1 : 0) + ")"); if (expression != null) primaryKeyConstraintExpressions.addObject(expression); } } } } } } } } return primaryKeyConstraintExpressions.immutableClone(); }
// [PJYF Nov 5 2004] // This is major Hack to generate a diffenrent bind dictionary for update and insert form the // one for select and delete public void addInsertListAttribute(EOAttribute attribute, Object value) { this.appendItemToListString(this.sqlStringForAttribute(attribute), this._listString()); String attributeValue = this.sqlStringForForInsertOrUpdateValue(value, attribute.name()); attributeValue = this.formatSQLString(attributeValue, attribute.writeFormat()); this.appendItemToListString(attributeValue, _valueList()); }
private AttributeRetriever(EOAttribute attribute) { this.propertyName = attribute.name(); this.attribute = attribute; }
/** * Returns an EOAttribute with all of its fields filled in based on the properties of this * ERXMigrationColumn. The attribute is attached to the given entity. * * @param entity the entity to add the attribute to * @return an EOAttribute with all of its fields filled in */ @SuppressWarnings("unchecked") public EOAttribute _newAttribute(EOEntity entity) { EOAdaptor eoAdaptor = _table.database().adaptor(); // MS: Hack to make Memory adaptor migrations "work" if (!(eoAdaptor instanceof JDBCAdaptor)) { EOAttribute nonJdbcAttribute = new EOAttribute(); nonJdbcAttribute.setName(_name); nonJdbcAttribute.setColumnName(_name); nonJdbcAttribute.setExternalType("nonJdbcAttribute"); entity.addAttribute(nonJdbcAttribute); return nonJdbcAttribute; } JDBCAdaptor adaptor = (JDBCAdaptor) _table.database().adaptor(); ERXSQLHelper sqlHelper = ERXSQLHelper.newSQLHelper(adaptor); String externalType = sqlHelper.externalTypeForJDBCType(adaptor, _jdbcType); if (externalType == null) { externalType = "IF_YOU_ARE_SEEING_THIS_SOMETHING_WENT_WRONG_WITH_EXTERNAL_TYPES"; } EOAttribute attribute = adaptor.createAttribute( _name, _name, _jdbcType, externalType, _precision, _scale, _allowsNull ? 1 : 0); if (_width > 0) { attribute.setWidth(_width); } if (_defaultValue != null) { NSDictionary userInfo = attribute.userInfo(); NSMutableDictionary mutableUserInfo; if (userInfo == null) { mutableUserInfo = new NSMutableDictionary(); } else { mutableUserInfo = userInfo.mutableClone(); } mutableUserInfo.setObjectForKey(_defaultValue, "default"); attribute.setUserInfo(mutableUserInfo); } if (_overrideValueType != null) { if (ERXMigrationColumn.NULL_VALUE_TYPE.equals(_overrideValueType)) { attribute.setValueType(null); } else { attribute.setValueType(_overrideValueType); } if (sqlHelper.reassignExternalTypeForValueTypeOverride(attribute)) { adaptor.assignExternalTypeForAttribute(attribute); } } if (_overrideExternalType != null) { attribute.setExternalType(_overrideExternalType); } entity.addAttribute(attribute); return attribute; }
@Override @SuppressWarnings("unchecked") public String sqlStringForSQLExpression(EOQualifier eoqualifier, EOSQLExpression e) { ERXToManyQualifier qualifier = (ERXToManyQualifier) eoqualifier; StringBuilder result = new StringBuilder(); EOEntity targetEntity = e.entity(); NSArray<String> toManyKeys = NSArray.componentsSeparatedByString(qualifier.key(), "."); EORelationship targetRelationship = null; for (int i = 0; i < toManyKeys.count() - 1; i++) { targetRelationship = targetEntity.anyRelationshipNamed(toManyKeys.objectAtIndex(i)); targetEntity = targetRelationship.destinationEntity(); } targetRelationship = targetEntity.relationshipNamed(toManyKeys.lastObject()); targetEntity = targetRelationship.destinationEntity(); if (targetRelationship.joins() == null || targetRelationship.joins().isEmpty()) { // we have a flattened many to many String definitionKeyPath = targetRelationship.definition(); NSArray<String> definitionKeys = NSArray.componentsSeparatedByString(definitionKeyPath, "."); EOEntity lastStopEntity = targetRelationship.entity(); EORelationship firstHopRelationship = lastStopEntity.relationshipNamed(definitionKeys.objectAtIndex(0)); EOEntity endOfFirstHopEntity = firstHopRelationship.destinationEntity(); EOJoin join = firstHopRelationship.joins().objectAtIndex(0); // assumes 1 join EOAttribute sourceAttribute = join.sourceAttribute(); EOAttribute targetAttribute = join.destinationAttribute(); EORelationship secondHopRelationship = endOfFirstHopEntity.relationshipNamed(definitionKeys.objectAtIndex(1)); join = secondHopRelationship.joins().objectAtIndex(0); // assumes 1 join EOAttribute secondHopSourceAttribute = join.sourceAttribute(); NSMutableArray<String> lastStopPKeyPath = toManyKeys.mutableClone(); lastStopPKeyPath.removeLastObject(); lastStopPKeyPath.addObject(firstHopRelationship.name()); lastStopPKeyPath.addObject(targetAttribute.name()); String firstHopRelationshipKeyPath = lastStopPKeyPath.componentsJoinedByString("."); result.append(e.sqlStringForAttributeNamed(firstHopRelationshipKeyPath)); result.append(" IN ( SELECT "); result.append(lastStopEntity.externalName()); result.append('.'); result.append(lastStopEntity.primaryKeyAttributes().objectAtIndex(0).columnName()); result.append(" FROM "); result.append(lastStopEntity.externalName()); result.append(','); lastStopPKeyPath.removeLastObject(); String tableAliasForJoinTable = (String) e.aliasesByRelationshipPath() .objectForKey( lastStopPKeyPath.componentsJoinedByString(".")); // "j"; //+random# result.append(endOfFirstHopEntity.externalName()); result.append(' '); result.append(tableAliasForJoinTable); result.append(" WHERE "); appendColumnForAttributeToStringBuilder(sourceAttribute, result); result.append('='); result.append(e.sqlStringForAttributeNamed(firstHopRelationshipKeyPath)); if (qualifier.elements() != null) { NSArray pKeys = ERXEOAccessUtilities.primaryKeysForObjects(qualifier.elements()); result.append(" AND "); result.append(tableAliasForJoinTable); result.append('.'); result.append(secondHopSourceAttribute.columnName()); result.append(" IN ("); EOAttribute pk = targetEntity.primaryKeyAttributes().lastObject(); for (int i = 0; i < pKeys.count(); i++) { Object key = pKeys.objectAtIndex(i); String keyString = e.formatValueForAttribute(key, pk); // AK: default is is broken if ("NULL".equals(keyString)) { keyString = "" + key; } result.append(keyString); if (i < pKeys.count() - 1) { result.append(','); } } result.append(") "); } result.append(" GROUP BY "); appendColumnForAttributeToStringBuilder(sourceAttribute, result); result.append(" HAVING COUNT(*)"); if (qualifier.minCount() <= 0) { result.append("=" + qualifier.elements().count()); } else { result.append(">=" + qualifier.minCount()); } result.append(" )"); } else { throw new RuntimeException("not implemented!!"); } return result.toString(); }
protected static void appendColumnForAttributeToStringBuilder( EOAttribute attribute, StringBuilder sb) { sb.append(attribute.entity().externalName()); sb.append('.'); sb.append(attribute.columnName()); }