pike.git / lib / modules / __builtin.pmod / Sql.pmod / Connection.pike

version» Context lines:

pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:17:   //! @ul   //! @item   //! In untyped mode, all values except SQL NULL are returned as   //! strings in their display representation, and SQL NULL is returned   //! as zero.   //! @item   //! In typed mode, values are returned in pike native form where it   //! works well. That means at least that SQL integer fields are   //! returned as pike integers, floats as floats, SQL NULL as   //! @[Val.null], and of course strings still as strings. The - //! representation of other SQL types depend on the capabilities of + //! representation of other SQL types depends on the capabilities of   //! the server specific backends. It's also possible that floats in   //! some cases are represented in other ways if too much precision is   //! lost in the conversion to pike floats.   //! @endul   //!   //! @endsection   //!   //! @note   //! For historical reasons, there may be server specific backends that   //! operate differently from what is described here, e.g. some that   //! return a bit of typed data in untyped mode.   //!   //! @note   //! Typed operation was not supported at all prior to Pike 7.8.363,   //! and may not be supported for all databases. -  + //! + //! @seealso + //! @[Sql.Connection], @[Sql.Sql()], @[Result]      #define ERROR(X ...) predef::error(X)      //! Compatibility interface.   //!   //! This used to be a variable containing the server specific   //! connection object used for the actual SQL queries.   //!   //! As the wrapper no longer exists, this symbol now   //! just evaluates to the object.
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:89:   //! string my_input = "rob' OR name!='rob";   //! my_db->query("DELETE FROM tblUsers WHERE name=%s", my_input);   //! @endcode   //!   //! The default implementation quotes single quotes by doubling them.   string quote(string s)   {    return replace(s, "\'", "\'\'");   }    - private constant timezone = localtime (0)->timezone; + private int timezone = localtime (0)->timezone;      //! Converts a system time value to an appropriately formatted time   //! spec for the database.   //!   //! @param time   //! Time to encode.   //!   //! @param date   //! If nonzero then @[time] is taken as a "full" unix time spec   //! (where the date part is ignored), otherwise it's converted as a
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:253:   //!   //! @param password   //! Password to access the database.   //!   //! @param options   //! Optional mapping of options.   //! See the SQL-database documentation for the supported options.   //! (eg @[Mysql.mysql()->create()]).   //!   //! @note + //! This function is typically called via @[Sql.Sql()]. + //! + //! @note   //! Support for @[options] was added in Pike 7.3.   //!   //! @note   //! The base class (@[__builtin.Sql.Connection]) only has a prototype. - void create(string host, void|string|mapping(string:int|string) db, + //! + //! @seealso + //! @[Sql.Sql()] + protected void create(string host, void|string|mapping(string:int|string) db,    void|string user, void|string _password,    void|mapping(string:int|string) options);      //! Returns true if the connection seems to be open.   //!   //! @note   //! This function only checks that there's an open connection,   //! and that the other end hasn't closed it yet. No data is   //! sent over the connection.   //!
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:307:   //! check the connection.   //!   //! @seealso   //! @[is_open()]   int ping()   {    if (!is_open()) return -1;    catch {    return sizeof(query("SELECT 0 AS zero") || ({})) - 1;    }; +  // FIXME: Inform is_open()?    return -1;   }      void set_charset (string charset)   //! Changes the charset that the connection uses for queries and   //! returned text strings.   //!   //! @param charset   //! The charset to use. The valid values and their meanings depends   //! on the database brand. However, the special value
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:350:   //! least) query strings. Returns zero if the connection doesn't   //! support charsets this way (typically means that a call to   //! @[set_charset] will throw an error).   //!   //! @seealso   //! @[set_charset], @[Sql.mysql.get_charset]   {    return UNDEFINED;   }    - protected array(mapping(string:mixed)) res_obj_to_array(.Result res_obj) + // FIXME: _sprintf(). +  + array(mapping(string:mixed)) +  res_obj_to_array(array(mixed)|.Result res_obj, void|array(mapping) fields)   {    if (!res_obj)    return 0;       array(mapping(string:mixed)) res = ({});    while (res_obj)    {    // Not very efficient, but sufficient    array(string) fieldnames; -  +  array(array(mixed)) rows;    array(mixed) row; -  +  int i;    -  array(mapping) fields = res_obj->fetch_fields(); -  if(!sizeof(fields)) return ({}); +  if (arrayp(res_obj)) +  rows = res_obj; +  else { +  fields = 0; +  rows = ({}); +  while (row = res_obj->fetch_row_array()) +  rows += row; +  }    -  +  if (!fields) +  fields = res_obj->fetch_fields(); +  if(!sizeof(fields)) return res; +     int has_table = fields[0]->table && fields[0]->table!="";       if(has_table)    fieldnames = (map(fields,    lambda (mapping(string:mixed) m) {    return (m->table||"") + "." + m->name;    }) +    fields->name);    else    fieldnames = fields->name;       if (case_convert)    fieldnames = map(fieldnames, lower_case);       if(has_table) -  while (row = res_obj->fetch_row()) -  res += ({ mkmapping(fieldnames, row + row) }); +  foreach (rows; i; row) +  rows[i] = mkmapping(fieldnames, row + row);    else -  while (row = res_obj->fetch_row()) -  res += ({ mkmapping(fieldnames, row) }); +  foreach (rows; i; row) +  rows[i] = mkmapping(fieldnames, row);    -  +  res += rows;    // Try the next result. -  res_obj = res_obj->next_result && res_obj->next_result(); +  res_obj = objectp(res_obj) +  && res_obj->next_result && res_obj->next_result();    }    return res;   }    - //! Return last error message. - int|string error() + //! The textual description of the last + //! server-related error. Returns @expr{0@} if no error has occurred + //! yet. It is not cleared upon reading (can be invoked multiple + //! times, will return the same result until a new error occurs). + //! + //! @note + //! The string returned is not newline-terminated. + //! + //! @param clear + //! To clear the error, set it to @expr{1@}. + int|string error(void|int clear)   { -  return "Unknown error"; +  return 0;   }      //! Return last SQLSTATE.   //!   //! The SQLSTATE error codes are specified in ANSI SQL.   string sqlstate()   {    return "IM001"; // "driver does not support this function"   }   
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:509:    continue;    }    if (objectp(s) && s->is_val_null) {    args[j] = .null_arg;    continue;    }    ERROR("Wrong type to query argument %d: %O\n", j + 1, s);    }       query = sprintf(query, @args); -  +     if (sizeof(bindings)) return ({ query, bindings });    return ({ query });   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in untyped mode.   //!   //! @param q   //! Query to send to the SQL-server. This can either be a string with the   //! query, or a previously compiled query (see @[compile_query()]).   //!   //! @returns - //! The result is returned as an @[Sql.sql_result] object in untyped + //! An @[Sql.Result] object in untyped   //! mode. This allows for having some more info about the result as   //! well as processing the result in a streaming fashion, although the   //! result itself wasn't obtained streamingly from the server.   //! - //! Returns @expr{0@} if the query didn't return any result - //! (e.g. @tt{INSERT@} or similar). - //! +    //! @throws - //! Throws an exception if the query fails. + //! Might throw an exception if the query fails. In some cases, the + //! exception is delayed, because the database reports the error + //! a (little) while after the query has already been started.   //! - //! Called by other variants of @[big_query()] after they have processed - //! their extra arguments. - //! +    //! This prototype function is the base variant and is intended to be   //! overloaded by actual drivers.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[query] also for   //! ones that return only a few rows.   //!   //! @seealso - //! @[query], @[streaming_query] - int|.Result big_query(object|string q); + //! @[query], @[streaming_query], @[big_typed_query], @[streaming_typed_query] + variant .Result big_query(object|string q);      //! Send an SQL query synchronously to the SQL-server and return   //! the results in untyped mode.   //!   //! @param q   //! Query to send to the SQL-server. This can either be a string with the   //! query, or a previously compiled query (see @[compile_query()]).   //!   //! @param bindings   //! A mapping containing bindings of variables used in the query.
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:570:   //! the variable is used.   //!   //! @code   //! res = query("SELECT foo FROM bar WHERE gazonk=:baz",   //! ([":baz":"value"]));   //! @endcode   //!   //! Binary values (BLOBs) may need to be placed in multisets.   //!   //! @returns - //! The result is returned as an @[Sql.sql_result] object in untyped + //! An @[Sql.Result] object in untyped   //! mode. This allows for having some more info about the result as   //! well as processing the result in a streaming fashion, although the   //! result itself wasn't obtained streamingly from the server.   //! - //! Returns @expr{0@} if the query didn't return any result - //! (e.g. @tt{INSERT@} or similar). - //! +    //! @throws - //! Throws an exception if the query fails. + //! Might throw an exception if the query fails. In some cases, the + //! exception is delayed, because the database reports the error + //! a (little) while after the query has already been started.   //!   //! Calls the base variant of @[big_query()] after having inserted   //! the bindings into the query (using @[emulate_bindings()]).   //!   //! Drivers that actually support bindings should overload this   //! variant in addition to the base variant.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[query] also for   //! ones that return only a few rows.   //!   //! @seealso - //! @[query], @[emulate_bindings], @[streaming_query] - variant int|.Result big_query(object|string q, + //! @[query], @[emulate_bindings], @[streaming_query], @[big_typed_query], + //! @[streaming_typed_query] + variant .Result big_query(object|string q,    mapping(string|int:mixed) bindings)   {    return big_query(emulate_bindings(q, bindings));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in untyped mode.   //!   //! @param q   //! Query to send to the SQL-server. This can either be a string with the
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:616:   //!   //! @param extraarg   //! @param extraargs   //! Arguments as you would use in sprintf. They are automatically   //! quoted.   //!   //! @code   //! res = query("select foo from bar where gazonk=%s","value");   //! @endcode   //! - //! The result is returned as an @[Sql.sql_result] object in untyped - //! mode. This allows for having some more info about the result as - //! well as processing the result in a streaming fashion, although the - //! result itself wasn't obtained streamingly from the server. Returns - //! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@} - //! or similar). + //! @returns + //! An @[Sql.Result] object in untyped + //! mode. This allows for having some more info about the result as + //! well as processing the result in a streaming fashion, although the + //! result itself wasn't obtained streamingly from the server.   //!   //! The default implementation normalizes @[q] and @[extraargs] to   //! use the bindings mapping (via @[handle_extraargs()]), and calls   //! one of the other variants of @[big_query()] with the result.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[query] also for   //! ones that return only a few rows.   //!   //! @seealso   //! @[query], @[handle_extraargs], @[streaming_query] - variant int|.Result big_query(object|string q, + variant .Result big_query(object|string q,    string|multiset|int|float|object extraarg,    string|multiset|int|float|object ... extraargs)   {    return big_query(@handle_extraargs(q, ({ extraarg }) + extraargs));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in untyped mode.   //!   //! For the arguments, please see the @[big_query()] function.
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:678:    mixed ... extraargs)   {    return res_obj_to_array(big_query(q, @extraargs));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in typed mode.   //!   //! For the argument, please see the @[big_query()] function.   //! - //! The result is returned as an @[Sql.sql_result] object in typed + //! @returns + //! An @[Sql.Result] object in typed   //! mode. This allows for having some more info about the result as   //! well as processing the result in a streaming fashion, although the - //! result itself wasn't obtained streamingly from the server. Returns - //! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@} - //! or similar). + //! result itself wasn't obtained streamingly from the server.   //!   //! @note - //! Typed mode is not supported by all sql databases. If not - //! supported, an error is thrown. + //! Typed mode support varies per database and per datatype. + //! SQL datatypes which the current database cannot return as a native Pike + //! type, will be returned as (untyped) strings.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[typed_query] also   //! for ones that return only a few rows.   //! - //! Called by @[big_typed_query()] after it has processed any bindings. + //! Drivers should override this prototype function.   //! - //! This prototype function is intended for overriding by drivers. - //! +    //! @seealso   //! @[query], @[typed_query], @[big_query], @[streaming_query] - int|.Result big_typed_query(object|string q); + variant .Result big_typed_query(object|string q) + { +  return big_query(q); // Fall back to untyped, if no native support + }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in typed mode.   //!   //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as an @[Sql.sql_result] object in typed + //! The result is returned as an @[Sql.Result] object in typed   //! mode. This allows for having some more info about the result as   //! well as processing the result in a streaming fashion, although the - //! result itself wasn't obtained streamingly from the server. Returns - //! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@} - //! or similar). + //! result itself wasn't obtained streamingly from the server.   //!   //! @note - //! Typed mode is not supported by all sql databases. If not - //! supported, an error is thrown. + //! Typed mode support varies per database and per datatype. + //! SQL datatypes which the current database cannot return as a native Pike + //! type, will be returned as (untyped) strings.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[typed_query] also   //! for ones that return only a few rows.   //! - //! Called by @[big_typed_query()] after it has processed any bindings. + //! Drivers that actually support bindings should overload this + //! variant in addition to the base variant.   //!   //! @seealso   //! @[query], @[typed_query], @[big_query], @[streaming_query] - variant int|.Result big_typed_query(object|string q, + variant .Result big_typed_query(object|string q,    mapping(string|int:mixed) bindings)   {    return big_typed_query(emulate_bindings(q, bindings));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in typed mode.   //!   //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as an @[Sql.sql_result] object in typed + //! The result is returned as an @[Sql.Result] object in typed   //! mode. This allows for having some more info about the result as   //! well as processing the result in a streaming fashion, although the - //! result itself wasn't obtained streamingly from the server. Returns - //! @expr{0@} if the query didn't return any result (e.g. @tt{INSERT@} - //! or similar). + //! result itself wasn't obtained streamingly from the server.   //!   //! @note - //! Typed mode is not supported by all sql databases. If not - //! supported, an error is thrown. + //! Typed mode support varies per database and per datatype. + //! SQL datatypes which the current database cannot return as a native Pike + //! type, will be returned as (untyped) strings.   //!   //! @note   //! Despite the name, this function is not only useful for "big"   //! queries. It typically has less overhead than @[typed_query] also   //! for ones that return only a few rows.   //!   //! @seealso   //! @[query], @[typed_query], @[big_query], @[streaming_query] - variant int|.Result big_typed_query(object|string q, + variant .Result big_typed_query(object|string q,    string|multiset|int|float|object extraarg,    string|multiset|int|float|object ... extraargs)   {    return big_typed_query(@handle_extraargs(q, ({ extraarg }) + extraargs));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results in typed mode.   //!   //! For the arguments, please see the @[query()] function.
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:782:   //! The result as an array of mappings indexed on the name of   //! the columns. The values have the appropriate native pike   //! types where they fit the SQL data types - see the class doc   //! for details on typed mode.   //! @type zero   //! The value @expr{0@} (zero) if the query didn't return any   //! result (eg @tt{INSERT@} or similar).   //! @endmixed   //!   //! @note - //! Typed mode is not supported by all sql databases. If not - //! supported, an error is thrown. + //! Typed mode support varies per database and per datatype. + //! SQL datatypes which the current database cannot return as a native Pike + //! type, will be returned as (untyped) strings.   //!   //! @note   //! The default implementation calls @[big_typed_query()]   //! and converts its result.   //!   //! @seealso   //! @[query], @[big_typed_query]   array(mapping(string:mixed)) typed_query(object|string q, mixed ... extraargs)   {    return res_obj_to_array(big_typed_query(q, @extraargs));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in untyped mode.   //! - //! For the arguments, please see the @[low_big_query()] function. + //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! untyped mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). For the other arguments, they are the same as - //! for the @[query()] function. +    //! - //! Called by @[streaming_query()] after it has processed any bindings. + //! Drivers should override this prototype function.   //! - //! This variant function is intended for overriding by drivers. - //! +    //! @note - //! Streaming operation is not supported by all sql databases. - //! The default implementation falls back to calling @[big_query()]. + //! Typed mode support varies per database and per datatype. + //! SQL datatypes which the current database cannot return as a native Pike + //! type, will be returned as (untyped) strings.   //!   //! @seealso   //! @[big_query], @[streaming_typed_query] - int|.Result streaming_query(object|string q) + variant .Result streaming_query(object|string q)   {    return big_query(q);   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in untyped mode.   //! - //! For the arguments, please see the @[low_big_query()] function. + //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! untyped mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). For the other arguments, they are the same as - //! for the @[query()] function. +    //! - //! Called by @[streaming_query()] after it has processed any bindings. + //! Drivers that implement bindings should override this prototype function.   //! - //! This variant function is intended for overriding by drivers that - //! actually implement bindings. - //! - //! @note - //! Streaming operation is not supported by all sql databases. - //! The default implementation falls back to calling @[big_query()]. - //! +    //! @seealso   //! @[big_query], @[streaming_typed_query] - variant int|.Result streaming_query(object|string q, + variant .Result streaming_query(object|string q,    mapping(string:mixed) bindings)   {    return streaming_query(emulate_bindings(q, bindings));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in untyped mode.   //! - //! For the arguments, please see the @[query()] function. + //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! untyped mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). For the other arguments, they are the same as - //! for the @[query()] function. +    //! - //! @note - //! Streaming operation is not supported by all sql databases. - //! If not supported, this function will fall back to calling - //! @[big_query()]. - //! +    //! @seealso   //! @[big_query], @[streaming_typed_query] - variant int|.Result streaming_query(object|string q, + variant .Result streaming_query(object|string q,    string|multiset|int|float|object extraarg,    string|multiset|int|float|object ... extraargs)   {    return streaming_query(@handle_extraargs(q, ({ extraarg }) + extraargs));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in typed mode.   //! - //! For the arguments, please see the @[query()] function. + //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! typed mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). +    //! -  + //! Drivers should override this prototype function.   //! - //! Called by @[streaming_query()] after it has processed any bindings. - //! - //! This function is intended for overriding by drivers. - //! - //! @note - //! Neither streaming operation nor typed results are supported - //! by all sql databases. The default implentation falls back to - //! calling @[big_typed_query()]. - //! +    //! @seealso - //! @[streaming_query], @[big_typed_query] - int|.Result streaming_typed_query(object|string q) + //! @[big_query], @[streaming_query], @[big_typed_query] + variant .Result streaming_typed_query(object|string q)   {    return big_typed_query(q);   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in typed mode.   //! - //! For the arguments, please see the @[query()] function. + //! For the arguments, please see the @[big_query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! typed mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). +    //! -  + //! Drivers should override this prototype function.   //! - //! Called by @[streaming_query()] after it has processed any bindings. - //! - //! This function is intended for overriding by drivers. - //! - //! @note - //! Neither streaming operation nor typed results are supported - //! by all sql databases. The default implentation falls back to - //! calling @[low_big_typed_query()]. - //! +    //! @seealso - //! @[streaming_query], @[big_typed_query] - variant int|.Result streaming_typed_query(object|string q, + //! @[big_query], @[streaming_query], @[big_typed_query] + variant .Result streaming_typed_query(object|string q,    mapping(string|int:mixed) bindings)   {    return streaming_typed_query(emulate_bindings(q, bindings));   }      //! Send an SQL query synchronously to the SQL-server and return   //! the results streaming in typed mode.   //!   //! For the arguments, please see the @[query()] function.   //! - //! The result is returned as a streaming @[Sql.sql_result] object in + //! @returns + //! A streaming @[Sql.Result] object in   //! typed mode. This allows for having results larger than the   //! available memory, and returning some more info about the result. - //! Returns @expr{0@} if the query didn't return any result (e.g. - //! INSERT or similar). +    //! - //! @note - //! Neither streaming operation nor typed results are supported - //! by all sql databases. If not supported, this function will - //! fall back to calling @[big_typed_query()]. - //! +    //! @seealso - //! @[streaming_query], @[big_typed_query] - variant int|.Result streaming_typed_query(object|string q, + //! @[big_query], @[streaming_query], @[big_typed_query] + variant .Result streaming_typed_query(object|string q,    string|multiset|int|float|object extraarg,    string|multiset|int|float|object ... extraargs)   {    return streaming_typed_query(@handle_extraargs(q, ({ extraarg }) + extraargs));   }      //! Create a new database.   //!   //! @param db   //! Name of database to create.
pike.git/lib/modules/__builtin.pmod/Sql.pmod/Connection.pike:1180:       if (res && wild) {    res =    filter(res,    map(res->name,    Regexp(replace(wild, ({"%", "_"}), ({".*", "."})))->match));    }       return res;   } +  + //! Sends a typed query to the database asynchronously. + //! + //! @returns + //! An @[Sql.Promise] object which can be used to obtain + //! an @[Sql.FutureResult] object to evaluate the query. + //! + //! @seealso + //! @[streaming_typed_query()], @[Sql.Promise], @[Sql.FutureResult] + //! + //! @param map_cb + //! + //! Callback function which is called for every row returned. + //! First parameter is the row, second parameter is the result object + //! being processed, and the third parameter is the array of result rows + //! already collected so far. The function should return the modified + //! version of the row that needs to be stored, or it should return + //! @expr{0@} to discard the row. + //! + //! @example + //! @code + //! + //! Sql.Connection db = Sql.Connection("..."); + //! Sql.Promise q1 = db->promise_query("SELECT 42")->max_records(10); + //! Sql.Promise q2 = db->promise_query("SELECT :foo::INT", (["foo":2])); + //! + //! array(Concurrent.Future) all = ({ q1, q2 })->future(); + //! + //! // To get a callback for each of the requests + //! + //! all->on_success(lambda (Sql.FutureResult resp) { + //! werror("Got result %O from %O\n", resp->get(), resp->query); + //! }); + //! all->on_failure(lambda (Sql.FutureResult resp) { + //! werror("Request %O failed: %O\n", resp->query, + //! resp->status_command_complete); + //! }); + //! + //! // To get a callback when all of the requests are done. In this case + //! // on_failure will be called if any of the requests fails. + //! + //! Concurrent.Future all2 = Concurrent.results(all); + //! + //! all2->on_success(lambda (array(Sql.FutureResult) resp) { + //! werror("All requests were successful: %O\n", resp); + //! }); + //! all->on_failure(lambda (Sql.FutureResult resp) { + //! werror("Requests %O failed with %O.\n", resp->query, + //! resp->status_command_complete); + //! }); + //! @endcode + public variant .Promise promise_query(string q, +  void|mapping(string|int:mixed) bindings, +  void|function(array, .Result, array :array) map_cb) { +  return __builtin.Sql.Promise(this, q, bindings, map_cb); + } + public variant .Promise promise_query(string q, +  function(array, .Result, array :array) map_cb) { +  return __builtin.Sql.Promise(this, q, 0, map_cb); + }