Beispiel #1
0
  /**
   * Create an OEntityKey instance for the specified entity id
   *
   * @param edmDataServices edmDataServices
   * @param entity Entity set name
   * @param id Id
   * @return An OEntityKey instance
   * @throws Exception Error creating key
   */
  public static OEntityKey createEntityKey(
      EdmDataServices edmDataServices, String entitySetName, String id) throws Exception {
    // Lookup type of entity key (simple keys only)
    String keyType = null;
    EdmEntitySet entitySet = edmDataServices.getEdmEntitySet(entitySetName);
    if (entitySet != null) {
      EdmEntityType entityType = entitySet.getType();
      List<String> keys = entityType.getKeys();
      if (keys.size() == 1) {
        EdmProperty prop = entityType.findDeclaredProperty(keys.get(0));
        if (prop != null && prop.getType() != null) {
          keyType = prop.getType().getFullyQualifiedTypeName();
        }
      }
    }
    assert (keyType != null) : "Should not be possible to get this far and find no key type";

    // Create an entity key
    OEntityKey key = null;
    try {
      if (keyType.equals("Edm.Int64")) {
        key = OEntityKey.parse(id);
      } else if (keyType.equals("Edm.Int32")) {
        key = OEntityKey.parse(id);
      } else if (keyType.equals("Edm.DateTime")) {
        key = OEntityKey.parse(id);
      } else if (keyType.equals("Edm.Time")) {
        key = OEntityKey.parse(id);
      } else if (keyType.equals("Edm.String")) {
        key = OEntityKey.parse(id);
      }
    } catch (Exception e) {
      logger.warn(
          "Entity key type "
              + keyType
              + " is not supported by CommandHelper, trying OEntityKey.parse");
    }
    // could not parse the key, have one last attempt with OEntityKey create
    if (key == null) {
      try {
        if (keyType.equals("Edm.Int64")) {
          key = OEntityKey.create(Long.parseLong(id));
        } else if (keyType.equals("Edm.Int32")) {
          key = OEntityKey.create(Integer.parseInt(id));
        } else {
          key = OEntityKey.create(id);
        }
      } catch (Exception e) {
        logger.error("OEntityKey.parse failed to parse id [" + id + "]");
      }
    }
    if (key == null) throw new Exception("Entity key type " + id + " is not supported.");
    return key;
  }
/** ReceivedMessageのPort用Edm 定義体. */
public class ReceivedMessagePort extends ReceivedMessage {
  private ReceivedMessagePort() {
    super();
  }

  /** Schemaプロパティの定義体. */
  public static final EdmProperty.Builder P_SCHEMA =
      EdmProperty.newBuilder("Schema")
          .setType(EdmSimpleType.BOOLEAN)
          .setNullable(true)
          .setDefaultValue("false");

