pq\Connection
authorMichael Wallner <mike@php.net>
Wed, 24 Sep 2014 16:01:29 +0000 (18:01 +0200)
committerMichael Wallner <mike@php.net>
Wed, 24 Sep 2014 16:01:29 +0000 (18:01 +0200)
35 files changed:
pq.md
pq/Connection.md
pq/Connection/: Asynchronous Usage.md [new file with mode: 0644]
pq/Connection/: Executing Queries.md [new file with mode: 0644]
pq/Connection/: General Usage.md [new file with mode: 0644]
pq/Connection/__construct.md
pq/Connection/declare.md [new file with mode: 0644]
pq/Connection/declareAsync.md [new file with mode: 0644]
pq/Connection/escapeBytea.md [new file with mode: 0644]
pq/Connection/exec.md [new file with mode: 0644]
pq/Connection/execAsync.md [new file with mode: 0644]
pq/Connection/execParams.md [new file with mode: 0644]
pq/Connection/execParamsAsync.md [new file with mode: 0644]
pq/Connection/getResult.md [new file with mode: 0644]
pq/Connection/listen.md [new file with mode: 0644]
pq/Connection/listenAsync.md [new file with mode: 0644]
pq/Connection/notify.md [new file with mode: 0644]
pq/Connection/notifyAsync.md [new file with mode: 0644]
pq/Connection/off.md [new file with mode: 0644]
pq/Connection/on.md [new file with mode: 0644]
pq/Connection/poll.md [new file with mode: 0644]
pq/Connection/prepare.md [new file with mode: 0644]
pq/Connection/prepareAsync.md [new file with mode: 0644]
pq/Connection/quote.md [new file with mode: 0644]
pq/Connection/quoteName.md [new file with mode: 0644]
pq/Connection/reset.md [new file with mode: 0644]
pq/Connection/resetAsync.md [new file with mode: 0644]
pq/Connection/setConverter.md [new file with mode: 0644]
pq/Connection/startTransaction.md [new file with mode: 0644]
pq/Connection/startTransactionAsync.md [new file with mode: 0644]
pq/Connection/trace.md [new file with mode: 0644]
pq/Connection/unescapeBytea.md [new file with mode: 0644]
pq/Connection/unlisten.md [new file with mode: 0644]
pq/Connection/unlistenAsync.md [new file with mode: 0644]
pq/Connection/unsetConverter.md [new file with mode: 0644]

diff --git a/pq.md b/pq.md
index 45d9faa1b8fe7a8ce58e8cc58734e4e9c5356db3..7abc9b181c6929f9381c617f9da6e846e40b63f2 100644 (file)
--- a/pq.md
+++ b/pq.md
@@ -2,7 +2,7 @@
 
 ## 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:
 
index 924e10414499c804710188b5381f7f70ebe94d8f..0bf2897511e99e28a8911148c823856237012a73 100644 (file)
@@ -1,6 +1,6 @@
 # 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.
 
@@ -19,7 +19,7 @@ Broken connection; consider pq\Connection::reset() or recreation.
 * 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  
@@ -71,21 +71,36 @@ Negotiating environment-driven parameter settings.
   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.
+  
diff --git a/pq/Connection/: Asynchronous Usage.md b/pq/Connection/: Asynchronous Usage.md
new file mode 100644 (file)
index 0000000..b19779b
--- /dev/null
@@ -0,0 +1,104 @@
+# 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.
diff --git a/pq/Connection/: Executing Queries.md b/pq/Connection/: Executing Queries.md
new file mode 100644 (file)
index 0000000..d603214
--- /dev/null
@@ -0,0 +1,57 @@
+# 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.
diff --git a/pq/Connection/: General Usage.md b/pq/Connection/: General Usage.md
new file mode 100644 (file)
index 0000000..0b282c5
--- /dev/null
@@ -0,0 +1,87 @@
+# 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
index 10d78d83e48b8b0a1a00e2535c7c739192d87e08..7890c93d170f5e1dbb5435c52b4115dbc5c33717 100644 (file)
@@ -4,9 +4,9 @@ Create a new PostgreSQL connection.
 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:
@@ -17,8 +17,6 @@ See also [General Usage](pq/Connection/: General Usage).
 
 ## Example:
 
