/** Return a summary description of this query. */
  public String getSummary() {
    StringBuilder sb = new StringBuilder(80);
    sb.append("FindIds exeMicros[")
        .append(executionTimeMicros)
        .append("] rows[")
        .append(rowCount)
        .append("] type[")
        .append(desc.getName())
        .append("] predicates[")
        .append(predicates.getLogWhereSql())
        .append("] bind[")
        .append(bindLog)
        .append("]");

    return sb.toString();
  }
  /** Execute the query returning the row count. */
  public BeanIdList findIds() throws SQLException {

    long startNano = System.nanoTime();

    try {
      // get the list that we are going to put the id's into.
      // This was already set so that it is available to be
      // read by other threads (it is a synchronised list)
      List<Object> idList = query.getIdList();
      if (idList == null) {
        // running in foreground thread (not FutureIds query)
        idList = Collections.synchronizedList(new ArrayList<Object>());
        query.setIdList(idList);
      }

      BeanIdList result = new BeanIdList(idList);

      SpiTransaction t = request.getTransaction();
      Connection conn = t.getInternalConnection();
      pstmt = conn.prepareStatement(sql);

      if (query.getBufferFetchSizeHint() > 0) {
        pstmt.setFetchSize(query.getBufferFetchSizeHint());
      }

      if (query.getTimeout() > 0) {
        pstmt.setQueryTimeout(query.getTimeout());
      }

      bindLog = predicates.bind(new DataBind(pstmt));

      ResultSet rset = pstmt.executeQuery();
      dataReader = new RsetDataReader(rset);

      boolean hitMaxRows = false;
      boolean hasMoreRows = false;
      rowCount = 0;

      DbReadContext ctx = new DbContext();

      while (rset.next()) {
        Object idValue = desc.getIdBinder().read(ctx);
        idList.add(idValue);
        // reset back to 0
        dataReader.resetColumnPosition();
        rowCount++;

        if (maxRows > 0 && rowCount == maxRows) {
          hitMaxRows = true;
          hasMoreRows = rset.next();
          break;
        }
      }

      if (hitMaxRows) {
        result.setHasMore(hasMoreRows);
      }

      long exeNano = System.nanoTime() - startNano;
      executionTimeMicros = (int) exeNano / 1000;

      return result;

    } finally {
      close();
    }
  }