summaryrefslogtreecommitdiff
path: root/ext/pdo_pgsql/tests
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_pgsql/tests')
-rw-r--r--ext/pdo_pgsql/tests/bug36727.phpt24
-rw-r--r--ext/pdo_pgsql/tests/bug43925.phpt59
-rw-r--r--ext/pdo_pgsql/tests/bug46274.phpt85
-rw-r--r--ext/pdo_pgsql/tests/bug46274_2.phpt91
-rw-r--r--ext/pdo_pgsql/tests/bug48764.phpt134
-rw-r--r--ext/pdo_pgsql/tests/bug61267.phpt22
-rw-r--r--ext/pdo_pgsql/tests/bug62593.phpt51
-rw-r--r--ext/pdo_pgsql/tests/bug_33876.phpt155
-rw-r--r--ext/pdo_pgsql/tests/bug_49985.phpt35
-rw-r--r--ext/pdo_pgsql/tests/common.phpt24
-rw-r--r--ext/pdo_pgsql/tests/config.inc14
-rw-r--r--ext/pdo_pgsql/tests/copy_from.phpt386
-rw-r--r--ext/pdo_pgsql/tests/copy_to.phpt129
-rw-r--r--ext/pdo_pgsql/tests/is_in_transaction.phpt66
-rw-r--r--ext/pdo_pgsql/tests/large_objects.phpt93
15 files changed, 1368 insertions, 0 deletions
diff --git a/ext/pdo_pgsql/tests/bug36727.phpt b/ext/pdo_pgsql/tests/bug36727.phpt
new file mode 100644
index 0000000..34d14db
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug36727.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #36727 (segfault in bindValue() when no parameters are defined)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+require dirname(__FILE__) . '/config.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+require dirname(__FILE__) . '/config.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$stmt = $db->prepare('SELECT * FROM child');
+var_dump($stmt->bindValue(':test', 1, PDO::PARAM_INT));
+
+echo "Done\n";
+?>
+--EXPECTF--
+Warning: PDOStatement::bindValue(): SQLSTATE[HY093]: Invalid parameter number: :test in %sbug36727.php on line %d
+bool(false)
+Done \ No newline at end of file
diff --git a/ext/pdo_pgsql/tests/bug43925.phpt b/ext/pdo_pgsql/tests/bug43925.phpt
new file mode 100644
index 0000000..e22ffba
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug43925.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Bug #43925 (Incorrect argument counter in prepared statements with pgsql)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$dbh = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+@$dbh->query('DROP TABLE nodes');
+
+$dbh->query('
+CREATE TABLE nodes
+(
+ id integer NOT NULL PRIMARY KEY
+ , root integer NOT NULL
+ , lft integer NOT NULL
+ , rgt integer NOT NULL
+);');
+
+$dbh->query('INSERT INTO nodes (id, root, lft, rgt) VALUES (1, 1, 1, 6);');
+$dbh->query('INSERT INTO nodes (id, root, lft, rgt) VALUES (2, 1, 2, 3);');
+$dbh->query('INSERT INTO nodes (id, root, lft, rgt) VALUES (3, 1, 4, 5);');
+
+
+$stmt = $dbh->prepare('
+ SELECT *
+ FROM nodes
+ WHERE (:rootId > 0 OR lft > :left OR rgt > :left)
+ AND (root = :rootId OR root = :left)
+ AND (1 > :left OR 1 < :left OR 1 = :left)
+ AND (:x > 0 OR :x < 10 OR :x > 100)
+ OR :y = 1 OR :left = 1
+');
+
+$stmt->bindValue('left', 1, PDO::PARAM_INT);
+$stmt->bindValue('rootId', 3, PDO::PARAM_INT);
+$stmt->bindValue('x', 5, PDO::PARAM_INT);
+$stmt->bindValue('y', 50, PDO::PARAM_INT);
+
+$stmt->execute();
+
+foreach ($stmt->fetchAll() as $row) {
+ print implode(' - ', $row);
+ print "\n";
+}
+
+$dbh->query('DROP TABLE nodes');
+
+?>
+--EXPECTF--
+1 - 1 - 1 - 1 - 1 - 1 - 6 - 6
+2 - 2 - 1 - 1 - 2 - 2 - 3 - 3
+3 - 3 - 1 - 1 - 4 - 4 - 5 - 5
diff --git a/ext/pdo_pgsql/tests/bug46274.phpt b/ext/pdo_pgsql/tests/bug46274.phpt
new file mode 100644
index 0000000..c34839a
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug46274.phpt
@@ -0,0 +1,85 @@
+--TEST--
+Bug #46274 (pdo_pgsql - Segfault when using PDO::ATTR_STRINGIFY_FETCHES and blob)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true);
+
+$db->query('CREATE TABLE test_one_blob (id SERIAL NOT NULL, blob1 BYTEA)');
+
+$stmt = $db->prepare("INSERT INTO test_one_blob (blob1) VALUES (:foo)");
+
+$data = 'foo';
+$blob = fopen('php://memory', 'a');
+fwrite($blob, $data);
+rewind($blob);
+
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$blob = '';
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$data = '';
+$blob = fopen('php://memory', 'a');
+fwrite($blob, $data);
+rewind($blob);
+
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$blob = NULL;
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$res = $db->query("SELECT blob1 from test_one_blob");
+// Resource
+var_dump($res->fetch());
+
+// Empty string
+var_dump($res->fetch());
+
+// Empty string
+var_dump($res->fetch());
+
+// NULL
+var_dump($res->fetch());
+
+$db->query('DROP TABLE test_one_blob');
+
+?>
+--EXPECTF--
+array(2) {
+ ["blob1"]=>
+ string(3) "foo"
+ [0]=>
+ string(3) "foo"
+}
+array(2) {
+ ["blob1"]=>
+ string(0) ""
+ [0]=>
+ string(0) ""
+}
+array(2) {
+ ["blob1"]=>
+ string(0) ""
+ [0]=>
+ string(0) ""
+}
+array(2) {
+ ["blob1"]=>
+ NULL
+ [0]=>
+ NULL
+}
diff --git a/ext/pdo_pgsql/tests/bug46274_2.phpt b/ext/pdo_pgsql/tests/bug46274_2.phpt
new file mode 100644
index 0000000..eb675af
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug46274_2.phpt
@@ -0,0 +1,91 @@
+--TEST--
+Bug #46274 (pdo_pgsql - Segfault when using PDO::ATTR_STRINGIFY_FETCHES and blob)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->query('CREATE TABLE test_one_blob (id SERIAL NOT NULL, blob1 BYTEA)');
+
+$stmt = $db->prepare("INSERT INTO test_one_blob (blob1) VALUES (:foo)");
+
+$data = 'foo';
+$blob = fopen('php://memory', 'a');
+fwrite($blob, $data);
+rewind($blob);
+
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$blob = '';
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$data = '';
+$blob = fopen('php://memory', 'a');
+fwrite($blob, $data);
+rewind($blob);
+
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$blob = NULL;
+$stmt->bindparam(':foo', $blob, PDO::PARAM_LOB);
+$stmt->execute();
+
+$res = $db->query("SELECT blob1 from test_one_blob");
+// Resource
+var_dump($x = $res->fetch());
+var_dump(fread($x['blob1'], 10));
+
+// Resource
+var_dump($res->fetch());
+var_dump(fread($x['blob1'], 10));
+
+// Resource
+var_dump($res->fetch());
+var_dump(fread($x['blob1'], 10));
+
+// NULL
+var_dump($res->fetch());
+
+$db->query('DROP TABLE test_one_blob');
+
+?>
+--EXPECTF--
+array(2) {
+ ["blob1"]=>
+ resource(%d) of type (stream)
+ [0]=>
+ resource(%d) of type (stream)
+}
+string(3) "foo"
+array(2) {
+ ["blob1"]=>
+ resource(%d) of type (stream)
+ [0]=>
+ resource(%d) of type (stream)
+}
+string(0) ""
+array(2) {
+ ["blob1"]=>
+ resource(%d) of type (stream)
+ [0]=>
+ resource(%d) of type (stream)
+}
+string(0) ""
+array(2) {
+ ["blob1"]=>
+ NULL
+ [0]=>
+ NULL
+}
diff --git a/ext/pdo_pgsql/tests/bug48764.phpt b/ext/pdo_pgsql/tests/bug48764.phpt
new file mode 100644
index 0000000..67e8f39
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug48764.phpt
@@ -0,0 +1,134 @@
+--TEST--
+Bug #48764 (PDO_pgsql::query always uses implicit prepared statements if v3 proto available)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+
+$db = PDOTest::factory();
+
+$client_version = $db->getAttribute(PDO::ATTR_CLIENT_VERSION);
+$server_version = $db->getAttribute(PDO::ATTR_SERVER_VERSION);
+
+if (version_compare($server_version, '7.4', '<') || version_compare($client_version, '7.4', '<')) {
+ die('skip');
+}
+
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+echo "Test 1\n";
+bug($db);
+
+echo "Test 2\n";
+bug($db, array(PDO::ATTR_EMULATE_PREPARES => 0));
+bug($db, array(PDO::ATTR_EMULATE_PREPARES => 1));
+
+echo "Test 3\n";
+bug($db, array(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 0));
+bug($db, array(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 1));
+
+echo "Test 4\n";
+$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
+bug($db);
+$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
+bug($db);
+
+echo "Test 5\n";
+$db->setAttribute(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 1);
+bug($db);
+$db->setAttribute(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0);
+bug($db);
+
+
+putenv('PDOTEST_ATTR='.serialize(array(
+ PDO::ATTR_EMULATE_PREPARES => 1,
+)));
+$db = PDOTest::factory('PDO', false);
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+echo "Test 6\n";
+bug($db);
+bug($db, array(PDO::ATTR_EMULATE_PREPARES => 0));
+bug($db, array(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 0));
+
+
+putenv('PDOTEST_ATTR='.serialize(array(
+ PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 1,
+)));
+
+$db = PDOTest::factory('PDO', false);
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+echo "Test 7\n";
+bug($db);
+bug($db, array(PDO::ATTR_EMULATE_PREPARES => 0));
+bug($db, array(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 0));
+
+
+putenv('PDOTEST_ATTR='.serialize(array(
+ PDO::ATTR_EMULATE_PREPARES => 1,
+ PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 1,
+)));
+
+$db = PDOTest::factory('PDO', false);
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+echo "Test 8\n";
+bug($db);
+bug($db, array(PDO::ATTR_EMULATE_PREPARES => 0));
+bug($db, array(PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 0));
+bug($db, array(
+ PDO::ATTR_EMULATE_PREPARES => 0,
+ PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => 0,
+));
+
+
+putenv('PDOTEST_ATTR');
+
+
+function bug($db, $options = array()) {
+ try {
+ $stmt = $db->prepare("SELECT ?", $options);
+ $stmt->execute(array(1));
+ echo "OK\n";
+ } catch (PDOException $e) {
+ // Indetermined data type when using native prepared statements
+ echo $e->getCode()."\n";
+ }
+}
+
+--EXPECT--
+Test 1
+42P18
+Test 2
+42P18
+OK
+Test 3
+42P18
+OK
+Test 4
+OK
+42P18
+Test 5
+OK
+42P18
+Test 6
+OK
+42P18
+OK
+Test 7
+OK
+OK
+42P18
+Test 8
+OK
+OK
+OK
+42P18
diff --git a/ext/pdo_pgsql/tests/bug61267.phpt b/ext/pdo_pgsql/tests/bug61267.phpt
new file mode 100644
index 0000000..4214cd9
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug61267.phpt
@@ -0,0 +1,22 @@
+--TEST--
+PDO::exec() returns 0 when the statement is a SELECT.
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+require_once dirname(__FILE__) . '/config.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+require_once dirname(__FILE__) . '/config.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$res = $db->exec('SELECT * from generate_series(1, 42);');
+var_dump($res);
+echo "Done\n";
+?>
+--EXPECTF--
+int(0)
+Done
diff --git a/ext/pdo_pgsql/tests/bug62593.phpt b/ext/pdo_pgsql/tests/bug62593.phpt
new file mode 100644
index 0000000..e3ebf46
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug62593.phpt
@@ -0,0 +1,51 @@
+--TEST--
+PDO PgSQL Bug #62593 (Emulate prepares behave strangely with PARAM_BOOL)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
+$errors = array();
+
+$value = true;
+$query = $db->prepare('SELECT :foo IS FALSE as val_is_false');
+$query->bindValue(':foo', $value, PDO::PARAM_BOOL);
+$query->execute();
+$errors[] = $query->errorInfo();
+var_dump($value);
+
+$query->bindValue(':foo', 0, PDO::PARAM_BOOL);
+$query->execute();
+$errors[] = $query->errorInfo();
+
+// Verify bindParam maintains reference and only passes when execute is called
+$value = true;
+$query->bindParam(':foo', $value, PDO::PARAM_BOOL);
+$value = false;
+$query->execute();
+$errors[] = $query->errorInfo();
+var_dump($value);
+
+$expect = 'No errors found';
+
+foreach ($errors as $error)
+{
+ if (strpos('Invalid text representation', $error[2]) !== false)
+ {
+ $expect = 'Invalid boolean found';
+ }
+}
+echo $expect;
+?>
+--EXPECTF--
+bool(true)
+bool(false)
+No errors found
diff --git a/ext/pdo_pgsql/tests/bug_33876.phpt b/ext/pdo_pgsql/tests/bug_33876.phpt
new file mode 100644
index 0000000..48618e1
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug_33876.phpt
@@ -0,0 +1,155 @@
+--TEST--
+PDO PgSQL Bug #33876 (PDO misquotes/miscasts bool(false))
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_SILENT);
+
+$db->exec("SET LC_MESSAGES='C'");
+$db->exec('CREATE TABLE test (foo varchar(5) NOT NULL, bar bool NOT NULL)');
+$db->exec("INSERT INTO test VALUES('false','f')");
+$db->exec("INSERT INTO test VALUES('true', 't')");
+
+$res = $db->prepare('SELECT foo from test where bar = ?');
+
+# this is the portable approach to binding a bool
+$res->bindValue(1, false, PDO::PARAM_BOOL);
+if (!$res->execute())
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+# this is the portable approach to binding a bool
+$res->bindValue(1, true, PDO::PARAM_BOOL);
+if (!$res->execute())
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+
+# true gets cast to string (because the implied default is string)
+# true-as-string is 1, so this "works"
+if (!$res->execute(array(true)))
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+# Expected to fail; unless told otherwise, PDO assumes string inputs
+# false -> "" as string, which pgsql doesn't like
+if (!$res->execute(array(false)))
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+# And now using emulator prepares
+echo "EMUL\n";
+
+
+$res = $db->prepare('SELECT foo from test where bar = ?', array(
+ PDO::PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT => true));
+
+# this is the portable approach to binding a bool
+$res->bindValue(1, false, PDO::PARAM_BOOL);
+if (!$res->execute())
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+# this is the portable approach to binding a bool
+$res->bindValue(1, true, PDO::PARAM_BOOL);
+if (!$res->execute())
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+
+# true gets cast to string (because the implied default is string)
+# true-as-string is 1, so this "works"
+if (!$res->execute(array(true)))
+ print_r($res->errorInfo());
+else
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+
+# Expected to fail; unless told otherwise, PDO assumes string inputs
+# false -> "" as string, which pgsql doesn't like
+if (!$res->execute(array(false))) {
+ $err = $res->errorInfo();
+ // Strip additional lines ouputted by recent PgSQL versions
+ $err[2] = trim(current(explode("\n", $err[2])));
+ print_r($err);
+} else {
+ print_r($res->fetchAll(PDO::FETCH_ASSOC));
+}
+
+
+
+--EXPECT--
+Array
+(
+ [0] => Array
+ (
+ [foo] => false
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [foo] => true
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [foo] => true
+ )
+
+)
+Array
+(
+ [0] => 22P02
+ [1] => 7
+ [2] => ERROR: invalid input syntax for type boolean: ""
+)
+EMUL
+Array
+(
+ [0] => Array
+ (
+ [foo] => false
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [foo] => true
+ )
+
+)
+Array
+(
+ [0] => Array
+ (
+ [foo] => true
+ )
+
+)
+Array
+(
+ [0] => 22P02
+ [1] => 7
+ [2] => ERROR: invalid input syntax for type boolean: ""
+)
diff --git a/ext/pdo_pgsql/tests/bug_49985.phpt b/ext/pdo_pgsql/tests/bug_49985.phpt
new file mode 100644
index 0000000..26dcfc6
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug_49985.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Bug #49985 (pdo_pgsql prepare() re-use previous aborted transaction)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+$db->exec("CREATE TABLE test (a int PRIMARY KEY)");
+
+for ($i = 0; $i < 3; $i++) {
+ try {
+ $db->beginTransaction();
+ $stmt = $db->prepare("INSERT INTO test (a) VALUES (?)");
+ var_dump($stmt->execute(array(1)));
+ $db->commit();
+ } catch (Exception $e) {
+ echo trim(current(explode("\n", $e->getMessage())))."\n";
+ $db->rollback();
+ }
+}
+
+?>
+--EXPECTF--
+bool(true)
+SQLSTATE[23505]: %s"test_pkey"
+SQLSTATE[23505]: %s"test_pkey"
+
diff --git a/ext/pdo_pgsql/tests/common.phpt b/ext/pdo_pgsql/tests/common.phpt
new file mode 100644
index 0000000..2ecc202
--- /dev/null
+++ b/ext/pdo_pgsql/tests/common.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Postgres
+--SKIPIF--
+<?php # vim:ft=php
+if (!extension_loaded('pdo_pgsql')) print 'skip'; ?>
+--REDIRECTTEST--
+# magic auto-configuration
+# Also update config.inc if you make changes here...
+
+$config = array(
+ 'TESTS' => 'ext/pdo/tests'
+);
+
+if (false !== getenv('PDO_PGSQL_TEST_DSN')) {
+ # user set them from their shell
+ $config['ENV']['PDOTEST_DSN'] = getenv('PDO_PGSQL_TEST_DSN');
+ if (false !== getenv('PDO_PGSQL_TEST_ATTR')) {
+ $config['ENV']['PDOTEST_ATTR'] = getenv('PDO_PGSQL_TEST_ATTR');
+ }
+} else {
+ $config['ENV']['PDOTEST_DSN'] = 'pgsql:host=localhost port=5432 dbname=test user=root password=';
+}
+
+return $config;
diff --git a/ext/pdo_pgsql/tests/config.inc b/ext/pdo_pgsql/tests/config.inc
new file mode 100644
index 0000000..6d616cd
--- /dev/null
+++ b/ext/pdo_pgsql/tests/config.inc
@@ -0,0 +1,14 @@
+<?php # vim:se ft=php:
+if (false !== getenv('PDO_PGSQL_TEST_DSN')) {
+ # user set them from their shell
+ $config['ENV']['PDOTEST_DSN'] = getenv('PDO_PGSQL_TEST_DSN');
+ if (false !== getenv('PDO_PGSQL_TEST_ATTR')) {
+ $config['ENV']['PDOTEST_ATTR'] = getenv('PDO_PGSQL_TEST_ATTR');
+ }
+} else {
+ $config['ENV']['PDOTEST_DSN'] = 'pgsql:host=localhost port=5432 dbname=test user=root password=';
+}
+
+foreach ($config['ENV'] as $k => $v) {
+ putenv("$k=$v");
+}
diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt
new file mode 100644
index 0000000..2858905
--- /dev/null
+++ b/ext/pdo_pgsql/tests/copy_from.phpt
@@ -0,0 +1,386 @@
+--TEST--
+PDO PgSQL pgsqlCopyFromArray and pgsqlCopyFromFile
+--SKIPIF--
+<?php # vim:se ft=php:
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->exec('CREATE TABLE test (a integer not null primary key, b text, c integer)');
+
+try {
+
+echo "Preparing test file and array for CopyFrom tests\n";
+
+$tableRows = array();
+$tableRowsWithDifferentNullValues = array();
+
+for($i=0;$i<3;$i++) {
+ $firstParameter = $i;
+ $secondParameter = "test insert {$i}";
+ $tableRows[] = "{$firstParameter}\t{$secondParameter}\t\\N";
+ $tableRowsWithDifferentNullValues[] = "{$firstParameter};{$secondParameter};NULL";
+ $tableRowsWithDifferentNullValuesAndSelectedFields[] = "{$firstParameter};NULL";
+}
+$filename = 'test_pgsqlCopyFromFile.csv';
+$filenameWithDifferentNullValues = 'test_pgsqlCopyFromFileWithDifferentNullValues.csv';
+$filenameWithDifferentNullValuesAndSelectedFields = 'test_pgsqlCopyFromFileWithDifferentNullValuesAndSelectedFields.csv';
+
+file_put_contents($filename, implode("\n",$tableRows));
+file_put_contents($filenameWithDifferentNullValues, implode("\n",$tableRowsWithDifferentNullValues));
+file_put_contents($filenameWithDifferentNullValuesAndSelectedFields, implode("\n",$tableRowsWithDifferentNullValuesAndSelectedFields));
+
+echo "Testing pgsqlCopyFromArray() with default parameters\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromArray('test',$tableRows));
+
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromArray() with different field separator and not null indicator\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromArray('test',$tableRowsWithDifferentNullValues,";","NULL"));
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromArray() with only selected fields\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromArray('test',$tableRowsWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c'));
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromArray() with error\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromArray('test_error',$tableRowsWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c'));
+$db->rollback();
+
+
+echo "Testing pgsqlCopyFromFile() with default parameters\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromFile('test',$filename));
+
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromFile() with different field separator and not null indicator\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromFile('test',$filenameWithDifferentNullValues,";","NULL"));
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromFile() with only selected fields\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromFile('test',$filenameWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c'));
+$stmt = $db->query("select * from test");
+foreach($stmt as $r) {
+ var_dump($r);
+}
+$db->rollback();
+
+echo "Testing pgsqlCopyFromFile() with error\n";
+$db->beginTransaction();
+var_dump($db->pgsqlCopyFromFile('test_error',$filenameWithDifferentNullValuesAndSelectedFields,";","NULL",'a,c'));
+$db->rollback();
+
+} catch (Exception $e) {
+ /* catch exceptions so that we can show the relative error */
+ echo "Exception! at line ", $e->getLine(), "\n";
+ var_dump($e->getMessage());
+}
+if(isset($filename)) {
+ @unlink($filename);
+}
+?>
+--EXPECT--
+Preparing test file and array for CopyFrom tests
+Testing pgsqlCopyFromArray() with default parameters
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ string(13) "test insert 0"
+ [1]=>
+ string(13) "test insert 0"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ string(13) "test insert 1"
+ [1]=>
+ string(13) "test insert 1"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ string(13) "test insert 2"
+ [1]=>
+ string(13) "test insert 2"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromArray() with different field separator and not null indicator
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ string(13) "test insert 0"
+ [1]=>
+ string(13) "test insert 0"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ string(13) "test insert 1"
+ [1]=>
+ string(13) "test insert 1"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ string(13) "test insert 2"
+ [1]=>
+ string(13) "test insert 2"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromArray() with only selected fields
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromArray() with error
+bool(false)
+Testing pgsqlCopyFromFile() with default parameters
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ string(13) "test insert 0"
+ [1]=>
+ string(13) "test insert 0"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ string(13) "test insert 1"
+ [1]=>
+ string(13) "test insert 1"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ string(13) "test insert 2"
+ [1]=>
+ string(13) "test insert 2"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromFile() with different field separator and not null indicator
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ string(13) "test insert 0"
+ [1]=>
+ string(13) "test insert 0"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ string(13) "test insert 1"
+ [1]=>
+ string(13) "test insert 1"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ string(13) "test insert 2"
+ [1]=>
+ string(13) "test insert 2"
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromFile() with only selected fields
+bool(true)
+array(6) {
+ ["a"]=>
+ int(0)
+ [0]=>
+ int(0)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(1)
+ [0]=>
+ int(1)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+array(6) {
+ ["a"]=>
+ int(2)
+ [0]=>
+ int(2)
+ ["b"]=>
+ NULL
+ [1]=>
+ NULL
+ ["c"]=>
+ NULL
+ [2]=>
+ NULL
+}
+Testing pgsqlCopyFromFile() with error
+bool(false) \ No newline at end of file
diff --git a/ext/pdo_pgsql/tests/copy_to.phpt b/ext/pdo_pgsql/tests/copy_to.phpt
new file mode 100644
index 0000000..1dc7d1d
--- /dev/null
+++ b/ext/pdo_pgsql/tests/copy_to.phpt
@@ -0,0 +1,129 @@
+--TEST--
+PDO PgSQL pgsqlCopyToArray and pgsqlCopyToFile
+--SKIPIF--
+<?php # vim:se ft=php:
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->exec('CREATE TABLE test (a integer not null primary key, b text, c integer)');
+
+$db->beginTransaction();
+try {
+
+echo "Preparing test table for CopyTo tests\n";
+$stmt = $db->prepare("INSERT INTO test (a, b, c) values (?, ?, ?)");
+
+for($i=0;$i<3;$i++) {
+ $firstParameter = $i;
+ $secondParameter = "test insert {$i}";
+ $thirdParameter = NULL;
+ $stmt->bindValue(1, $firstParameter);
+ $stmt->bindValue(2, $secondParameter);
+ $stmt->bindValue(3, $thirdParameter);
+ $stmt->execute();
+}
+
+$db->commit();
+
+echo "Testing pgsqlCopyToArray() with default parameters\n";
+var_dump($db->pgsqlCopyToArray('test'));
+echo "Testing pgsqlCopyToArray() with different field separator and not null indicator\n";
+var_dump($db->pgsqlCopyToArray('test',";","NULL"));
+echo "Testing pgsqlCopyToArray() with only selected fields\n";
+var_dump($db->pgsqlCopyToArray('test',";","NULL",'a,c'));
+
+echo "Testing pgsqlCopyToArray() with error\n";
+var_dump($db->pgsqlCopyToArray('test_error'));
+
+
+echo "Testing pgsqlCopyToFile() with default parameters\n";
+
+$filename="test_pgsqlCopyToFile.csv";
+var_dump($db->pgsqlCopyToFile('test',$filename));
+echo file_get_contents($filename);
+echo "Testing pgsqlCopyToFile() with different field separator and not null indicator\n";
+var_dump($db->pgsqlCopyToFile('test',$filename,";","NULL"));
+echo file_get_contents($filename);
+echo "Testing pgsqlCopyToFile() with only selected fields\n";
+var_dump($db->pgsqlCopyToFile('test',$filename,";","NULL",'a,c'));
+echo file_get_contents($filename);
+
+echo "Testing pgsqlCopyToFile() with error\n";
+var_dump($db->pgsqlCopyToFile('test_error',$filename));
+
+
+} catch (Exception $e) {
+ /* catch exceptions so that we can show the relative error */
+ echo "Exception! at line ", $e->getLine(), "\n";
+ var_dump($e->getMessage());
+}
+if(isset($filename)) {
+ @unlink($filename);
+}
+?>
+--EXPECT--
+Preparing test table for CopyTo tests
+Testing pgsqlCopyToArray() with default parameters
+array(3) {
+ [0]=>
+ string(19) "0 test insert 0 \N
+"
+ [1]=>
+ string(19) "1 test insert 1 \N
+"
+ [2]=>
+ string(19) "2 test insert 2 \N
+"
+}
+Testing pgsqlCopyToArray() with different field separator and not null indicator
+array(3) {
+ [0]=>
+ string(21) "0;test insert 0;NULL
+"
+ [1]=>
+ string(21) "1;test insert 1;NULL
+"
+ [2]=>
+ string(21) "2;test insert 2;NULL
+"
+}
+Testing pgsqlCopyToArray() with only selected fields
+array(3) {
+ [0]=>
+ string(7) "0;NULL
+"
+ [1]=>
+ string(7) "1;NULL
+"
+ [2]=>
+ string(7) "2;NULL
+"
+}
+Testing pgsqlCopyToArray() with error
+bool(false)
+Testing pgsqlCopyToFile() with default parameters
+bool(true)
+0 test insert 0 \N
+1 test insert 1 \N
+2 test insert 2 \N
+Testing pgsqlCopyToFile() with different field separator and not null indicator
+bool(true)
+0;test insert 0;NULL
+1;test insert 1;NULL
+2;test insert 2;NULL
+Testing pgsqlCopyToFile() with only selected fields
+bool(true)
+0;NULL
+1;NULL
+2;NULL
+Testing pgsqlCopyToFile() with error
+bool(false) \ No newline at end of file
diff --git a/ext/pdo_pgsql/tests/is_in_transaction.phpt b/ext/pdo_pgsql/tests/is_in_transaction.phpt
new file mode 100644
index 0000000..99ff561
--- /dev/null
+++ b/ext/pdo_pgsql/tests/is_in_transaction.phpt
@@ -0,0 +1,66 @@
+--TEST--
+PDO PgSQL isInTransaction
+--SKIPIF--
+<?php # vim:se ft=php:
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->exec('CREATE TABLE test (a integer not null primary key, b text)');
+
+$db->beginTransaction();
+try {
+echo "Test PDO::PGSQL_TRANSACTION_INTRANS\n";
+var_dump($db->inTransaction());
+
+$stmt = $db->prepare("INSERT INTO test (a, b) values (?, ?)");
+$stmt->bindValue(1, 1);
+$stmt->bindValue(2, "test insert");
+$stmt->execute();
+
+$db->commit();
+
+echo "Test PDO::PGSQL_TRANSACTION_IDLE\n";
+var_dump($db->inTransaction());
+
+$db->beginTransaction();
+
+try {
+$stmt = $db->prepare("INSERT INTO test (a, b) values (?, ?)");
+$stmt->bindValue(1, "error");
+$stmt->bindValue(2, "test insert");
+$stmt->execute();
+} catch (Exception $e) {
+ /* We catch the exception because the execute will give error and we must test the PDO::PGSQL_TRANSACTION_ERROR */
+ echo "Test PDO::PGSQL_TRANSACTION_INERROR\n";
+ var_dump($db->inTransaction());
+ $db->rollBack();
+}
+
+echo "Test PDO::PGSQL_TRANSACTION_IDLE\n";
+var_dump($db->inTransaction());
+
+} catch (Exception $e) {
+ /* catch exceptions so that we can show the relative error */
+ echo "Exception! at line ", $e->getLine(), "\n";
+ var_dump($e->getMessage());
+}
+
+?>
+--EXPECT--
+Test PDO::PGSQL_TRANSACTION_INTRANS
+int(2)
+Test PDO::PGSQL_TRANSACTION_IDLE
+int(0)
+Test PDO::PGSQL_TRANSACTION_INERROR
+int(3)
+Test PDO::PGSQL_TRANSACTION_IDLE
+int(0)
diff --git a/ext/pdo_pgsql/tests/large_objects.phpt b/ext/pdo_pgsql/tests/large_objects.phpt
new file mode 100644
index 0000000..316963a
--- /dev/null
+++ b/ext/pdo_pgsql/tests/large_objects.phpt
@@ -0,0 +1,93 @@
+--TEST--
+PDO PgSQL Large Objects
+--SKIPIF--
+<?php # vim:se ft=php:
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false);
+
+$db->exec('CREATE TABLE test (blobid integer not null primary key, bloboid OID)');
+
+$db->beginTransaction();
+$oid = $db->pgsqlLOBCreate();
+try {
+$stm = $db->pgsqlLOBOpen($oid, 'w+b');
+fwrite($stm, "Hello dude\n");
+
+$stmt = $db->prepare("INSERT INTO test (blobid, bloboid) values (?, ?)");
+$stmt->bindValue(1, 1);
+/* bind as LOB; the oid from the pgsql stream will be inserted instead
+ * of the stream contents. Binding other streams will attempt to bind
+ * as bytea, and will most likely lead to an error.
+ * You can also just bind the $oid in as a string. */
+$stmt->bindParam(2, $stm, PDO::PARAM_LOB);
+$stmt->execute();
+$stm = null;
+
+/* Pull it out */
+$stmt = $db->prepare("SELECT * from test");
+$stmt->bindColumn('bloboid', $lob, PDO::PARAM_LOB);
+$stmt->execute();
+echo "Fetching:\n";
+while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
+ var_dump($row['blobid']);
+ var_dump(stream_get_contents($lob));
+}
+echo "Fetched!\n";
+
+/* Try again, with late bind */
+$stmt = $db->prepare("SELECT * from test");
+$stmt->execute();
+$stmt->bindColumn('bloboid', $lob, PDO::PARAM_LOB);
+echo "Fetching late bind:\n";
+while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
+ var_dump($row['blobid']);
+ var_dump(is_int($row['bloboid']));
+}
+echo "Fetched!\n";
+
+/* Try again, with NO bind */
+$stmt = $db->prepare("SELECT * from test");
+$stmt->execute();
+$stmt->bindColumn('bloboid', $lob, PDO::PARAM_LOB);
+echo "Fetching NO bind:\n";
+while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
+ var_dump($row['blobid']);
+ var_dump(is_int($row['bloboid']));
+}
+echo "Fetched!\n";
+
+} catch (Exception $e) {
+ /* catch exceptions so that we can guarantee to clean
+ * up the LOB */
+ echo "Exception! at line ", $e->getLine(), "\n";
+ var_dump($e->getMessage());
+}
+
+/* Now to remove the large object from the database, so it doesn't
+ * linger and clutter up the storage */
+$db->pgsqlLOBUnlink($oid);
+
+?>
+--EXPECT--
+Fetching:
+int(1)
+string(11) "Hello dude
+"
+Fetched!
+Fetching late bind:
+int(1)
+bool(true)
+Fetched!
+Fetching NO bind:
+int(1)
+bool(true)
+Fetched!