mbeccati                                 Wed, 07 Oct 2009 17:40:16 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=289287

Log:
- Fixed bug #48764 (PDO_pgsql::query always uses implicit prepared statements 
if v3 proto available)

# original patch by Mark Kirkwood

Bug: http://bugs.php.net/48764 (Open) PDO_pgsql::query always uses implicit 
prepared statements if v3 proto available
      
Changed paths:
    U   php/php-src/branches/PHP_5_2/NEWS
    U   php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pdo_pgsql.c
    U   php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_driver.c
    U   php/php-src/branches/PHP_5_2/ext/pdo_pgsql/php_pdo_pgsql_int.h
    A   php/php-src/branches/PHP_5_2/ext/pdo_pgsql/tests/bug48764.phpt
    U   php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pdo_pgsql.c
    U   php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_driver.c
    U   php/php-src/branches/PHP_5_3/ext/pdo_pgsql/php_pdo_pgsql_int.h
    A   php/php-src/branches/PHP_5_3/ext/pdo_pgsql/tests/bug48764.phpt
    U   php/php-src/trunk/ext/pdo_pgsql/pdo_pgsql.c
    U   php/php-src/trunk/ext/pdo_pgsql/pgsql_driver.c
    U   php/php-src/trunk/ext/pdo_pgsql/php_pdo_pgsql_int.h
    A   php/php-src/trunk/ext/pdo_pgsql/tests/bug48764.phpt

Modified: php/php-src/branches/PHP_5_2/NEWS
===================================================================
--- php/php-src/branches/PHP_5_2/NEWS	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_2/NEWS	2009-10-07 17:40:16 UTC (rev 289287)
@@ -29,6 +29,8 @@
 - Fixed bug #49528 (UTF-16 strings prefixed by BOMs wrongly converted).
   (Moriyoshi)
 - Fixed bug #48805 (IPv6 socket transport is not working). (Ilia)
+- Fixed bug #48764 (PDO_pgsql::query always uses implicit prepared statements
+  if v3 proto available). (Matteo, Mark Kirkwood)


 17 Sep 2009, PHP 5.2.11

Modified: php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pdo_pgsql.c
===================================================================
--- php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -80,8 +80,8 @@
  */
 PHP_MINIT_FUNCTION(pdo_pgsql)
 {
+	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	php_pdo_register_driver(&pdo_pgsql_driver);
-	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	return SUCCESS;
 }
 /* }}} */

