/**
   * 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();
  }
Пример #2
0
    @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();
    }