/** * Generates the sql string for the given sql expression. Bulk of the logic for generating the * sub-query is in this method. * * @param e a given sql expression * @return sql string for the current sub-query. */ public String sqlStringForSQLExpression(EOSQLExpression e) { StringBuffer sb = new StringBuffer(); if (attributeName != null) sb.append(e.sqlStringForAttributeNamed(attributeName)); else { EOAttribute pk = (EOAttribute) e.entity().primaryKeyAttributes().lastObject(); sb.append(e.sqlStringForAttribute(pk)); } sb.append(" IN ( "); EOEntity entity = entityName == null ? e.entity() : e.entity().model().modelGroup().entityNamed(entityName); EOFetchSpecification fs = new EOFetchSpecification(entity.name(), qualifier, null, false, true, null); if (qualifier != null) { qualifier = EOQualifierSQLGeneration.Support._schemaBasedQualifierWithRootEntity(qualifier, entity); } if (qualifier != fs.qualifier()) { fs.setQualifier(qualifier); } // ASSUME: This makes a few assumptions, if anyone can figure out a fool // proof way that would be nice to get the model // Note you can't use: // EOAdaptor.adaptorWithModel(e.entity().model()).expressionFactory(); // as this creates a // EODatabaseContext context = EODatabaseContext.registeredDatabaseContextForModel( entity.model(), EOObjectStoreCoordinator.defaultCoordinator()); EOSQLExpressionFactory factory = context.database().adaptor().expressionFactory(); NSArray subAttributes = destinationAttName != null ? new NSArray(entity.attributeNamed(destinationAttName)) : entity.primaryKeyAttributes(); EOSQLExpression subExpression = factory.expressionForEntity(entity); // Arroz: Having this table identifier replacement causes serious // problems if you have more than a table being processed in the subquery. Disabling // it will apparently not cause problems, because t0 inside the subquery is not // the same t0 outside it. // subExpression.aliasesByRelationshipPath().setObjectForKey("t1", ""); subExpression.setUseAliases(true); subExpression.prepareSelectExpressionWithAttributes(subAttributes, false, fs); // EOSQLExpression // expression=factory.selectStatementForAttributes(entity.primaryKeyAttributes(), // false, fs, entity); for (Enumeration bindEnumeration = subExpression.bindVariableDictionaries().objectEnumerator(); bindEnumeration.hasMoreElements(); ) { e.addBindVariableDictionary((NSDictionary) bindEnumeration.nextElement()); } // sb.append(ERXStringUtilities.replaceStringByStringInString("t0.", // "t1.", subExpression.statement())); sb.append(subExpression.statement()); sb.append(" ) "); return sb.toString(); }
@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(); }