## About:
-This is a modern binding to the mature [libpq, the official PostgreSQL C-client library](http://www.postgresql.org/docs/current/static/libpq.html).
+This is a modern binding to the mature [libpq](http://www.postgresql.org/docs/current/static/libpq.html), the official PostgreSQL C-client library.
### Highlights:
# class pq\Connection
-A class representing a connection to the PostgreSQL server.
+The connection to the PostgreSQL server.
See the [General Usage](pq/Connection/: General Usage) page for an introduction on how to use this class.
* STARTED
Waiting for connection to be made.
* MADE
-Connection OK; waiting to send.
+Connection okay; waiting to send.
* AWAITING_RESPONSE
Waiting for a response from the server.
* AUTH_OK
Whether the connection is busy with [asynchronous operations](pq/Connection/: Asynchronous Usage).
* public (readonly) $errorMessage
Any error message on failure.
+* public (readonly) $eventHandlers
+ List of registered event handlers.
* public $encoding = NULL
Connection character set.
* public $unbuffered = FALSE
- Whether to fetch results in unbuffered mode, i.e. each row generates a distinct pq\Result.
+ Whether to fetch [asynchronous](pq/Connection/: Asynchronous Usage) results in unbuffered mode, i.e. each row generates a distinct pq\Result.
### Connection Information:
* public (readonly) $db
-The database name of the connection.
+ The database name of the connection.
* public (readonly) $user
-The user name of the connection.
+ The user name of the connection.
* public (readonly) $pass
-The password of the connection.
+ The password of the connection.
* public (readonly) $host
-The server host name of the connection.
+ The server host name of the connection.
* public (readonly) $port
-The port of the connection.
+ The port of the connection.
* public (readonly) $options
-The command-line options passed in the connection request.
+ The command-line options passed in the connection request.
+
+### Inheritable Defaults:
+* public $defaultFetchType = pq\Result::FETCH_ARRAY
+ Default fetch type for future pq\Result instances.
+* public $defaultAutoConvert = pq\Result::CONV_ALL
+ Default conversion bitmask for future pq\Result instances.
+* public $defaultTransactionIsolation = pq\Transaction::READ_COMMITTED
+ Default transaction isolation level for future pq\Transaction instances.
+* public $defaultTransactionReadonly = FALSE
+ Default transaction readonlyness for futire pq\Transaction instances.
+* public $defaultTransactionDeferrable = FALSE
+ Default transaction deferrability for future pq\Transaction instances.
+
--- /dev/null
+# pq\Connection: Asynchronous Usage
+
+Whenever you start an asynchronous operation, you will have to probe pq\Connection::poll() to determine the current status of the operation.
+
+You can then use the ***public readonly*** property pq\Connection::$socket with ```stream_select()``` to wait for read/write-readiness.
+
+> ***NOTE:***
+You cannot use the connection for anything else while an asynchronous operation is active.
+
+## Connect or reset asynchronously:
+
+First, you can establish or reset a connection asynchronously.
+
+### Start asynchronous connect:
+
+ <?php
+
+ $c = new pq\Connection(null, pq\Connection::ASYNC);
+
+ ?>
+
+### Start asynchronous reset:
+
+ <?php
+
+ $c->resetAsync();
+
+ ?>
+
+### Complete asynchronous operation:
+
+Keep in mind that you have to test for write-readiness once *before* starting the polling loop on connect/reset.
+
+ <?php
+
+ // wait until the stream becomes writable
+ $w = array($c->socket);
+ $r = $e = null;
+
+ if (stream_select($r, $w, $e, null)) {
+
+ // loop until the connection is established
+ while (true) {
+
+ switch ($c->poll()) {
+
+ case pq\Connection::POLLING_READING:
+ // we should wait for the stream to be read-ready
+ $r = array($c->socket);
+ stream_select($r, $w, $e, NULL);
+ break;
+
+ case pq\Connection::POLLING_WRITING:
+ // we should wait for the stream to be write-ready
+ $w = array($c->socket);
+ $r = $e = null;
+ stream_select($r, $w, $e, null);
+ break;
+
+ case pq\Connection::POLLING_FAILED:
+ printf("Connection failed: %s\n", $c->errorMessage);
+ break 2;
+
+ case pq\Connection::POLLING_OK:
+ printf("Connection completed\n");
+ break 2;
+ }
+ }
+
+ ?>
+
+
+If you use an appropriate timeout in the ```stream_select()``` call and do something else at the end of the while loop, you probably got the idea...
+
+## Execute queries asynchronously:
+
+ <?php
+
+ $c = new pq\Connection;
+ $c->execAsync("SELECT 1+2+3; SELECT 2,3,4", function ($res) {
+ var_dump($res);
+ });
+
+ ?>
+
+The body of the while loop looks slightly different, when executing queries asynchronously, because you only have to wait for read-readiness.
+
+You can use the ***public readonly*** property pq\Connection::$busy to test if a call to pq\Connection::getResult() would block, and if so wait for read-readiness and then call pq\Connection::poll().
+
+ <?php
+
+ do {
+ while ($c->busy) {
+ $r = array($c->socket);
+ $w = $e = null;
+ if (stream_select($r, $w, $e, null)) {
+ $c->poll();
+ }
+ }
+ } while ($c->getResult());
+
+ ?>
+
+If pq\Connection::getResult() returns NULL, there's nothing more in the pipeline.
--- /dev/null
+# Executing queries
+
+ext/pq provides three means to execute queries against the PostgreSQL server:
+
+* pq\Connection::exec()
+ Simple plain execution of a query.
+* pq\Connection::execParams()
+ Automatic prepare & execute of an unnamed statement.
+* pq\Connection::prepare() and pq\Statement::exec()
+ Explicit prepare & execute of an named statement.
+
+
+## Simple plain execution of a query
+
+pq\Connection::exec() accepts a single argument, a ***query string***, containing a single or multiple SQL queries, separated by semi-colon.
+
+ <?php
+ $result = $c->exec("SELECT 1*s,2*s,3*s FROM generate_series(1,3) s");
+ ?>
+
+An object of class pq\Result is returned on success. See [Fetching results](pq/: Fetching Results) for details.
+
+> ***NOTE:***
+> Only the last result will be returned, if the query string contains more than one SQL query.
+
+
+## Automatic prepare & execute of an unnamed statement
+
+pq\Connection::execParams() accepts a ***query string*** with a single SQL query as first argument, which will be prepared as an unnamed statement.
+
+The second argument is an ***array of parameters*** to execute the prepared statement with.
+
+If the third argument is present, an ***array with pg_type OIDs***, those types will be used for the parameters. See [Using types](pq/: Using Types) for details.
+
+ <?php
+ $result = $c->execParams("SELECT int($1) * s, int($2) * s, int($3) * s FROM generate_series(1,3) s", array(1,2,3));
+ ?>
+
+An object of class pq\Result is returned on success. See [Fetching results](pq/: Fetching Results) for details.
+
+
+## Explicit prepare & execute of a named statement
+
+pq\Connection::prepare() requires the ***statement name*** as string as first argument. This name is used later to refer to this prepared statement. See [Prepared statements](pq/: Prepared Statements) for details.
+
+The second argument is a ***query string*** containing a single SQL query, which will be prepared on the server.
+
+If the third argument is present, an ***array with pg_type OIDs***, those types will be used for the parameters. See [Using types](pq/: Using Types) for details.
+
+ <?php
+
+ $statement = $c->prepare("my_stm", "SELECT \$1::int*s,\$2::int*s,\$3::int*s FROM generate_series(1,3) s");
+ $result = $statement->exec(array(1,2,3));
+
+ ?>
+
+An object of class pq\Statement will be returned on success. See [Prepared statements](pq/: Prepared Statements) for details.
--- /dev/null
+# pq\Connection: General Usage
+
+What is needed to create, check and reset a connection.
+
+## Creating a connection:
+
+Creating a connection to the PostgreSQL server is as simple as:
+
+ <?php
+
+ $connection = new pq\Connection("dbname=test user=test password=test");
+
+ ?>
+
+The first argument to the Connection constructor is a ***connection string*** as described [in the PostgreSQL documentation](http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING).
+
+Optional ***flags*** are accepted as second argument. See [connection flag constants](pq/Connection#Connection.Flags:).
+
+### Creating a persistent connection:
+
+ <?php
+
+ $connection = new pq\Connection("dbname=test user=test password=test", pq\Connection::PERSISTENT);
+
+ ?>
+
+### Creating an asynchronously opened connection:
+
+ <?php
+
+ $connection = new pq\Connection("dbname=test user=test password=test", pq\Connection::ASYNC);
+
+ ?>
+
+## Checking the connection status:
+
+The connection object provides a ***public readonly*** property pq\Connection::$status, which value can be one of the [connection status constants](pq/Connection#Connection.Status:).
+
+ <?php
+
+ switch ($connection->status) {
+ case pq\Connection::OK:
+ // connection complete
+ break;
+ case pq\Connection::BAD:
+ $connection->reset();
+ break;
+ default:
+ // connection in progress
+ break;
+ }
+
+ ?>
+
+## Resetting the connection:
+
+ <?php
+
+ $connection->reset();
+
+ ?>
+
+Attempt to close the connection to the server and reestablish a new connection with the same connection parameters previously used.
+
+## Closing the connection:
+
+ <?php
+
+ $connection = NULL;
+
+ ?>
+
+### Non-persistent connections:
+
+A ***non-persistent*** connection will be closed when all references to the pq\Connection object are gone.
+
+### Persistent connections:
+
+A ***persistent*** connection will be recycled, when it is not referenced any longer.
+
+There is also some cleanup performed, so that subsequent usage is as unimpaired as possible:
+
+* any active asynchronous queries are canceled
+* any pending results of asynchronous queries are fetched and cleared
+* ```ROLLBACK``` if pq\Connection::$transactionStatus is anything but pq\Connection::TRANS_IDLE
+* ```RESET ALL``` to reset any changed session variables
+* ```UNLISTEN``` for each listened notification channel
See also [General Usage](pq/Connection/: General Usage).
## Params:
-* string $dsn = ""
+* Optional string $dsn = ""
A ***connection string*** as described [in the PostgreSQL documentation](http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING).
-* int $flags = 0
+* Optional int $flags = 0
See [connection flag constants](pq/Connection#Connection.Flags:).
## Throws:
## Example:
-Creating a connection:
-
<?php
$connection = new pq\Connection("dbname=test user=test password=test",
--- /dev/null
+# pq\Cursor pq\Connection::declare(string $name, int $flags, string $query)
+
+Declare a cursor for a query.
+
+## Params:
+
+* string $name
+ The identifying name of the cursor.
+* int $flags
+ Any combination of pq\Cursor constants.
+* string $query
+ The query for which to open a cursor.
+
+## Returns:
+
+* pq\Cursor, an open cursor instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\RuntimeException
+* pq\Exception\BadMethodCallException
+
+## Example:
+
+ <?php
+
+ $connection = new pq\Connection;
+
+ $cursor = $connection->declare("example", pq\Cursor::WITH_HOLD,
+ "SELECT * FROM generate_series(0,29) s WHERE (s%2)=0");
+
+ for ( $result = $cursor->fetch(2);
+ $result->numRows;
+ $cursor->move(1), $result = $cursor->fetch(2)) {
+ foreach ($result as $row) {
+ foreach ($row as $col) {
+ echo " $col";
+ }
+ echo "\n";
+ }
+ }
+
+ ?>
+
+Yields:
+
+ 0
+ 2
+ 6
+ 8
+ 12
+ 14
+ 18
+ 20
+ 24
+ 26
--- /dev/null
+# pq\Cursor pq\Connection::declareAsync(string $name, int $flags, string $query)
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) declare a cursor for a query.
+
+> ***NOTE***:
+ If pq\Connection::$unbuffered is TRUE, each call to pq\Connection::getResult() will generate a distinct pq\Result containing exactly one row.
+
+## Params:
+
+* string $name
+ The identifying name of the cursor.
+* int $flags
+ Any combination of pq\Cursor constants.
+* string $query
+ The query for which to open a cursor.
+
+## Returns:
+
+* pq\Cursor, an open cursor instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\RuntimeException
+* pq\Exception\BadMethodCallException
--- /dev/null
+# string pq\Connection::escapeBytea(string $binary)
+
+Escape binary data for use within a query with the type bytea.
+
+> ***NOTE:***
+ The result is not wrapped in single quotes.
+
+## Params:
+
+* string $binary
+ The binary data to escape.
+
+## Returns:
+
+* string, the escaped binary data.
+* FALSE, if escaping fails.
+
+## Throws:
+
+* pq\Exception\BadMethodCallException
--- /dev/null
+# pq\Result pq\Connection::exec(string $query)
+
+[Execute one or multiple SQL queries](pq/Connection/: Executing Queries) on the connection.
+
+> ***NOTE:***
+> Only the last result will be returned, if the query string contains more than one SQL query.
+
+
+## Params:
+
+* string $query
+ The queries to send to the server, separated by semi-colon.
+
+## Returns:
+
+* pq\Result
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+* pq\Exception\DomainException
+
+
+## Example:
+
+ <?php
+
+ $connection = new pq\Connection;
+ $result = $connection->exec("SELECT 1");
+
+ ?>
--- /dev/null
+# void pq\Connection::exec(string $query[, callable $callback])
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) [execute an SQL query](pq/Connection: Executing Queries) on the connection.
+
+> ***NOTE***:
+ If pq\Connection::$unbuffered is TRUE, each call to pq\Connection::getResult() will generate a distinct pq\Result containing exactly one row.
+
+## Params:
+
+* string $query
+ The query to send to the server.
+* Optional callable $callback as function(pq\Result $res)
+ The callback to execute when the query finishes.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+## Example:
+
+ <?php
+
+ $connection = new pq\Connection;
+ $connection->execAsync("SELECT 1", function($res) {
+ //...
+ });
+ $connection->getResult();
+
+ ?>
--- /dev/null
+# pq\Result pq\Connection::execParams(string $query, array $params[, array $types = NULL])
+
+[Execute an SQL query](pq/Connection: Executing Queries) with properly escaped parameters substituted.
+
+## Params:
+
+* string $query
+ The query to execute.
+* array $params
+ The parameter list to substitute.
+* Optional array $types = NULL
+ Corresponding list of type OIDs for the parameters.
+
+## Returns:
+
+* pq\Result
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\RuntimeException
+* pq\Exception\DomainException
+
+## Example:
+
+ <?php
+ $c = new pq\Connection;
+
+ $result = $c->execParams("SELECT int($1) * s, int($2) * s, int($3) * s
+ FROM generate_series(1,3) s", array(1,2,3));
+
+ ?>
--- /dev/null
+# pq\Result pq\Connection::execParamsAsync(string $query, array $params[, array $types = NULL])
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) [execute an SQL query](pq/Connection: Executing Queries) with properly escaped parameters substituted.
+
+> ***NOTE***:
+ If pq\Connection::$unbuffered is TRUE, each call to pq\Connection::getResult() will generate a distinct pq\Result containing exactly one row.
+
+## Params:
+
+* string $query
+ The query to execute.
+* array $params
+ The parameter list to substitute.
+* Optional array $types = NULL
+ Corresponding list of type OIDs for the parameters.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\RuntimeException
+* pq\Exception\BadMethodCallException
+
--- /dev/null
+# pq\Result pq\Connection::getResult()
+
+Fetch the result of an [asynchronous](pq/Connection/: Asynchronous Usage) query.
+
+If the query hasn't finished yet, the call will block until the result is available.
+
+## Params:
+
+None.
+
+## Returns:
+
+* NULL, if there has not been a query
+* pq\Result, when the query has finished
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+
+## Example:
+
+ <?php
+
+ $conn = new pq\Connection;
+ $conn->execAsync("SELECT 1");
+
+ // ...
+
+ $result = $conn->getResult();
+
+ ?>
--- /dev/null
+# void pq\Connection::listen(string $channel, callable $listener)
+
+Listen on $channel for notifcations.
+See pq\Connection::unlisten().
+
+## Params:
+
+* string $channel
+ The channel to listen on.
+* callable $listener as function(string $channel, string $message, int $pid)
+ A callback automatically called whenever a notification on $channel arrives.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+## Example:
+
+ <?php
+
+ $conn = new pq\Connection;
+ $conn->listen("queue", function($channel, $message, $backend_pid) {
+ printf("Connection on backend %d said %s\n", $backend_pid, $message);
+ });
+
+ ?>
--- /dev/null
+# void pq\Connection::listenAsync(string $channel, callable $listener)
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) start listening on $channel for notifcations.
+See pq\Connection::listen().
+
+## Params:
+
+* string $channel
+ The channel to listen on.
+* callable $listener as function(string $channel, string $message, int $pid)
+ A callback automatically called whenever a notification on $channel arrives.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
--- /dev/null
+# void pq\Connection::notify(string $channel, string $message)
+
+Notify all listeners on $channel with $message.
+
+## Params:
+
+* string $channel
+ The channel to notify.
+* string $message
+ The message to send.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+## Example:
+
+ <?php
+
+ $conn = new pq\Connection;
+ $conn->notify("queue", "Hello World!");
+
+ ?>
--- /dev/null
+# void pq\Connection::notifyAsync(string $channel, string $message)
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) start notifying all listeners on $channel with $message.
+
+## Params:
+
+* string $channel
+ The channel to notify.
+* string $message
+ The message to send.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+## Example:
+
+ <?php
+
+ $conn = new pq\Connection;
+ $conn->notifyAsync("queue", "Hello World!");
+
+ ?>
--- /dev/null
+# bool pq\Connection::off(string $event)
+
+Stops listening for an event type.
+
+## Params:
+
+* string $event
+ Any pq\Connection::EVENT_*.
+
+## Returns:
+
+* bool, success.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
--- /dev/null
+# int pq\Connection::on(string $event, callable $callback)
+
+Listen for an event.
+
+## Params:
+
+* string $event
+ Any pq\Connection::EVENT_*.
+* callable $callback as function(pq\Connection $c[, pq\Result $r)
+ The callback to invoke on event.
+
+## Returns:
+
+* int, number of previously attached event listeners.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+
+## Example:
+
+ <?php
+
+ $connection = new pq\Connection;
+ $connection->on(pq\Connection::EVENT_RESULT, function($c, $r) {
+ printf("Got result with %d rows\n", $r->numRows);
+ });
+ $connection->exec("SELECT * FROM generate_series(1,3)");
+
+ ?>
+
+Yields:
+
+ Got result with 3 rows
--- /dev/null
+# int pq\Connection::poll()
+
+Poll an [asynchronously](pq/Connection/: Asynchronous Usage) operating connection.
+See pq\Connection::resetAsync() for an usage example.
+
+## Params:
+
+None.
+
+## Returns:
+
+ * int, pq\Connection::POLLING_* constant
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\RuntimeException
+* pq\Exception\BadMethodCallException
+
--- /dev/null
+# pq\Statement pq\Connection::prepare(string $name, string $query[, array $types = NULL])
+
+Prepare a named statement for later execution with pq\Statement::execute().
+
+## Params:
+
+* string $name
+ The identifying name of the prepared statement.
+* string $query
+ The query to prepare.
+* Optional array $types = NULL
+ An array of type OIDs for the substitution parameters.
+
+## Returns:
+
+* pq\Statement, a prepared statement instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+
+## Example:
+
+ <?php
+
+ $connection = new pq\Connection;
+
+ $statement = $connection->prepare(
+ "example",
+ "SELECT a from generate_series(1,9) a WHERE a > \$1",
+ [pq\Types::INT4]);
+ $result = $statement->exec([5]);
+
+ var_dump($result->fetchAllCols(0));
+
+ ?>
+
+Yields:
+
+ array(4) {
+ [0]=>
+ int(6)
+ [1]=>
+ int(7)
+ [2]=>
+ int(8)
+ [3]=>
+ int(9)
+ }
+
--- /dev/null
+# pq\Statement pq\Connection::prepareAsync(string $name, string $query[, array $types = NULL])
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) prepare a named statement for later execution with pq\Statement::exec().
+
+> ***NOTE***:
+ If pq\Connection::$unbuffered is TRUE, each call to pq\Connection::getResult() will generate a distinct pq\Result containing exactly one row.
+
+## Params:
+
+* string $name
+ The identifying name of the prepared statement.
+* string $query
+ The query to prepare.
+* Optional array $types = NULL
+ An array of type OIDs for the substitution parameters.
+
+## Returns:
+
+* pq\Statement, a prepared statement instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
--- /dev/null
+# string pq\Connection::quote(string $payload)
+
+Quote a string for safe use in a query.
+The result is truncated at any zero byte and wrapped in single quotes.
+
+> ***NOTE:***
+ Beware of matching character encodings.
+
+## Params:
+
+* string $payload
+ The payload to quote for use in a query.
+
+## Returns:
+
+* string, a single-quote wrapped string safe for literal use in a qurey.
+* FALSE, if quoting fails.
+
+# Throws:
+
+* pq\Exception\BadMethodCallException
--- /dev/null
+# string pq\Connection::quoteName(string $name)
+
+Quote an identifier for safe usage as name.
+
+> ***NOTE:***
+ Beware of case-sensitivity.
+
+## Params:
+
+* string $name
+ The name to quote.
+
+## Returns:
+
+* string, the quoted identifier.
+* FALSE, if quoting fails.
+
+## Throws:
+
+* pq\Exception\BadMethodCallException
--- /dev/null
+# void pq\Connection::reset()
+
+Attempt to reset a possibly broken connection to a working state.
+
+## Params:
+
+None.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+
+## Example:
+
+ <?php
+
+ if ($connection->status != pq\Connection::OK) {
+ $connection->reset();
+ }
+
+ ?>
--- /dev/null
+# void pq\Connection::resetAsync()
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) reset a possibly broken connection to a working state.
+
+## Params:
+
+None.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+
+## Example:
+
+ <?php
+
+ $c->resetAsync();
+
+ // wait until the stream becomes writable
+ $w = array($c->socket);
+ $r = $e = null;
+
+ if (stream_select($r, $w, $e, null)) {
+
+ // loop until the connection is established
+ while (true) {
+
+ switch ($c->poll()) {
+
+ case pq\Connection::POLLING_READING:
+ // we should wait for the stream to be read-ready
+ $r = array($c->socket);
+ stream_select($r, $w, $e, NULL);
+ break;
+
+ case pq\Connection::POLLING_WRITING:
+ // we should wait for the stream to be write-ready
+ $w = array($c->socket);
+ $r = $e = null;
+ stream_select($r, $w, $e, null);
+ break;
+
+ case pq\Connection::POLLING_FAILED:
+ printf("Connection failed: %s\n", $c->errorMessage);
+ break 2;
+
+ case pq\Connection::POLLING_OK:
+ printf("Connection completed\n");
+ break 2;
+ }
+ }
+
+ ?>
+
--- /dev/null
+# void pq\Connection::setConverter(pq\ConverterInterface $converter)
+
+Set a data type converter.
+
+## Params:
+
+* pq\ConverterInterface $converter
+ An instance implementing pq\ConverterInterface.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+
+## Example:
+
+ <?php
+
+ class HStoreConverter implements pq\ConverterInterface
+ {
+ private $oids;
+
+ function __construct(pq\Types $types) {
+ $this->oids = [$types["hstore"]->oid];
+ }
+
+ function convertTypes() {
+ return $this->oids;
+ }
+
+ function convertFromString($string) {
+ return eval("return [$string];");
+ }
+
+ function convertToString($data) {
+ $string = "";
+ foreach ($data as $k => $v) {
+ if (isset($v)) {
+ $string .= sprintf("\"%s\"=>\"%s\",", addslashes($k), addslashes($v));
+ } else {
+ $string .= sprintf("\"%s\"=>NULL,", addslashes($k));
+ }
+ }
+ return $string;
+ }
+ }
+ $connection = new pq\Connection;
+ $types = new pq\Types($connection);
+
+ $connection->setConverter(new HStoreConverter($types));
+
+ $result = $connection->execParams("SELECT \$1", [
+ [
+ "k1" => "v1",
+ "k2" => "v2",
+ "k3" => null
+ ]
+ ], [
+ $types["hstore"]->oid
+ ]);
+
+ var_dump(current($result->fetchAll()));
+
+ ?>
+
+Yields:
+
+ array(1) {
+ [0]=>
+ array(3) {
+ ["k1"]=>
+ string(2) "v1"
+ ["k2"]=>
+ string(2) "v2"
+ ["k3"]=>
+ NULL
+ }
+ }
--- /dev/null
+# pq\Transaction pq\Connection::startTransaction([int $isolation = pq\Transaction::READ_COMMITTED[, bool $readonly = FALSE[, bool $deferrable = FALSE]]])
+
+Begin a transaction.
+
+## Params:
+
+* Optional int $isolation = pq\Transaction::READ_COMMITTED
+ Any pq\Transaction isolation level constant
+ (defaults to pq\Connection::$defaultTransactionIsolation).
+* Optional bool $readonly = FALSE
+ Whether the transaction executes only reads
+ (defaults to pq\Connection::$defaultTransactionReadonly).
+* Optional bool $deferrable = FALSE
+ Whether the transaction is deferrable
+ (defaults to pq\Connection::$defaultTransactionDeferrable).
+
+> ***NOTE:***
+ A transaction can only be deferrable if it also is readonly and serializable.
+ See the official [PostgreSQL documentaion](http://www.postgresql.org/docs/current/static/sql-set-transaction.html) for further information.
+
+## Returns:
+
+* pq\Transaction, a begun transaction instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+
+## Example:
+
+ <?php
+
+ $transaction = (new pq\Connection)->startTransaction(
+ pq\Transaction::SERIALIZABLE, true, true);
+ $result = $transaction->connection->exec(
+ "SELECT * FROM generate_series(1,3)");
+
+ ?>
--- /dev/null
+# pq\Transaction pq\Connection::startTransactionAsync([int $isolation = pq\Transaction::READ_COMMITTED[, bool $readonly = FALSE[, bool $deferrable = FALSE]]])
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) begin a transaction.
+
+## Params:
+
+* Optional int $isolation = pq\Transaction::READ_COMMITTED
+ Any pq\Transaction isolation level constant
+ (defaults to pq\Connection::$defaultTransactionIsolation).
+* Optional bool $readonly = FALSE
+ Whether the transaction executes only reads
+ (defaults to pq\Connection::$defaultTransactionReadonly).
+* Optional bool $deferrable = FALSE
+ Whether the transaction is deferrable
+ (defaults to pq\Connection::$defaultTransactionDeferrable).
+
+> ***NOTE:***
+ A transaction can only be deferrable if it also is readonly and serializable.
+ See the official [PostgreSQL documentaion](http://www.postgresql.org/docs/current/static/sql-set-transaction.html) for further information.
+
+## Returns:
+
+* pq\Transaction, an asynchronously begun transaction instance.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
--- /dev/null
+# bool pq\Connection::trace([resource $stream])
+
+Trace protocol communication with the server.
+
+> ***NOTE:***
+ Calling pq\Connection::trace() without parameter or NULL stops tracing.
+
+## Params:
+
+* Optional resource $stream = NULL
+ The resource to which the protocol trace will be output.
+ (The stream must be castable to STDIO).
+
+## Returns:
+
+* bool, success.
+
+## Throws:
+
+* pq\Exception\BadMethodCallException
--- /dev/null
+# string pq\Connection::unescapeBytea(string $bytea)
+
+Unescape bytea data retrieved from the server.
+
+## Params:
+
+* string $bytea
+ Bytea data retrieved from the server.
+
+
+## Returns:
+
+* string, unescaped binary data.
+* FALSE, if unescaping fails.
+
+## Throws:
+
+* pq\Exception\BadMethodCallException
--- /dev/null
+# void pq\Connection::unlisten(string $channel)
+
+Stop listening for notifications on channel $channel.
+See pq\Connection::listen().
+
+## Params:
+
+* string $channel
+ The name of a channel which is currently listened on.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
+
+## Example:
+
+ <?php
+
+ $conn = new pq\Connection;
+ $conn->listen("foo", function($channel, $message, $backend_pid) {
+ printf("Got message '%s' on channel '%s' from backend %d\n",
+ $message, $channel, $backend_pid);
+ });
+
+ $conn->notify("foo", "bar");
+ $conn->unlisten("foo");
+
+ ?>
--- /dev/null
+# void pq\Connection::unlistenAsync(string $channel)
+
+[Asynchronously](pq/Connection/: Asynchronous Usage) stop listening for notifications on channel $channel.
+See pq\Connection::unlisten() and pq\Connection::listenAsync().
+
+## Params:
+
+* string $channel
+ The name of a channel which is currently listened on.
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException
+* pq\Exception\RuntimeException
+
--- /dev/null
+# void pq\Connection::unsetConverter(pq\ConverterInterface $converter)
+
+Stop applying a data type converter.
+
+## Params:
+
+* pq\ConverterInterface $converter
+ A converter previously set with pq\Connection::setConverter().
+
+## Throws:
+
+* pq\Exception\InvalidArgumentException
+* pq\Exception\BadMethodCallException