code: public List<GroovyRowResult> rows(String sql, int offset, int maxRows, Closure metaClosure) throws SQLException {
          AbstractQueryCommand command = createQueryCommand(sql);
          // for efficiency set maxRows (adjusted for the first offset rows we are going to skip the cursor over)
          command.setMaxRows(offset + maxRows);
          ResultSet rs = null;
          try {
              rs = command.execute();
              List<GroovyRowResult> result = asList(sql, rs, offset, maxRows, metaClosure);
              rs = null;
              return result;
          } finally {
              command.closeResources(rs);
          }
      }
docs: Performs the given SQL query and return a "page" of rows from the result set.  A page is defined as starting at
  a 1-based offset, and containing a maximum number of rows.
  In addition, the <code>metaClosure</code> will be called once passing in the
  <code>ResultSetMetaData</code> as argument.
  <p>
  Note that the underlying implementation is based on either invoking <code>ResultSet.absolute()</code>,
  or if the ResultSet type is <code>ResultSet.TYPE_FORWARD_ONLY</code>, the <code>ResultSet.next()</code> method
  is invoked equivalently.  The first row of a ResultSet is 1, so passing in an offset of 1 or less has no effect
  on the initial positioning within the result set.
  <p>
  Note that different database and JDBC driver implementations may work differently with respect to this method.
  Specifically, one should expect that <code>ResultSet.TYPE_FORWARD_ONLY</code> may be less efficient than a
  "scrollable" type.
  <p>
  Resource handling is performed automatically where appropriate.
  
  @param sql         the SQL statement
  @param offset      the 1-based offset for the first row to be processed
  @param maxRows     the maximum number of rows to be processed
  @param metaClosure called for meta data (only once after sql execution)
  @return a list of GroovyRowResult objects
  @throws SQLException if a database access error occurs