  /** EntityType Builder. */
  public static final EdmEntityType.Builder EDM_TYPE_BUILDER =
      EdmEntityType.newBuilder()
          .setNamespace(Common.EDM_NS_CELL_CTL)
          .setName(EDM_TYPE_NAME)
          .addProperties(
              Enumerable.create(
                      P_ID,
                      P_SCHEMA,
                      P_IN_REPLY_TO,
                      P_FROM,
                      P_MULTICAST_TO,
                      P_TYPE,
                      P_TITLE,
                      P_BODY,
                      P_PRIORITY,
                      P_STATUS,
                      P_REQUEST_RELATION,
                      P_REQUEST_RELATION_TARGET,
                      P_BOX_NAME,
                      Common.P_PUBLISHED,
                      Common.P_UPDATED)
                  .toList())
          .addKeys(P_ID.getName());
}
  private static void buildEntityTypes(
      MetadataStore metadataStore, List<EdmSchema.Builder> edmSchemas) {
    for (Schema schema : metadataStore.getSchemaList()) {

      List<EdmEntitySet.Builder> entitySets = new ArrayList<EdmEntitySet.Builder>();
      List<EdmEntityType.Builder> entityTypes = new ArrayList<EdmEntityType.Builder>();

      for (Table table : schema.getTables().values()) {

        KeyRecord primaryKey = table.getPrimaryKey();
        List<KeyRecord> uniques = table.getUniqueKeys();
        if (primaryKey == null && uniques.isEmpty()) {
          LogManager.logDetail(
              LogConstants.CTX_ODATA,
              ODataPlugin.Util.gs(ODataPlugin.Event.TEIID16002, table.getFullName()));
          continue;
        }

        EdmEntityType.Builder entityType =
            EdmEntityType.newBuilder().setName(table.getName()).setNamespace(schema.getName());

        // adding key
        if (primaryKey != null) {
          for (Column c : primaryKey.getColumns()) {
            entityType.addKeys(c.getName());
          }
        } else {
          for (Column c : uniques.get(0).getColumns()) {
            entityType.addKeys(c.getName());
          }
        }

        // adding properties
        for (Column c : table.getColumns()) {
          EdmProperty.Builder property =
              EdmProperty.newBuilder(c.getName())
                  .setType(ODataTypeManager.odataType(c.getDatatype().getRuntimeTypeName()))
                  .setNullable(c.getNullType() == NullType.Nullable);
          if (c.getDatatype()
              .getRuntimeTypeName()
              .equals(DataTypeManager.DefaultDataTypes.STRING)) {
            property.setFixedLength(c.isFixedLength()).setMaxLength(c.getLength()).setUnicode(true);
          }
          entityType.addProperties(property);
        }

        // entity set one for one entity type
        EdmEntitySet.Builder entitySet =
            EdmEntitySet.newBuilder().setName(table.getName()).setEntityType(entityType);

        entityType.setNamespace(schema.getName());
        entitySets.add(entitySet);

        // add enitity types for entity schema
        entityTypes.add(entityType);
      }

      // entity container is holder entity sets, association sets, function imports
      EdmEntityContainer.Builder entityContainer =
          EdmEntityContainer.newBuilder()
              .setName(schema.getName())
              .setIsDefault(false)
              .addEntitySets(entitySets);

      // build entity schema
      EdmSchema.Builder modelSchema =
          EdmSchema.newBuilder()
              .setNamespace(schema.getName())
              .addEntityTypes(entityTypes)
              .addEntityContainers(entityContainer);

      edmSchemas.add(modelSchema);
    }
  }
  public static EdmEntitySet.Builder getBuilder(String namespace) {
    EdmEntityType.Builder modelBuilder = MdHierNodeWrapper.getEntityModel(namespace);

    EdmEntityType.Builder rowType =
        EdmEntityType.newBuilder().setNamespace(namespace).setName("Row");
    EdmEntityType.Builder mdDataDimType = MdDataDimWrapper.getEntityModel(namespace);
    EdmEntityType.Builder mdHierarchyType = MdHierarchyWrapper.getEntityModel(namespace);

    EdmAssociationEnd.Builder mdHierNodeRowEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("MdHierNode")
            .setType(modelBuilder)
            .setMultiplicity(EdmMultiplicity.ONE);
    EdmAssociationEnd.Builder rowMdHierNodeEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("Rows")
            .setType(rowType)
            .setMultiplicity(EdmMultiplicity.MANY);
    EdmAssociation.Builder mdHierNodeRow =
        EdmAssociation.newBuilder()
            .setName("MdHierNode-Rows")
            .setEnds(mdHierNodeRowEnd, rowMdHierNodeEnd);

    EdmAssociationEnd.Builder mdHierNodeMdDataDimEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("MdHierNode")
            .setType(modelBuilder)
            .setMultiplicity(EdmMultiplicity.ONE);
    EdmAssociationEnd.Builder mdDataDimMdHierNodeEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("MdDataDim")
            .setType(mdDataDimType)
            .setMultiplicity(EdmMultiplicity.MANY);
    EdmAssociation.Builder mdHierNodeMdDataDim =
        EdmAssociation.newBuilder()
            .setName("MdHierNode-MdDataDim")
            .setEnds(mdHierNodeMdDataDimEnd, mdDataDimMdHierNodeEnd);

    EdmAssociationEnd.Builder mdHierarchyMdHierNodeEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("MdHierarchy")
            .setType(mdHierarchyType)
            .setMultiplicity(EdmMultiplicity.ONE);
    EdmAssociationEnd.Builder mdHierNodeMdHierarchyEnd =
        EdmAssociationEnd.newBuilder()
            .setRole("MdHierNode")
            .setType(modelBuilder)
            .setMultiplicity(EdmMultiplicity.MANY);
    EdmAssociation.Builder mdHierNodeMdHierarchy =
        EdmAssociation.newBuilder()
            .setName("MdHierNode-MdHierarchy")
            .setEnds(mdHierNodeMdHierarchyEnd, mdHierarchyMdHierNodeEnd);

    EdmNavigationProperty.Builder nodeHierarchyNavigationProperty =
        EdmNavigationProperty.newBuilder("IdHierarchy")
            .setRelationship(mdHierNodeMdHierarchy)
            .setFromTo(mdHierNodeMdHierarchy.getEnd1(), mdHierNodeMdHierarchy.getEnd2());
    modelBuilder.addNavigationProperties(nodeHierarchyNavigationProperty);

    EdmNavigationProperty.Builder nodeRowsNavigationProperty =
        EdmNavigationProperty.newBuilder("NodeRows")
            .setRelationship(mdHierNodeRow)
            .setFromTo(mdHierNodeRow.getEnd1(), mdHierNodeRow.getEnd2());
    modelBuilder.addNavigationProperties(nodeRowsNavigationProperty);

    EdmNavigationProperty.Builder nodeDataNavigationProperty =
        EdmNavigationProperty.newBuilder("NodeData")
            .setRelationship(mdHierNodeMdDataDim)
            .setFromTo(mdHierNodeMdDataDim.getEnd1(), mdHierNodeMdDataDim.getEnd2());
    modelBuilder.addNavigationProperties(nodeDataNavigationProperty);

    return EdmEntitySet.newBuilder().setName("MdHierNode").setEntityType(modelBuilder);
  }
  public static void write(EdmDataServices services, Writer w) {

    XMLWriter2 writer = XMLFactoryProvider2.getInstance().newXMLWriterFactory2().createXMLWriter(w);
    writer.startDocument();

    writer.startElement(new QName2(edmx, "Edmx", "edmx"));
    writer.writeAttribute("Version", "1.0");
    writer.writeNamespace("edmx", edmx);
    writer.writeNamespace("d", d);
    writer.writeNamespace("m", m);
    writeExtensionNamespaces(services, writer);

    writer.startElement(new QName2(edmx, "DataServices", "edmx"));
    writer.writeAttribute(new QName2(m, "DataServiceVersion", "m"), "1.0");

    // Schema
    for (EdmSchema schema : services.getSchemas()) {

      writer.startElement(new QName2("Schema"), edm);
      writer.writeAttribute("Namespace", schema.getNamespace());
      writeAnnotationAttributes(schema, writer);
      writeDocumentation(schema, writer);

      // ComplexType
      for (EdmComplexType ect : schema.getComplexTypes()) {
        writer.startElement(new QName2("ComplexType"));

        writer.writeAttribute("Name", ect.getName());
        if (null != ect.getIsAbstract()) {
          writer.writeAttribute("Abstract", ect.getIsAbstract().toString());
        }
        writeAnnotationAttributes(ect, writer);
        writeDocumentation(ect, writer);

        writeProperties(ect.getProperties(), writer);
        writeAnnotationElements(ect, writer);
        writer.endElement("ComplexType");
      }
      // EntityType
      for (EdmEntityType eet : schema.getEntityTypes()) {
        writer.startElement(new QName2("EntityType"));

        writer.writeAttribute("Name", eet.getName());
        if (null != eet.getIsAbstract()) {
          writer.writeAttribute("Abstract", eet.getIsAbstract().toString());
        }

        if (Boolean.TRUE.equals(eet.getHasStream())) {
          writer.writeAttribute(new QName2(m, "HasStream", "m"), "true");
        }

        // keys only on base types
        if (eet.isRootType()) {
          writeAnnotationAttributes(eet, writer);
          writeDocumentation(eet, writer);
          writer.startElement(new QName2("Key"));
          for (String key : eet.getKeys()) {
            writer.startElement(new QName2("PropertyRef"));
            writer.writeAttribute("Name", key);
            writer.endElement("PropertyRef");
          }

          writer.endElement("Key");
        } else {
          writer.writeAttribute("BaseType", eet.getBaseType().getFullyQualifiedTypeName());
          writeAnnotationAttributes(eet, writer);
          writeDocumentation(eet, writer);
        }

        writeProperties(eet.getDeclaredProperties(), writer);

        for (EdmNavigationProperty np : eet.getDeclaredNavigationProperties()) {

          writer.startElement(new QName2("NavigationProperty"));
          writer.writeAttribute("Name", np.getName());
          writer.writeAttribute("Relationship", np.getRelationship().getFQNamespaceName());
          writer.writeAttribute("FromRole", np.getFromRole().getRole());
          writer.writeAttribute("ToRole", np.getToRole().getRole());
          writeAnnotationAttributes(np, writer);
          writeDocumentation(np, writer);
          writeAnnotationElements(np, writer);
          writer.endElement("NavigationProperty");
        }

        writeAnnotationElements(eet, writer);
        writer.endElement("EntityType");
      }

      // Association
      for (EdmAssociation assoc : schema.getAssociations()) {
        writer.startElement(new QName2("Association"));

        writer.writeAttribute("Name", assoc.getName());
        writeAnnotationAttributes(assoc, writer);
        writeDocumentation(assoc, writer);

        writer.startElement(new QName2("End"));
        writer.writeAttribute("Role", assoc.getEnd1().getRole());
        writer.writeAttribute("Type", assoc.getEnd1().getType().getFullyQualifiedTypeName());
        writer.writeAttribute("Multiplicity", assoc.getEnd1().getMultiplicity().getSymbolString());
        writer.endElement("End");

        writer.startElement(new QName2("End"));
        writer.writeAttribute("Role", assoc.getEnd2().getRole());
        writer.writeAttribute("Type", assoc.getEnd2().getType().getFullyQualifiedTypeName());
        writer.writeAttribute("Multiplicity", assoc.getEnd2().getMultiplicity().getSymbolString());
        writer.endElement("End");

        writeAnnotationElements(assoc, writer);
        writer.endElement("Association");
      }

      // EntityContainer
      for (EdmEntityContainer container : schema.getEntityContainers()) {
        writer.startElement(new QName2("EntityContainer"));

        writer.writeAttribute("Name", container.getName());
        writer.writeAttribute(
            new QName2(m, "IsDefaultEntityContainer", "m"),
            Boolean.toString(container.isDefault()));
        writeAnnotationAttributes(container, writer);
        writeDocumentation(container, writer);

        for (EdmEntitySet ees : container.getEntitySets()) {
          writer.startElement(new QName2("EntitySet"));
          writer.writeAttribute("Name", ees.getName());
          writer.writeAttribute("EntityType", ees.getType().getFullyQualifiedTypeName());
          writeAnnotationAttributes(ees, writer);
          writeDocumentation(ees, writer);
          writeAnnotationElements(ees, writer);
          writer.endElement("EntitySet");
        }

        for (EdmFunctionImport fi : container.getFunctionImports()) {
          writer.startElement(new QName2("FunctionImport"));
          writer.writeAttribute("Name", fi.getName());
          if (null != fi.getEntitySet()) {
            writer.writeAttribute("EntitySet", fi.getEntitySet().getName());
          }
          if (fi.getReturnType() != null) {
            // TODO: how to differentiate inline ReturnType vs embedded ReturnType?
            writer.writeAttribute("ReturnType", fi.getReturnType().getFullyQualifiedTypeName());
          }
          writer.writeAttribute(new QName2(m, "HttpMethod", "m"), fi.getHttpMethod());
          writeAnnotationAttributes(fi, writer);
          writeDocumentation(fi, writer);

          for (EdmFunctionParameter param : fi.getParameters()) {
            writer.startElement(new QName2("Parameter"));
            writer.writeAttribute("Name", param.getName());
            writer.writeAttribute("Type", param.getType().getFullyQualifiedTypeName());
            if (param.getMode() != null) writer.writeAttribute("Mode", param.getMode().toString());
            writeAnnotationAttributes(param, writer);
            writeDocumentation(param, writer);
            writeAnnotationElements(param, writer);
            writer.endElement("Parameter");
          }
          writeAnnotationElements(fi, writer);
          writer.endElement("FunctionImport");
        }

        for (EdmAssociationSet eas : container.getAssociationSets()) {
          writer.startElement(new QName2("AssociationSet"));
          writer.writeAttribute("Name", eas.getName());
          writer.writeAttribute("Association", eas.getAssociation().getFQNamespaceName());
          writeAnnotationAttributes(eas, writer);
          writeDocumentation(eas, writer);

          writer.startElement(new QName2("End"));
          writer.writeAttribute("Role", eas.getEnd1().getRole().getRole());
          writer.writeAttribute("EntitySet", eas.getEnd1().getEntitySet().getName());
          writer.endElement("End");

          writer.startElement(new QName2("End"));
          writer.writeAttribute("Role", eas.getEnd2().getRole().getRole());
          writer.writeAttribute("EntitySet", eas.getEnd2().getEntitySet().getName());
          writer.endElement("End");

          writeAnnotationElements(eas, writer);
          writer.endElement("AssociationSet");
        }

        writeAnnotationElements(container, writer);
        writer.endElement("EntityContainer");
      }

      writeAnnotationElements(schema, writer);
      writer.endElement("Schema");
    }

    writer.endDocument();
  }
  private EdmEntityType.Builder parseEdmEntityType(
      XMLEventReader2 reader,
      String schemaNamespace,
      String schemaAlias,
      StartElement2 entityTypeElement) {
    String name = entityTypeElement.getAttributeByName("Name").getValue();
    String hasStreamValue =
        getAttributeValueIfExists(entityTypeElement, new QName2(NS_METADATA, "HasStream"));
    Boolean hasStream = hasStreamValue == null ? null : hasStreamValue.equals("true");
    String baseType = getAttributeValueIfExists(entityTypeElement, "BaseType");
    String isAbstractS = getAttributeValueIfExists(entityTypeElement, "Abstract");
    String openTypeValue = getAttributeValueIfExists(entityTypeElement, "OpenType");
    Boolean openType = openTypeValue == null ? null : openTypeValue.equals("true");

    List<String> keys = new ArrayList<String>();
    List<EdmProperty.Builder> edmProperties = new ArrayList<EdmProperty.Builder>();
    List<EdmNavigationProperty.Builder> edmNavigationProperties =
        new ArrayList<EdmNavigationProperty.Builder>();
    List<EdmAnnotation<?>> annotElements = new ArrayList<EdmAnnotation<?>>();

    while (reader.hasNext()) {
      XMLEvent2 event = reader.nextEvent();
      if (event.isStartElement()) {
        if (isElement(
            event,
            EDM2006_PROPERTYREF,
            EDM2007_PROPERTYREF,
            EDM2008_1_PROPERTYREF,
            EDM2008_9_PROPERTYREF,
            EDM2009_8_PROPERTYREF,
            EDM2009_11_PROPERTYREF)) {
          keys.add(event.asStartElement().getAttributeByName("Name").getValue());
        } else if (isElement(
            event,
            EDM2006_PROPERTY,
            EDM2007_PROPERTY,
            EDM2008_1_PROPERTY,
            EDM2008_9_PROPERTY,
            EDM2009_8_PROPERTY,
            EDM2009_11_PROPERTY)) {
          edmProperties.add(parseEdmProperty(reader, event));
        } else if (isElement(
            event,
            EDM2006_NAVIGATIONPROPERTY,
            EDM2007_NAVIGATIONPROPERTY,
            EDM2008_1_NAVIGATIONPROPERTY,
            EDM2008_9_NAVIGATIONPROPERTY,
            EDM2009_8_NAVIGATIONPROPERTY,
            EDM2009_11_NAVIGATIONPROPERTY)) {
          edmNavigationProperties.add(parseEdmNavigationProperty(reader, event));

        } else {
          EdmAnnotation<?> anElement = getAnnotationElements(event, reader);
          if (anElement != null) {
            annotElements.add(anElement);
          }
        }
      }

      if (isEndElement(event, entityTypeElement.getName())) {
        return EdmEntityType.newBuilder()
            .setNamespace(schemaNamespace)
            .setAlias(schemaAlias)
            .setName(name)
            .setHasStream(hasStream)
            .setOpenType(openType)
            .addKeys(keys)
            .addProperties(edmProperties)
            .addNavigationProperties(edmNavigationProperties)
            .setBaseType(baseType)
            .setIsAbstract(isAbstractS == null ? null : "true".equals(isAbstractS))
            .setAnnotations(getAnnotations(entityTypeElement))
            .setAnnotationElements(annotElements);
      }
    }

    throw new UnsupportedOperationException();
  }
  @Override
  public EntityList executeSQL(
      Query query,
      List<SQLParam> parameters,
      EdmEntitySet entitySet,
      LinkedHashMap<String, Boolean> projectedColumns,
      QueryInfo queryInfo) {
    ConnectionImpl connection = null;
    try {
      boolean cache = queryInfo != null && this.batchSize > 0;
      if (cache) {
        CacheHint hint = new CacheHint();
        hint.setTtl(this.cacheTime);
        hint.setScope(CacheDirective.Scope.USER);
        hint.setMinRows(Long.valueOf(this.batchSize));
        query.setCacheHint(hint);
      }

      boolean getCount = false;
      if (queryInfo != null) {
        getCount = queryInfo.inlineCount == InlineCount.ALLPAGES;
        if (!getCount && (queryInfo.top != null || queryInfo.skip != null)) {
          if (queryInfo.top != null && queryInfo.skip != null) {
            query.setLimit(new Limit(new Constant(queryInfo.skip), new Constant(queryInfo.top)));
          } else if (queryInfo.top != null) {
            query.setLimit(new Limit(new Constant(0), new Constant(queryInfo.top)));
          }
        }
      }

      connection = getConnection();
      String sessionId = connection.getServerConnection().getLogonResult().getSessionID();

      String skipToken = null;
      if (queryInfo != null && queryInfo.skipToken != null) {
        skipToken = queryInfo.skipToken;
        if (cache) {
          int idx = queryInfo.skipToken.indexOf(DELIMITER);
          sessionId = queryInfo.skipToken.substring(0, idx);
          skipToken = queryInfo.skipToken.substring(idx + 2);
        }
      }
      String sql = query.toString();
      if (cache) {
        sql += " /* " + sessionId + " */"; // $NON-NLS-1$ //$NON-NLS-2$
      }
      LogManager.logDetail(LogConstants.CTX_ODATA, "Teiid-Query:", sql); // $NON-NLS-1$

      final PreparedStatement stmt =
          connection.prepareStatement(
              sql,
              cache ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY,
              ResultSet.CONCUR_READ_ONLY);
      if (parameters != null && !parameters.isEmpty()) {
        for (int i = 0; i < parameters.size(); i++) {
          stmt.setObject(i + 1, parameters.get(i).value, parameters.get(i).sqlType);
        }
      }

      final ResultSet rs = stmt.executeQuery();

      if (projectedColumns == null) {
        projectedColumns = new LinkedHashMap<String, Boolean>();
        for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
          projectedColumns.put(rs.getMetaData().getColumnLabel(i + 1), Boolean.TRUE);
        }
      }

      EntityList result = new EntityList(invalidCharacterReplacement);

      HashMap<String, EdmProperty> propertyTypes = new HashMap<String, EdmProperty>();

      EdmEntityType entityType = entitySet.getType();
      Iterator<EdmProperty> propIter = entityType.getProperties().iterator();
      while (propIter.hasNext()) {
        EdmProperty prop = propIter.next();
        propertyTypes.put(prop.getName(), prop);
      }

      // skip to the initial position
      int count = 0;
      int skipSize = 0;
      // skip based upon the skip value
      if (getCount && queryInfo.skip != null) {
        skipSize = queryInfo.skip;
      }
      // skip based upon the skipToken
      if (skipToken != null) {
        skipSize += Integer.parseInt(skipToken);
      }
      if (skipSize > 0) {
        count += skip(cache, rs, skipSize);
      }

      // determine the number of records to return
      int size = batchSize;
      int top = Integer.MAX_VALUE;
      if (getCount && queryInfo.top != null) {
        top = queryInfo.top;
        size = top;
        if (batchSize > 0) {
          size = Math.min(batchSize, size);
        }
      } else if (size < 1) {
        size = Integer.MAX_VALUE;
      }

      // build the results
      for (int i = 0; i < size; i++) {
        if (!rs.next()) {
          break;
        }
        count++;
        result.addEntity(rs, propertyTypes, projectedColumns, entitySet);
      }

      // set the count
      if (getCount) {
        if (!cache) {
          while (rs.next()) {
            count++;
          }
        } else {
          rs.last();
          count = rs.getRow();
        }
      }
      result.setCount(count);

      // set the skipToken if needed
      if (cache && result.size() == this.batchSize) {
        int end = skipSize + result.size();
        if (getCount) {
          if (end < Math.min(top, count)) {
            result.setNextToken(nextToken(cache, sessionId, end));
          }
        } else if (rs.next()) {
          result.setNextToken(nextToken(cache, sessionId, end));
          // will force the entry to cache or is effectively a no-op when already cached
          rs.last();
        }
      }
      return result;
    } catch (Exception e) {
      throw new ServerErrorException(e.getMessage(), e);
    } finally {
      if (connection != null) {
        try {
          connection.close();
        } catch (SQLException e) {
        }
      }
    }
  }