summaryrefslogtreecommitdiff
path: root/ext/pdo_pgsql
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pdo_pgsql')
-rw-r--r--ext/pdo_pgsql/pdo_pgsql.c10
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c372
-rw-r--r--ext/pdo_pgsql/php_pdo_pgsql_int.h9
-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
6 files changed, 967 insertions, 5 deletions
diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c
index 1be19cef7..5b3bff589 100644
--- a/ext/pdo_pgsql/pdo_pgsql.c
+++ b/ext/pdo_pgsql/pdo_pgsql.c
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: pdo_pgsql.c 293036 2010-01-03 09:23:27Z sebastian $ */
+/* $Id: pdo_pgsql.c 300351 2010-06-10 12:11:19Z iliaa $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -86,6 +86,12 @@ ZEND_GET_MODULE(pdo_pgsql)
PHP_MINIT_FUNCTION(pdo_pgsql)
{
REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
+ REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_IDLE", (long)PGSQL_TRANSACTION_IDLE);
+ REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_ACTIVE", (long)PGSQL_TRANSACTION_ACTIVE);
+ REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INTRANS", (long)PGSQL_TRANSACTION_INTRANS);
+ REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_INERROR", (long)PGSQL_TRANSACTION_INERROR);
+ REGISTER_PDO_CLASS_CONST_LONG("PGSQL_TRANSACTION_UNKNOWN", (long)PGSQL_TRANSACTION_UNKNOWN);
+
php_pdo_register_driver(&pdo_pgsql_driver);
return SUCCESS;
}
@@ -128,7 +134,7 @@ PHP_MINFO_FUNCTION(pdo_pgsql)
php_info_print_table_row(2, "PostgreSQL(libpq) Version", PG_VERSION);
#endif
php_info_print_table_row(2, "Module version", pdo_pgsql_module_entry.version);
- php_info_print_table_row(2, "Revision", " $Id: pdo_pgsql.c 293036 2010-01-03 09:23:27Z sebastian $ ");
+ php_info_print_table_row(2, "Revision", " $Id: pdo_pgsql.c 300351 2010-06-10 12:11:19Z iliaa $ ");
php_info_print_table_end();
}
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index 32fd472e9..0720ce6b0 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: pgsql_driver.c 294444 2010-02-03 19:48:04Z pajoye $ */
+/* $Id: pgsql_driver.c 300464 2010-06-15 11:13:20Z iliaa $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -29,6 +29,7 @@
#include "ext/standard/info.h"
#include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h"
+#include "ext/standard/file.h"
#undef PACKAGE_BUGREPORT
#undef PACKAGE_NAME
@@ -496,6 +497,368 @@ static int pgsql_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
return pdo_pgsql_transaction_cmd("ROLLBACK", dbh TSRMLS_CC);
}
+/* {{{ proto string PDO::pgsqlCopyFromArray(string $table_name , array $rows [, string $delimiter [, string $null_as ] [, string $fields])
+ Returns true if the copy worked fine or false if error */
+static PHP_METHOD(PDO, pgsqlCopyFromArray)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+
+ zval *pg_rows;
+
+ char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
+ int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
+ char *query;
+
+ PGresult *pgsql_result;
+ ExecStatusType status;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s/a|sss",
+ &table_name, &table_name_len, &pg_rows,
+ &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
+ return;
+ }
+
+ if (!zend_hash_num_elements(Z_ARRVAL_P(pg_rows))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot copy from an empty array");
+ RETURN_FALSE;
+ }
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ if (pg_fields) {
+ spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ } else {
+ spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ }
+
+ // Obtain db Handle
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+ pgsql_result = PQexec(H->server, query);
+
+ efree(query);
+ query = NULL;
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(H->server);
+ }
+
+ if (status == PGRES_COPY_IN && pgsql_result) {
+ int command_failed = 0;
+ int buffer_len = 0;
+ zval **tmp;
+ HashPosition pos;
+
+ PQclear(pgsql_result);
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(pg_rows), &pos);
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(pg_rows), (void **) &tmp, &pos) == SUCCESS) {
+ int query_len;
+ convert_to_string_ex(tmp);
+
+ if (buffer_len < Z_STRLEN_PP(tmp)) {
+ buffer_len = Z_STRLEN_PP(tmp);
+ query = erealloc(query, buffer_len + 2); /* room for \n\0 */
+ }
+ memcpy(query, Z_STRVAL_PP(tmp), Z_STRLEN_PP(tmp));
+ query_len = Z_STRLEN_PP(tmp);
+ if (query[query_len - 1] != '\n') {
+ query[query_len++] = '\n';
+ }
+ query[query_len] = '\0';
+ if (PQputCopyData(H->server, query, query_len) != 1) {
+ efree(query);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed");
+ RETURN_FALSE;
+ }
+ zend_hash_move_forward_ex(Z_ARRVAL_P(pg_rows), &pos);
+ }
+ if (query) {
+ efree(query);
+ }
+
+ if (PQputCopyEnd(H->server, NULL) != 1) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed");
+ RETURN_FALSE;
+ }
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ command_failed = 1;
+ }
+ PQclear(pgsql_result);
+ }
+
+ RETURN_BOOL(!command_failed);
+ } else {
+ PQclear(pgsql_result);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string PDO::pgsqlCopyFromFile(string $table_name , string $filename [, string $delimiter [, string $null_as ] [, string $fields])
+ Returns true if the copy worked fine or false if error */
+static PHP_METHOD(PDO, pgsqlCopyFromFile)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+
+ char *table_name, *filename, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
+ int table_name_len, filename_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
+ char *query;
+ PGresult *pgsql_result;
+ ExecStatusType status;
+ php_stream *stream;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
+ &table_name, &table_name_len, &filename, &filename_len,
+ &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
+ return;
+ }
+
+ // Obtain db Handler
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ stream = php_stream_open_wrapper_ex(filename, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context));
+ if (!stream) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file");
+ RETURN_FALSE;
+ }
+
+ if (pg_fields) {
+ spprintf(&query, 0, "COPY %s (%s) FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ } else {
+ spprintf(&query, 0, "COPY %s FROM STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ }
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+ pgsql_result = PQexec(H->server, query);
+
+ efree(query);
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(H->server);
+ }
+
+ if (status == PGRES_COPY_IN && pgsql_result) {
+ char *buf;
+ int command_failed = 0;
+ size_t line_len = 0;
+
+ PQclear(pgsql_result);
+ while ((buf = php_stream_get_line(stream, NULL, 0, &line_len)) != NULL) {
+ if (PQputCopyData(H->server, buf, line_len) != 1) {
+ efree(buf);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "copy failed");
+ php_stream_close(stream);
+ RETURN_FALSE;
+ }
+ efree(buf);
+ }
+ php_stream_close(stream);
+
+ if (PQputCopyEnd(H->server, NULL) != 1) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "putcopyend failed");
+ RETURN_FALSE;
+ }
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ if (PGRES_COMMAND_OK != PQresultStatus(pgsql_result)) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ command_failed = 1;
+ }
+ PQclear(pgsql_result);
+ }
+
+ RETURN_BOOL(!command_failed);
+ } else {
+ PQclear(pgsql_result);
+ php_stream_close(stream);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+
+/* {{{ proto string PDO::pgsqlCopyToFile(string $table_name , $filename, [string $delimiter [, string $null_as [, string $fields]]])
+ Returns true if the copy worked fine or false if error */
+static PHP_METHOD(PDO, pgsqlCopyToFile)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+
+ char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL, *filename = NULL;
+ int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len, filename_len;
+ char *query;
+
+ PGresult *pgsql_result;
+ ExecStatusType status;
+
+ php_stream *stream;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|sss",
+ &table_name, &table_name_len, &filename, &filename_len,
+ &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
+ return;
+ }
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ stream = php_stream_open_wrapper_ex(filename, "wb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, FG(default_context));
+ if (!stream) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to open the file for writing");
+ RETURN_FALSE;
+ }
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+
+ if (pg_fields) {
+ spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ } else {
+ spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ }
+ pgsql_result = PQexec(H->server, query);
+ efree(query);
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(H->server);
+ }
+
+ if (status == PGRES_COPY_OUT && pgsql_result) {
+ PQclear(pgsql_result);
+ while (1) {
+ char *csv = NULL;
+ int ret = PQgetCopyData(H->server, &csv, 0);
+
+ if (ret == -1) {
+ break; /* done */
+ } else if (ret > 0) {
+ if (php_stream_write(stream, csv, ret) != ret) {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Unable to write to file");
+ PQfreemem(csv);
+ php_stream_close(stream);
+ RETURN_FALSE;
+ } else {
+ PQfreemem(csv);
+ }
+ } else {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed");
+ php_stream_close(stream);
+ RETURN_FALSE;
+ }
+ }
+ php_stream_close(stream);
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+ RETURN_TRUE;
+ } else {
+ php_stream_close(stream);
+ PQclear(pgsql_result);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string PDO::pgsqlCopyToArray(string $table_name , [string $delimiter [, string $null_as [, string $fields]]])
+ Returns true if the copy worked fine or false if error */
+static PHP_METHOD(PDO, pgsqlCopyToArray)
+{
+ pdo_dbh_t *dbh;
+ pdo_pgsql_db_handle *H;
+
+ char *table_name, *pg_delim = NULL, *pg_null_as = NULL, *pg_fields = NULL;
+ int table_name_len, pg_delim_len = 0, pg_null_as_len = 0, pg_fields_len;
+ char *query;
+
+ PGresult *pgsql_result;
+ ExecStatusType status;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sss",
+ &table_name, &table_name_len,
+ &pg_delim, &pg_delim_len, &pg_null_as, &pg_null_as_len, &pg_fields, &pg_fields_len) == FAILURE) {
+ return;
+ }
+
+ dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
+ PDO_CONSTRUCT_CHECK;
+
+ H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+
+ if (pg_fields) {
+ spprintf(&query, 0, "COPY %s (%s) TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, pg_fields, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ } else {
+ spprintf(&query, 0, "COPY %s TO STDIN DELIMITERS E'%c' WITH NULL AS E'%s'", table_name, (pg_delim_len ? *pg_delim : '\t'), (pg_null_as_len ? pg_null_as : "\\\\N"));
+ }
+ pgsql_result = PQexec(H->server, query);
+ efree(query);
+
+ if (pgsql_result) {
+ status = PQresultStatus(pgsql_result);
+ } else {
+ status = (ExecStatusType) PQstatus(H->server);
+ }
+
+ if (status == PGRES_COPY_OUT && pgsql_result) {
+ PQclear(pgsql_result);
+ array_init(return_value);
+
+ while (1) {
+ char *csv = NULL;
+ int ret = PQgetCopyData(H->server, &csv, 0);
+ if (ret == -1) {
+ break; /* copy done */
+ } else if (ret > 0) {
+ add_next_index_stringl(return_value, csv, ret, 1);
+ PQfreemem(csv);
+ } else {
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed: getline failed");
+ RETURN_FALSE;
+ }
+ }
+
+ while ((pgsql_result = PQgetResult(H->server))) {
+ PQclear(pgsql_result);
+ }
+ } else {
+ PQclear(pgsql_result);
+ pdo_pgsql_error(dbh, PGRES_FATAL_ERROR, "Copy command failed");
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+
/* {{{ proto string PDO::pgsqlLOBCreate()
Creates a new large object, returning its identifier. Must be called inside a transaction. */
static PHP_METHOD(PDO, pgsqlLOBCreate)
@@ -608,6 +971,10 @@ static const zend_function_entry dbh_methods[] = {
PHP_ME(PDO, pgsqlLOBCreate, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, pgsqlLOBOpen, NULL, ZEND_ACC_PUBLIC)
PHP_ME(PDO, pgsqlLOBUnlink, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlCopyFromArray, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlCopyFromFile, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlCopyToArray, NULL, ZEND_ACC_PUBLIC)
+ PHP_ME(PDO, pgsqlCopyToFile, NULL, ZEND_ACC_PUBLIC)
{NULL, NULL, NULL}
};
@@ -653,7 +1020,8 @@ static struct pdo_dbh_methods pgsql_methods = {
pdo_pgsql_fetch_error_func,
pdo_pgsql_get_attribute,
pdo_pgsql_check_liveness, /* check_liveness */
- pdo_pgsql_get_driver_methods /* get_driver_methods */
+ pdo_pgsql_get_driver_methods, /* get_driver_methods */
+ NULL,
};
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
diff --git a/ext/pdo_pgsql/php_pdo_pgsql_int.h b/ext/pdo_pgsql/php_pdo_pgsql_int.h
index a9c686ba1..8cdfe1291 100644
--- a/ext/pdo_pgsql/php_pdo_pgsql_int.h
+++ b/ext/pdo_pgsql/php_pdo_pgsql_int.h
@@ -18,7 +18,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_pdo_pgsql_int.h 293036 2010-01-03 09:23:27Z sebastian $ */
+/* $Id: php_pdo_pgsql_int.h 300351 2010-06-10 12:11:19Z iliaa $ */
#ifndef PHP_PDO_PGSQL_INT_H
#define PHP_PDO_PGSQL_INT_H
@@ -102,6 +102,13 @@ struct pdo_pgsql_lob_self {
Oid oid;
};
+enum pdo_pgsql_specific_constants {
+ PGSQL_TRANSACTION_IDLE = PQTRANS_IDLE,
+ PGSQL_TRANSACTION_ACTIVE = PQTRANS_ACTIVE,
+ PGSQL_TRANSACTION_INTRANS = PQTRANS_INTRANS,
+ PGSQL_TRANSACTION_INERROR = PQTRANS_INERROR,
+ PGSQL_TRANSACTION_UNKNOWN = PQTRANS_UNKNOWN
+};
php_stream *pdo_pgsql_create_lob_stream(pdo_dbh_t *stmt, int lfd, Oid oid TSRMLS_DC);
extern php_stream_ops pdo_pgsql_lob_stream_ops;
diff --git a/ext/pdo_pgsql/tests/copy_from.phpt b/ext/pdo_pgsql/tests/copy_from.phpt
new file mode 100644
index 000000000..2858905d0
--- /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 000000000..1dc7d1de3
--- /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 000000000..99ff56162
--- /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)