Modified: php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_driver.c
===================================================================
--- php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_2/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -239,13 +239,12 @@
 #if HAVE_PQPREPARE

 	if (driver_options) {
-		if (pdo_attr_lval(driver_options,
-				PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
+		if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1 ||
+			pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) {
 			emulate = 1;
-		} else if (pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES,
-				0 TSRMLS_CC) == 1) {
-			emulate = 1;
 		}
+	} else {
+		emulate = H->disable_native_prepares || H->emulate_prepares;
 	}

 	if (!emulate && PQprotocolVersion(H->server) > 2) {
@@ -646,7 +645,21 @@

 static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
 {
-	return 0;
+	pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+	switch (attr) {
+#if HAVE_PQPREPARE
+		case PDO_ATTR_EMULATE_PREPARES:
+			H->emulate_prepares = Z_LVAL_P(val);
+			return 1;
+		case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT:
+			H->disable_native_prepares = Z_LVAL_P(val);
+			return 1;
+#endif
+
+		default:
+			return 0;
+	}
 }

 static struct pdo_dbh_methods pgsql_methods = {

Modified: php/php-src/branches/PHP_5_2/ext/pdo_pgsql/php_pdo_pgsql_int.h
===================================================================
--- php/php-src/branches/PHP_5_2/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_2/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:40:16 UTC (rev 289287)
@@ -43,6 +43,13 @@
 	unsigned 	_reserved:31;
 	pdo_pgsql_error_info	einfo;
 	Oid 		pgoid;
+#if HAVE_PQPREPARE
+	/* The following two variables have the same purpose. Unfortunately we need
+	   to keep track of two different attributes having the same effect.
+	   It might be worth to deprecate the driver specific one soon. */
+	int		emulate_prepares;
+	int		disable_native_prepares;
+#endif
 } pdo_pgsql_db_handle;

 typedef struct {

Added: php/php-src/branches/PHP_5_2/ext/pdo_pgsql/tests/bug48764.phpt
===================================================================
--- php/php-src/branches/PHP_5_2/ext/pdo_pgsql/tests/bug48764.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_2/ext/pdo_pgsql/tests/bug48764.phpt	2009-10-07 17:40:16 UTC (rev 289287)
@@ -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

Modified: php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pdo_pgsql.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -85,8 +85,8 @@
  */
 PHP_MINIT_FUNCTION(pdo_pgsql)
 {
+	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	php_pdo_register_driver(&pdo_pgsql_driver);
-	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	return SUCCESS;
 }
 /* }}} */

Modified: php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_driver.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_3/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -239,15 +239,13 @@
 	}

 #if HAVE_PQPREPARE
-
 	else if (driver_options) {
-		if (pdo_attr_lval(driver_options,
-				PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
+		if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1 ||
+			pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) {
 			emulate = 1;
-		} else if (pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES,
-				0 TSRMLS_CC) == 1) {
-			emulate = 1;
 		}
+	} else {
+		emulate = H->disable_native_prepares || H->emulate_prepares;
 	}

 	if (!emulate && PQprotocolVersion(H->server) > 2) {
@@ -625,7 +623,21 @@

 static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
 {
-	return 0;
+	pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+	switch (attr) {
+#if HAVE_PQPREPARE
+		case PDO_ATTR_EMULATE_PREPARES:
+			H->emulate_prepares = Z_LVAL_P(val);
+			return 1;
+		case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT:
+			H->disable_native_prepares = Z_LVAL_P(val);
+			return 1;
+#endif
+
+		default:
+			return 0;
+	}
 }

 static struct pdo_dbh_methods pgsql_methods = {

Modified: php/php-src/branches/PHP_5_3/ext/pdo_pgsql/php_pdo_pgsql_int.h
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/branches/PHP_5_3/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:40:16 UTC (rev 289287)
@@ -43,6 +43,13 @@
 	unsigned 	_reserved:31;
 	pdo_pgsql_error_info	einfo;
 	Oid 		pgoid;
+#if HAVE_PQPREPARE
+	/* The following two variables have the same purpose. Unfortunately we need
+	   to keep track of two different attributes having the same effect.
+	   It might be worth to deprecate the driver specific one soon. */
+	int		emulate_prepares;
+	int		disable_native_prepares;
+#endif
 } pdo_pgsql_db_handle;

 typedef struct {

Added: php/php-src/branches/PHP_5_3/ext/pdo_pgsql/tests/bug48764.phpt
===================================================================
--- php/php-src/branches/PHP_5_3/ext/pdo_pgsql/tests/bug48764.phpt	                        (rev 0)
+++ php/php-src/branches/PHP_5_3/ext/pdo_pgsql/tests/bug48764.phpt	2009-10-07 17:40:16 UTC (rev 289287)
@@ -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

Modified: php/php-src/trunk/ext/pdo_pgsql/pdo_pgsql.c
===================================================================
--- php/php-src/trunk/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/trunk/ext/pdo_pgsql/pdo_pgsql.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -85,8 +85,8 @@
  */
 PHP_MINIT_FUNCTION(pdo_pgsql)
 {
+	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	php_pdo_register_driver(&pdo_pgsql_driver);
-	REGISTER_PDO_CLASS_CONST_LONG("PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT", PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT);
 	return SUCCESS;
 }
 /* }}} */

Modified: php/php-src/trunk/ext/pdo_pgsql/pgsql_driver.c
===================================================================
--- php/php-src/trunk/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/trunk/ext/pdo_pgsql/pgsql_driver.c	2009-10-07 17:40:16 UTC (rev 289287)
@@ -239,15 +239,13 @@
 	}

 #if HAVE_PQPREPARE
-
 	else if (driver_options) {
-		if (pdo_attr_lval(driver_options,
-				PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, 0 TSRMLS_CC) == 1) {
+		if (pdo_attr_lval(driver_options, PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT, H->disable_native_prepares TSRMLS_CC) == 1 ||
+			pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES, H->emulate_prepares TSRMLS_CC) == 1) {
 			emulate = 1;
-		} else if (pdo_attr_lval(driver_options, PDO_ATTR_EMULATE_PREPARES,
-				0 TSRMLS_CC) == 1) {
-			emulate = 1;
 		}
+	} else {
+		emulate = H->disable_native_prepares || H->emulate_prepares;
 	}

 	if (!emulate && PQprotocolVersion(H->server) > 2) {
@@ -625,7 +623,21 @@

 static int pdo_pgsql_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
 {
-	return 0;
+	pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
+
+	switch (attr) {
+#if HAVE_PQPREPARE
+		case PDO_ATTR_EMULATE_PREPARES:
+			H->emulate_prepares = Z_LVAL_P(val);
+			return 1;
+		case PDO_PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT:
+			H->disable_native_prepares = Z_LVAL_P(val);
+			return 1;
+#endif
+
+		default:
+			return 0;
+	}
 }

 static struct pdo_dbh_methods pgsql_methods = {

Modified: php/php-src/trunk/ext/pdo_pgsql/php_pdo_pgsql_int.h
===================================================================
--- php/php-src/trunk/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:35:31 UTC (rev 289286)
+++ php/php-src/trunk/ext/pdo_pgsql/php_pdo_pgsql_int.h	2009-10-07 17:40:16 UTC (rev 289287)
@@ -43,6 +43,13 @@
 	unsigned 	_reserved:31;
 	pdo_pgsql_error_info	einfo;
 	Oid 		pgoid;
+#if HAVE_PQPREPARE
+	/* The following two variables have the same purpose. Unfortunately we need
+	   to keep track of two different attributes having the same effect.
+	   It might be worth to deprecate the driver specific one soon. */
+	int		emulate_prepares;
+	int		disable_native_prepares;
+#endif
 } pdo_pgsql_db_handle;

 typedef struct {

Added: php/php-src/trunk/ext/pdo_pgsql/tests/bug48764.phpt
===================================================================
--- php/php-src/trunk/ext/pdo_pgsql/tests/bug48764.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/pdo_pgsql/tests/bug48764.phpt	2009-10-07 17:40:16 UTC (rev 289287)
@@ -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
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to