-Creating a connection:
-
        <?php
 
        $connection = new pq\Connection("dbname=test user=test password=test",
diff --git a/pq/Connection/declare.md b/pq/Connection/declare.md
new file mode 100644 (file)
index 0000000..d8647d6
--- /dev/null
@@ -0,0 +1,57 @@
+# 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
diff --git a/pq/Connection/declareAsync.md b/pq/Connection/declareAsync.md
new file mode 100644 (file)
index 0000000..af80b52
--- /dev/null
@@ -0,0 +1,25 @@
+# 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
diff --git a/pq/Connection/escapeBytea.md b/pq/Connection/escapeBytea.md
new file mode 100644 (file)
index 0000000..6cb0a2a
--- /dev/null
@@ -0,0 +1,20 @@
+# 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
diff --git a/pq/Connection/exec.md b/pq/Connection/exec.md
new file mode 100644 (file)
index 0000000..54f6dd9
--- /dev/null
@@ -0,0 +1,33 @@
+# 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");
+       
+       ?>
diff --git a/pq/Connection/execAsync.md b/pq/Connection/execAsync.md
new file mode 100644 (file)
index 0000000..a002319
--- /dev/null
@@ -0,0 +1,31 @@
+# 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();
+       
+       ?>
diff --git a/pq/Connection/execParams.md b/pq/Connection/execParams.md
new file mode 100644 (file)
index 0000000..9d45720
--- /dev/null
@@ -0,0 +1,32 @@
+# 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));
+       
+       ?>
diff --git a/pq/Connection/execParamsAsync.md b/pq/Connection/execParamsAsync.md
new file mode 100644 (file)
index 0000000..24e57b0
--- /dev/null
@@ -0,0 +1,22 @@
+# 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
+
diff --git a/pq/Connection/getResult.md b/pq/Connection/getResult.md
new file mode 100644 (file)
index 0000000..afbf93e
--- /dev/null
@@ -0,0 +1,32 @@
+# 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();
+       
+       ?>
diff --git a/pq/Connection/listen.md b/pq/Connection/listen.md
new file mode 100644 (file)
index 0000000..66249a7
--- /dev/null
@@ -0,0 +1,28 @@
+# 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);
+       });
+       
+       ?>
diff --git a/pq/Connection/listenAsync.md b/pq/Connection/listenAsync.md
new file mode 100644 (file)
index 0000000..3e63d23
--- /dev/null
@@ -0,0 +1,17 @@
+# 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
diff --git a/pq/Connection/notify.md b/pq/Connection/notify.md
new file mode 100644 (file)
index 0000000..bf89f49
--- /dev/null
@@ -0,0 +1,25 @@
+# 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!");
+       
+       ?>
diff --git a/pq/Connection/notifyAsync.md b/pq/Connection/notifyAsync.md
new file mode 100644 (file)
index 0000000..7ce1b78
--- /dev/null
@@ -0,0 +1,25 @@
+# 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!");
+       
+       ?>
diff --git a/pq/Connection/off.md b/pq/Connection/off.md
new file mode 100644 (file)
index 0000000..fc0e228
--- /dev/null
@@ -0,0 +1,17 @@
+# 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
diff --git a/pq/Connection/on.md b/pq/Connection/on.md
new file mode 100644 (file)
index 0000000..cda9738
--- /dev/null
@@ -0,0 +1,34 @@
+# 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
diff --git a/pq/Connection/poll.md b/pq/Connection/poll.md
new file mode 100644 (file)
index 0000000..92e1ae1
--- /dev/null
@@ -0,0 +1,19 @@
+# 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
+
diff --git a/pq/Connection/prepare.md b/pq/Connection/prepare.md
new file mode 100644 (file)
index 0000000..ceaea70
--- /dev/null
@@ -0,0 +1,53 @@
+# 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)
+       }
+
diff --git a/pq/Connection/prepareAsync.md b/pq/Connection/prepareAsync.md
new file mode 100644 (file)
index 0000000..f74d024
--- /dev/null
@@ -0,0 +1,25 @@
+# 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
diff --git a/pq/Connection/quote.md b/pq/Connection/quote.md
new file mode 100644 (file)
index 0000000..4ede455
--- /dev/null
@@ -0,0 +1,21 @@
+# 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
diff --git a/pq/Connection/quoteName.md b/pq/Connection/quoteName.md
new file mode 100644 (file)
index 0000000..a981872
--- /dev/null
@@ -0,0 +1,20 @@
+# 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
diff --git a/pq/Connection/reset.md b/pq/Connection/reset.md
new file mode 100644 (file)
index 0000000..52d8ca8
--- /dev/null
@@ -0,0 +1,24 @@
+# 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();
+    }
+    
+    ?>
diff --git a/pq/Connection/resetAsync.md b/pq/Connection/resetAsync.md
new file mode 100644 (file)
index 0000000..8b1ff99
--- /dev/null
@@ -0,0 +1,57 @@
+# 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;
+               }
+       }
+       
+       ?>
+
diff --git a/pq/Connection/setConverter.md b/pq/Connection/setConverter.md
new file mode 100644 (file)
index 0000000..0c71405
--- /dev/null
@@ -0,0 +1,78 @@
+# 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
+               }
+         }
diff --git a/pq/Connection/startTransaction.md b/pq/Connection/startTransaction.md
new file mode 100644 (file)
index 0000000..4fd8d0f
--- /dev/null
@@ -0,0 +1,41 @@
+# 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)");
+       
+       ?>
diff --git a/pq/Connection/startTransactionAsync.md b/pq/Connection/startTransactionAsync.md
new file mode 100644 (file)
index 0000000..126d65d
--- /dev/null
@@ -0,0 +1,29 @@
+# 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
diff --git a/pq/Connection/trace.md b/pq/Connection/trace.md
new file mode 100644 (file)
index 0000000..8bb27f3
--- /dev/null
@@ -0,0 +1,20 @@
+# 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
diff --git a/pq/Connection/unescapeBytea.md b/pq/Connection/unescapeBytea.md
new file mode 100644 (file)
index 0000000..1e4bc54
--- /dev/null
@@ -0,0 +1,18 @@
+# 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
diff --git a/pq/Connection/unlisten.md b/pq/Connection/unlisten.md
new file mode 100644 (file)
index 0000000..081901e
--- /dev/null
@@ -0,0 +1,31 @@
+# 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");
+       
+       ?>
diff --git a/pq/Connection/unlistenAsync.md b/pq/Connection/unlistenAsync.md
new file mode 100644 (file)
index 0000000..f8ebfb1
--- /dev/null
@@ -0,0 +1,16 @@
+# 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
+
diff --git a/pq/Connection/unsetConverter.md b/pq/Connection/unsetConverter.md
new file mode 100644 (file)
index 0000000..9d2fb46
--- /dev/null
@@ -0,0 +1,13 @@
+# 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