com php-src: Add PDO parameter types for national character set strings: NEWS ext/pdo/pdo_dbh.c ext/pdo/php_pdo_driver.h e xt/pdo_dblib/dblib_driver.c ext/pdo_dblib/php_pdo _dblib_int.h ext/pdo_dblib/tests/pdo_dblib_param _str_natl.phpt ext/pdo_dblib/tests/pdo_dblib_quot e.phpt ext/pdo_mysql/mysql_driver.c ext/pdo_mysql /php_pdo_mysql_int.h ext/pdo_mysql/tests/pdo_mysq l_param_str_natl.phpt ext/pdo_mysql/tests/pdo_mys ql_quote.phpt

[email protected] (Adam Baratz)
Newsgroups php.cvs
Message-ID <[email protected]>
Commit:    4afce8ec8c6660ebd9f9eb174d2614361d1c6129
Author:    Adam Baratz <[email protected]>         Mon, 20 Mar 2017 18:25:50 -0400
Parents:   3817cba7863f1cfa077baa3bb492c4eaf9f95bf3
Branches:  master

Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=4afce8ec8c6660ebd9f9eb174d2614361d1c6129

Log:
Add PDO parameter types for national character set strings

Changed paths:
  M  NEWS
  M  ext/pdo/pdo_dbh.c
  M  ext/pdo/php_pdo_driver.h
  M  ext/pdo_dblib/dblib_driver.c
  M  ext/pdo_dblib/php_pdo_dblib_int.h
  A  ext/pdo_dblib/tests/pdo_dblib_param_str_natl.phpt
  M  ext/pdo_dblib/tests/pdo_dblib_quote.phpt
  M  ext/pdo_mysql/mysql_driver.c
  M  ext/pdo_mysql/php_pdo_mysql_int.h
  A  ext/pdo_mysql/tests/pdo_mysql_param_str_natl.phpt
  A  ext/pdo_mysql/tests/pdo_mysql_quote.phpt
diff_4afce8ec8c6660ebd9f9eb174d2614361d1c6129.txt (text/plain, 16.9 KB)
diff --git a/NEWS b/NEWS
index bd66e01..7a28686 100644
--- a/NEWS
+++ b/NEWS
@@ -112,6 +112,7 @@ PHP                                                                        NEWS
 
 - PDO:
   . Add "Sent SQL" to debug dump for emulated prepares. (Adam Baratz)
+  . Add parameter types for national character set strings. (Adam Baratz)
 
 - PDO_DBlib:
   . Fixed bug #73234 (Emulated statements let value dictate parameter type).
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 4cfd010..cb5f1e1 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -1413,6 +1413,9 @@ void pdo_dbh_init(void)
 	REGISTER_PDO_CLASS_CONST_LONG("PARAM_LOB",  (zend_long)PDO_PARAM_LOB);
 	REGISTER_PDO_CLASS_CONST_LONG("PARAM_STMT", (zend_long)PDO_PARAM_STMT);
 	REGISTER_PDO_CLASS_CONST_LONG("PARAM_INPUT_OUTPUT", (zend_long)PDO_PARAM_INPUT_OUTPUT);
+	REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR_NATL", (zend_long)PDO_PARAM_STR_NATL);
+	REGISTER_PDO_CLASS_CONST_LONG("PARAM_STR_CHAR", (zend_long)PDO_PARAM_STR_CHAR);
+
 
 	REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_ALLOC",		(zend_long)PDO_PARAM_EVT_ALLOC);
 	REGISTER_PDO_CLASS_CONST_LONG("PARAM_EVT_FREE",			(zend_long)PDO_PARAM_EVT_FREE);
@@ -1462,6 +1465,7 @@ void pdo_dbh_init(void)
 	REGISTER_PDO_CLASS_CONST_LONG("ATTR_MAX_COLUMN_LEN", (zend_long)PDO_ATTR_MAX_COLUMN_LEN);
 	REGISTER_PDO_CLASS_CONST_LONG("ATTR_EMULATE_PREPARES", (zend_long)PDO_ATTR_EMULATE_PREPARES);
 	REGISTER_PDO_CLASS_CONST_LONG("ATTR_DEFAULT_FETCH_MODE", (zend_long)PDO_ATTR_DEFAULT_FETCH_MODE);
+	REGISTER_PDO_CLASS_CONST_LONG("ATTR_DEFAULT_STR_PARAM", (zend_long)PDO_ATTR_DEFAULT_STR_PARAM);
 
 	REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_SILENT",	(zend_long)PDO_ERRMODE_SILENT);
 	REGISTER_PDO_CLASS_CONST_LONG("ERRMODE_WARNING",	(zend_long)PDO_ERRMODE_WARNING);
diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h
index 9d5753e..bcbe5b3 100644
--- a/ext/pdo/php_pdo_driver.h
+++ b/ext/pdo/php_pdo_driver.h
@@ -46,7 +46,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64);
 # define FALSE 0
 #endif
 
-#define PDO_DRIVER_API	20161020
+#define PDO_DRIVER_API	20170320
 
 enum pdo_param_type {
 	PDO_PARAM_NULL,
@@ -77,7 +77,15 @@ enum pdo_param_type {
 	PDO_PARAM_ZVAL,
 
 	/* magic flag to denote a parameter as being input/output */
-	PDO_PARAM_INPUT_OUTPUT = 0x80000000
+	PDO_PARAM_INPUT_OUTPUT = 0x80000000,
+
+	/* magic flag to denote a string that uses the national character set
+	   see section 4.2.1 of SQL-92: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt
+	 */
+	PDO_PARAM_STR_NATL = 0x40000000,
+
+	/* magic flag to denote a string that uses the regular character set */
+	PDO_PARAM_STR_CHAR = 0x20000000,
 };
 
 #define PDO_PARAM_FLAGS			0xFFFF0000
@@ -140,6 +148,7 @@ enum pdo_attribute_type {
 	PDO_ATTR_MAX_COLUMN_LEN,	/* make database calculate maximum length of data found in a column */
 	PDO_ATTR_DEFAULT_FETCH_MODE, /* Set the default fetch mode */
 	PDO_ATTR_EMULATE_PREPARES,  /* use query emulation rather than native */
+	PDO_ATTR_DEFAULT_STR_PARAM, /* set the default string parameter type (see the PDO::PARAM_STR_* magic flags) */
 
 	/* this defines the start of the range for driver specific options.
 	 * Drivers should define their own attribute constants beginning with this
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index bb37ace..efc8dc1 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -151,10 +151,23 @@ static zend_long dblib_handle_doer(pdo_dbh_t *dbh, const char *sql, size_t sql_l
 
 static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype)
 {
+	pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+	zend_bool use_national_character_set = 0;
+
 	size_t i;
 	char * q;
 	*quotedlen = 0;
 
+	if (H->assume_national_character_set_strings) {
+		use_national_character_set = 1;
+	}
+	if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
+		use_national_character_set = 1;
+	}
+	if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) {
+		use_national_character_set = 0;
+	}
+
 	/* Detect quoted length, adding extra char for doubled single quotes */
 	for (i = 0; i < unquotedlen; i++) {
 		if (unquoted[i] == '\'') ++*quotedlen;
@@ -162,7 +175,13 @@ static int dblib_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unqu
 	}
 
 	*quotedlen += 2; /* +2 for opening, closing quotes */
+	if (use_national_character_set) {
+		++*quotedlen; /* N prefix */
+	}
 	q = *quoted = emalloc(*quotedlen + 1); /* Add byte for terminal null */
+	if (use_national_character_set) {
+		*q++ = 'N';
+	}
 	*q++ = '\'';
 
 	for (i = 0; i < unquotedlen; i++) {
@@ -256,12 +275,17 @@ char *dblib_handle_last_id(pdo_dbh_t *dbh, const char *name, size_t *len)
 
 static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
 {
+	pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+
 	switch(attr) {
+		case PDO_ATTR_DEFAULT_STR_PARAM:
+			H->assume_national_character_set_strings = zval_get_long(val) == PDO_PARAM_STR_NATL ? 1 : 0;
+			return 1;
 		case PDO_ATTR_TIMEOUT:
 		case PDO_DBLIB_ATTR_QUERY_TIMEOUT:
 			return SUCCEED == dbsettime(zval_get_long(val)) ? 1 : 0;
 		case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
-			((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier = zval_get_long(val);
+			H->stringify_uniqueidentifier = zval_get_long(val);
 			return 1;
 		default:
 			return 0;
@@ -270,14 +294,20 @@ static int dblib_set_attr(pdo_dbh_t *dbh, zend_long attr, zval *val)
 
 static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_value)
 {
+	pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data;
+
 	switch (attr) {
+		case PDO_ATTR_DEFAULT_STR_PARAM:
+			ZVAL_LONG(return_value, H->assume_national_character_set_strings ? PDO_PARAM_STR_NATL : PDO_PARAM_STR_CHAR);
+			break;
+
 		case PDO_ATTR_EMULATE_PREPARES:
 			/* this is the only option available, but expose it so common tests and whatever else can introspect */
 			ZVAL_TRUE(return_value);
 			break;
 
 		case PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER:
-			ZVAL_BOOL(return_value, ((pdo_dblib_db_handle *)dbh->driver_data)->stringify_uniqueidentifier);
+			ZVAL_BOOL(return_value, H->stringify_uniqueidentifier);
 			break;
 
 		case PDO_DBLIB_ATTR_VERSION:
@@ -355,6 +385,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
 	H = pecalloc(1, sizeof(*H), dbh->is_persistent);
 	H->login = dblogin();
 	H->err.sqlstate = dbh->error_code;
+	H->assume_national_character_set_strings = 0;
 	H->stringify_uniqueidentifier = 0;
 
 	if (!H->login) {
@@ -376,6 +407,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
 		dbsetlogintime(connect_timeout); /* Connection/Login Timeout */
 		dbsettime(query_timeout); /* Statement Timeout */
 
+		H->assume_national_character_set_strings = pdo_attr_lval(driver_options, PDO_ATTR_DEFAULT_STR_PARAM, 0) == PDO_PARAM_STR_NATL ? 1 : 0;
 		H->stringify_uniqueidentifier = pdo_attr_lval(driver_options, PDO_DBLIB_ATTR_STRINGIFY_UNIQUEIDENTIFIER, 0);
 	}
 
diff --git a/ext/pdo_dblib/php_pdo_dblib_int.h b/ext/pdo_dblib/php_pdo_dblib_int.h
index 7eb6b1d..c406976 100644
--- a/ext/pdo_dblib/php_pdo_dblib_int.h
+++ b/ext/pdo_dblib/php_pdo_dblib_int.h
@@ -116,6 +116,7 @@ typedef struct {
 	DBPROCESS	*link;
 
 	pdo_dblib_err err;
+	unsigned assume_national_character_set_strings:1;
 	unsigned stringify_uniqueidentifier:1;
 } pdo_dblib_db_handle;
 
diff --git a/ext/pdo_dblib/tests/pdo_dblib_param_str_natl.phpt b/ext/pdo_dblib/tests/pdo_dblib_param_str_natl.phpt
new file mode 100644
index 0000000..4753a91
--- /dev/null
+++ b/ext/pdo_dblib/tests/pdo_dblib_param_str_natl.phpt
@@ -0,0 +1,27 @@
+--TEST--
+PDO_DBLIB: national character set values are quoted correctly in queries
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$stmt = $db->prepare('SELECT :value');
+$stmt->bindValue(':value', 'foo', PDO::PARAM_STR | PDO::PARAM_STR_NATL);
+$stmt->execute();
+
+var_dump($stmt->debugDumpParams());
+?>
+--EXPECT--
+SQL: [13] SELECT :value
+Sent SQL: [13] SELECT N'foo'
+Params:  1
+Key: Name: [6] :value
+paramno=-1
+name=[6] ":value"
+is_param=1
+param_type=1073741826
+NULL
diff --git a/ext/pdo_dblib/tests/pdo_dblib_quote.phpt b/ext/pdo_dblib/tests/pdo_dblib_quote.phpt
index 543093d..854e14c 100644
--- a/ext/pdo_dblib/tests/pdo_dblib_quote.phpt
+++ b/ext/pdo_dblib/tests/pdo_dblib_quote.phpt
@@ -14,7 +14,20 @@ var_dump($db->quote(42, PDO::PARAM_INT));
 var_dump($db->quote(null, PDO::PARAM_NULL));
 var_dump($db->quote('\'', PDO::PARAM_STR));
 var_dump($db->quote('foo', PDO::PARAM_STR));
+var_dump($db->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR));
+var_dump($db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL));
+
+var_dump($db->getAttribute(PDO::ATTR_DEFAULT_STR_PARAM) === PDO::PARAM_STR_CHAR);
+$db->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_NATL);
+var_dump($db->getAttribute(PDO::ATTR_DEFAULT_STR_PARAM) === PDO::PARAM_STR_NATL);
+
+var_dump($db->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR));
 var_dump($db->quote('über', PDO::PARAM_STR));
+var_dump($db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL));
+
+$db = new PDO($dsn, $user, $pass, [PDO::ATTR_DEFAULT_STR_PARAM => PDO::PARAM_STR_NATL]);
+var_dump($db->getAttribute(PDO::ATTR_DEFAULT_STR_PARAM) === PDO::PARAM_STR_NATL);
+
 ?>
 --EXPECT--
 string(3) "'1'"
@@ -23,4 +36,11 @@ string(4) "'42'"
 string(2) "''"
 string(4) "''''"
 string(5) "'foo'"
-string(7) "'über'"
+string(5) "'foo'"
+string(8) "N'über'"
+bool(true)
+bool(true)
+string(5) "'foo'"
+string(8) "N'über'"
+string(8) "N'über'"
+bool(true)
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index a716c7b..08b546c 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -300,12 +300,35 @@ static char *pdo_mysql_last_insert_id(pdo_dbh_t *dbh, const char *name, size_t *
 static int mysql_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, size_t unquotedlen, char **quoted, size_t *quotedlen, enum pdo_param_type paramtype )
 {
 	pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
+	zend_bool use_national_character_set = 0;
+
+	if (H->assume_national_character_set_strings) {
+		use_national_character_set = 1;
+	}
+	if ((paramtype & PDO_PARAM_STR_NATL) == PDO_PARAM_STR_NATL) {
+		use_national_character_set = 1;
+	}
+	if ((paramtype & PDO_PARAM_STR_CHAR) == PDO_PARAM_STR_CHAR) {
+		use_national_character_set = 0;
+	}
+
 	PDO_DBG_ENTER("mysql_handle_quoter");
 	PDO_DBG_INF_FMT("dbh=%p", dbh);
 	PDO_DBG_INF_FMT("unquoted=%.*s", (int)unquotedlen, unquoted);
-	*quoted = safe_emalloc(2, unquotedlen, 3);
-	*quotedlen = mysql_real_escape_string(H->server, *quoted + 1, unquoted, unquotedlen);
-	(*quoted)[0] =(*quoted)[++*quotedlen] = '\'';
+	*quoted = safe_emalloc(2, unquotedlen, 3 + (use_national_character_set ? 1 : 0));
+
+	if (use_national_character_set) {
+		*quotedlen = mysql_real_escape_string(H->server, *quoted + 2, unquoted, unquotedlen);
+		(*quoted)[0] = 'N';
+		(*quoted)[1] = '\'';
+
+		++*quotedlen; /* N prefix */
+	} else {
+		*quotedlen = mysql_real_escape_string(H->server, *quoted + 1, unquoted, unquotedlen);
+		(*quoted)[0] = '\'';
+	}
+
+	(*quoted)[++*quotedlen] = '\'';
 	(*quoted)[++*quotedlen] = '\0';
 	PDO_DBG_INF_FMT("quoted=%.*s", (int)*quotedlen, *quoted);
 	PDO_DBG_RETURN(1);
@@ -369,7 +392,7 @@ static inline int mysql_handle_autocommit(pdo_dbh_t *dbh)
 static int pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
 {
 	zend_long lval = zval_get_long(val);
-	zend_bool bval = lval? 1 : 0;
+	zend_bool bval = lval ? 1 : 0;
 	PDO_DBG_ENTER("pdo_mysql_set_attribute");
 	PDO_DBG_INF_FMT("dbh=%p", dbh);
 	PDO_DBG_INF_FMT("attr=%l", attr);
@@ -382,18 +405,25 @@ static int pdo_mysql_set_attribute(pdo_dbh_t *dbh, zend_long attr, zval *val)
 			}
 			PDO_DBG_RETURN(1);
 
+		case PDO_ATTR_DEFAULT_STR_PARAM:
+			((pdo_mysql_db_handle *)dbh->driver_data)->assume_national_character_set_strings = lval == PDO_PARAM_STR_NATL ? 1 : 0;
+			PDO_DBG_RETURN(1);
+
 		case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
 			/* ignore if the new value equals the old one */
 			((pdo_mysql_db_handle *)dbh->driver_data)->buffered = bval;
 			PDO_DBG_RETURN(1);
+
 		case PDO_MYSQL_ATTR_DIRECT_QUERY:
 		case PDO_ATTR_EMULATE_PREPARES:
 			/* ignore if the new value equals the old one */
 			((pdo_mysql_db_handle *)dbh->driver_data)->emulate_prepare = bval;
 			PDO_DBG_RETURN(1);
+
 		case PDO_ATTR_FETCH_TABLE_NAMES:
 			((pdo_mysql_db_handle *)dbh->driver_data)->fetch_table_names = bval;
 			PDO_DBG_RETURN(1);
+
 #ifndef PDO_USE_MYSQLND
 		case PDO_MYSQL_ATTR_MAX_BUFFER_SIZE:
 			if (lval < 0) {
@@ -450,10 +480,15 @@ static int pdo_mysql_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_
 			}
 		}
 			break;
+
 		case PDO_ATTR_AUTOCOMMIT:
 			ZVAL_LONG(return_value, dbh->auto_commit);
 			break;
 
+		case PDO_ATTR_DEFAULT_STR_PARAM:
+			ZVAL_LONG(return_value, H->assume_national_character_set_strings ? PDO_PARAM_STR_NATL : PDO_PARAM_STR_CHAR);
+			break;
+
 		case PDO_MYSQL_ATTR_USE_BUFFERED_QUERY:
 			ZVAL_LONG(return_value, H->buffered);
 			break;
@@ -597,6 +632,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
 	H->max_buffer_size = 1024*1024;
 #endif
 
+	H->assume_national_character_set_strings = 0;
 	H->buffered = H->emulate_prepare = 1;
 
 	/* handle MySQL options */
@@ -616,6 +652,9 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
 		H->emulate_prepare = pdo_attr_lval(driver_options,
 			PDO_ATTR_EMULATE_PREPARES, H->emulate_prepare);
 
+		H->assume_national_character_set_strings = pdo_attr_lval(driver_options,
+			PDO_ATTR_DEFAULT_STR_PARAM, 0) == PDO_PARAM_STR_NATL ? 1 : 0;
+
 #ifndef PDO_USE_MYSQLND
 		H->max_buffer_size = pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_MAX_BUFFER_SIZE, H->max_buffer_size);
 #endif
diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h
index cf3ad9d..32e79e1 100644
--- a/ext/pdo_mysql/php_pdo_mysql_int.h
+++ b/ext/pdo_mysql/php_pdo_mysql_int.h
@@ -104,6 +104,7 @@ typedef struct {
 typedef struct {
 	MYSQL 		*server;
 
+	unsigned assume_national_character_set_strings:1;
 	unsigned attached:1;
 	unsigned buffered:1;
 	unsigned emulate_prepare:1;
diff --git a/ext/pdo_mysql/tests/pdo_mysql_param_str_natl.phpt b/ext/pdo_mysql/tests/pdo_mysql_param_str_natl.phpt
new file mode 100644
index 0000000..56b9448
--- /dev/null
+++ b/ext/pdo_mysql/tests/pdo_mysql_param_str_natl.phpt
@@ -0,0 +1,44 @@
+--TEST--
+PDO MySQL national character set parameters don't affect true prepared statements
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) 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__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
+
+$db->exec('CREATE TABLE test (bar NCHAR(4) NOT NULL)');
+
+$stmt = $db->prepare('INSERT INTO test VALUES(?)');
+$stmt->bindValue(1, 'foo', PDO::PARAM_STR | PDO::PARAM_STR_NATL);
+$stmt->execute();
+
+var_dump($db->query('SELECT * from test'));
+foreach ($db->query('SELECT * from test') as $row) {
+	print_r($row);
+}
+
+?>
+--CLEAN--
+<?php
+require dirname(__FILE__) . '/mysql_pdo_test.inc';
+MySQLPDOTest::dropTestTable();
+?>
+--EXPECTF--
+object(PDOStatement)#%d (1) {
+  ["queryString"]=>
+  string(18) "SELECT * from test"
+}
+Array
+(
+    [bar] => foo
+    [0] => foo
+)
diff --git a/ext/pdo_mysql/tests/pdo_mysql_quote.phpt b/ext/pdo_mysql/tests/pdo_mysql_quote.phpt
new file mode 100644
index 0000000..3d094a4
--- /dev/null
+++ b/ext/pdo_mysql/tests/pdo_mysql_quote.phpt
@@ -0,0 +1,34 @@
+--TEST--
+MySQL ensure quote function returns expected results
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+?>
+--FILE--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+$db = MySQLPDOTest::factory();
+
+var_dump($db->quote('foo', PDO::PARAM_STR));
+var_dump($db->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR));
+var_dump($db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL));
+
+var_dump($db->getAttribute(PDO::ATTR_DEFAULT_STR_PARAM) === PDO::PARAM_STR_CHAR);
+$db->setAttribute(PDO::ATTR_DEFAULT_STR_PARAM, PDO::PARAM_STR_NATL);
+var_dump($db->getAttribute(PDO::ATTR_DEFAULT_STR_PARAM) === PDO::PARAM_STR_NATL);
+
+var_dump($db->quote('foo', PDO::PARAM_STR | PDO::PARAM_STR_CHAR));
+var_dump($db->quote('über', PDO::PARAM_STR));
+var_dump($db->quote('über', PDO::PARAM_STR | PDO::PARAM_STR_NATL));
+?>
+--EXPECT--
+string(5) "'foo'"
+string(5) "'foo'"
+string(8) "N'über'"
+bool(true)
+bool(true)
+string(5) "'foo'"
+string(8) "N'über'"
+string(8) "N'über'"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.