code: public void query(String sql, List<Object> params, @ClosureParams(value=SimpleType.class, options="java.sql.ResultSet") Closure closure) throws SQLException {
          Connection connection = createConnection();
          PreparedStatement statement = null;
          ResultSet results = null;
          try {
              statement = getPreparedStatement(connection, sql, params);
              results = statement.executeQuery();
              closure.call(results);
          } catch (SQLException e) {
              LOG.warning("Failed to execute: " + sql + " because: " + e.getMessage());
              throw e;
          } finally {
              closeResources(connection, statement, results);
          }
      }
docs: Performs the given SQL query, which should return a single
  <code>ResultSet</code> object. The given closure is called
  with the <code>ResultSet</code> as its argument.
  The query may contain placeholder question marks which match the given list of parameters.
  <p>
  Example usage:
  <pre>
  sql.query('select * from PERSON where lastname like ?', ['%a%']) { ResultSet rs {@code ->}
  while (rs.next()) println rs.getString('lastname')
  }
  </pre>
  <p>
  This method supports named and named ordinal parameters.
  See the class Javadoc for more details.
  <p>
  All resources including the ResultSet are closed automatically
  after the closure is called.
  
  @param sql     the sql statement
  @param params  a list of parameters
  @param closure called for each row with a <code>ResultSet</code>
  @throws SQLException if a database access error occurs