Patch bug45259_sqlite-bind-params-autodetect_v308350 for PDO SQLite Bug #54023
Patch version 2011-02-15 10:47 UTC
Return to Bug #54023 |
Download this patch
Patch Revisions:
Developer: sl9@gmx.net
Index: ext/pdo_sqlite/tests/bug45259_bool.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_bool.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_bool.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - boolean)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_int
+ 'Boolean' => array(
+ 'concrete true = true ' => array('SELECT 1 = 1 AS test', array()),
+ 'concrete true = false ' => array('SELECT 1 = 0 AS test', array()),
+ 'bound true = true ' => array('SELECT 1 = ? AS test', array(true)),
+ 'bound true = false ' => array('SELECT 1 = ? AS test', array(false)),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+Boolean:
+ concrete true = true : 1
+ concrete true = false : 0
+ bound true = true : 1
+ bound true = false : 0
Index: ext/pdo_sqlite/tests/bug45259_double.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_double.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_double.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - double)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_double
+ 'Double' => array(
+ 'concrete 12.34 = 12.34 ' => array('SELECT 12.34 = 12.34 AS test', array()),
+ 'concrete 12.34 = 43.21 ' => array('SELECT 12.34 = 43.21 AS test', array()),
+ 'bound 12.34 = 12.34 ' => array('SELECT 12.34 = ? AS test', array(12.34)),
+ 'bound 12.34 = 43.21 ' => array('SELECT 12.34 = ? AS test', array(43.21)),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+Double:
+ concrete 12.34 = 12.34 : 1
+ concrete 12.34 = 43.21 : 0
+ bound 12.34 = 12.34 : 1
+ bound 12.34 = 43.21 : 0
Index: ext/pdo_sqlite/tests/bug45259_int-big.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_int-big.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_int-big.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - int big)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_int
+ 'Integer (big)' => array(
+ 'concrete PHP_INT_MAX = PHP_INT_MAX ' => array('SELECT ' . PHP_INT_MAX . ' = ' . PHP_INT_MAX . ' AS test', array()),
+ 'concrete PHP_INT_MAX = PHP_INT_MAX - 1' => array('SELECT ' . PHP_INT_MAX . ' = ' . (PHP_INT_MAX - 1) . ' AS test', array()),
+ 'bound PHP_INT_MAX = PHP_INT_MAX ' => array('SELECT ' . PHP_INT_MAX . ' = ? AS test', array(PHP_INT_MAX)),
+ 'bound PHP_INT_MAX = PHP_INT_MAX - 1' => array('SELECT ' . PHP_INT_MAX . ' = ? AS test', array(PHP_INT_MAX - 1)),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+Integer (big):
+ concrete PHP_INT_MAX = PHP_INT_MAX : 1
+ concrete PHP_INT_MAX = PHP_INT_MAX - 1: 0
+ bound PHP_INT_MAX = PHP_INT_MAX : 1
+ bound PHP_INT_MAX = PHP_INT_MAX - 1: 0
\ No newline at end of file
Index: ext/pdo_sqlite/tests/bug45259_int-small.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_int-small.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_int-small.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - int small)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_int
+ 'Integer (small)' => array(
+ 'concrete 100 = 100 ' => array('SELECT 100 = 100 AS test', array()),
+ 'concrete 100 = 50 ' => array('SELECT 100 = 50 AS test', array()),
+ 'bound 100 = 100 ' => array('SELECT 100 = ? AS test', array(100)),
+ 'bound 100 = 50 ' => array('SELECT 100 = ? AS test', array(50)),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+Integer (small):
+ concrete 100 = 100 : 1
+ concrete 100 = 50 : 0
+ bound 100 = 100 : 1
+ bound 100 = 50 : 0
Index: ext/pdo_sqlite/tests/bug45259_null.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_null.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_null.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - null)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_null
+ 'Null' => array(
+ 'concrete IFNULL(null) ' => array('SELECT IFNULL(null,"null") AS test', array()),
+ 'concrete IFNULL(ifail) ' => array('SELECT IFNULL("ifail","null") AS test', array()),
+ 'bound IFNULL(null) ' => array('SELECT IFNULL(?,"null") AS test', array(null)),
+ 'bound IFNULL(ifail) ' => array('SELECT IFNULL(?,"null") AS test', array('ifail')),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+Null:
+ concrete IFNULL(null) : null
+ concrete IFNULL(ifail) : ifail
+ bound IFNULL(null) : null
+ bound IFNULL(ifail) : ifail
Index: ext/pdo_sqlite/tests/bug45259_text.phpt
===================================================================
--- ext/pdo_sqlite/tests/bug45259_text.phpt (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_text.phpt (revision 0)
@@ -0,0 +1,31 @@
+--TEST--
+Bug #45259 (SQLite PDO prepared statements don't bind values - text)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$testGroups = array(
+ // sqlite3_bind_text
+ 'String' => array(
+ 'concrete testme = testme' => array('SELECT "testme" = "testme" AS test', array()),
+ 'concrete testme = ifail ' => array('SELECT "testme" = "ifail" AS test', array()),
+ 'bound testme = testme' => array('SELECT "testme" = ? AS test', array('testme')),
+ 'bound testme = ifail ' => array('SELECT "testme" = ? AS test', array('ifail')),
+ ),
+);
+
+require dirname(__FILE__) . '/bug45259_common.inc';
+
+?>
+--EXPECT--
+String:
+ concrete testme = testme: 1
+ concrete testme = ifail : 0
+ bound testme = testme: 1
+ bound testme = ifail : 0
Index: ext/pdo_sqlite/tests/bug45259_common.inc
===================================================================
--- ext/pdo_sqlite/tests/bug45259_common.inc (revision 0)
+++ ext/pdo_sqlite/tests/bug45259_common.inc (revision 0)
@@ -0,0 +1,15 @@
+<?php
+
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+foreach($testGroups as $testGroupName => $testCases){
+ echo $testGroupName, ':', PHP_EOL;
+ foreach($testCases as $testCaseName => $testCase){
+ $query = $testCase[0];
+ $param = $testCase[1];
+ $stmt = $db->prepare($query);
+ $stmt->execute($param);
+ $row = $stmt->fetch();
+ echo ' ', $testCaseName, ': ', $row['test'], PHP_EOL;
+ }
+}
Index: ext/pdo_sqlite/sqlite_statement.c
===================================================================
--- ext/pdo_sqlite/sqlite_statement.c (revision 308350)
+++ ext/pdo_sqlite/sqlite_statement.c (working copy)
@@ -78,6 +78,8 @@
static int pdo_sqlite_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param,
enum pdo_param_event event_type TSRMLS_DC)
{
+ int hookResult = 0; // failure
+
pdo_sqlite_stmt *S = (pdo_sqlite_stmt*)stmt->driver_data;
switch (event_type) {
@@ -86,39 +88,97 @@
sqlite3_reset(S->stmt);
S->done = 1;
}
-
+
if (param->is_param) {
-
if (param->paramno == -1) {
param->paramno = sqlite3_bind_parameter_index(S->stmt, param->name) - 1;
}
+ if(PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_ZVAL){
+ // XXX: User didn't specify a PDO_PARAM_* value, so let's do autodetect using the ZVAL type
+ switch(Z_TYPE_P(param->parameter)){
+ case IS_STRING:
+ param->param_type = PDO_PARAM_STR;
+ break;
+ case IS_LONG:
+ param->param_type = PDO_PARAM_INT;
+ break;
+ case IS_NULL:
+ param->param_type = PDO_PARAM_NULL;
+ break;
+ case IS_BOOL:
+ param->param_type = PDO_PARAM_BOOL;
+ break;
+ case IS_DOUBLE:
+ param->param_type = PDO_PARAM_INT;
+ break;
+ case IS_RESOURCE:
+ param->param_type = PDO_PARAM_LOB;
+ break;
+ default:
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Invalid parameter type" TSRMLS_CC);
+ }
+ }
+
switch (PDO_PARAM_TYPE(param->param_type)) {
case PDO_PARAM_STMT:
- return 0;
-
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Invalid parameter type" TSRMLS_CC);
+ break;
case PDO_PARAM_NULL:
- if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
- return 1;
+ if(sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
- pdo_sqlite_error_stmt(stmt);
- return 0;
-
+ break;
case PDO_PARAM_INT:
- case PDO_PARAM_BOOL:
- if (Z_TYPE_P(param->parameter) == IS_NULL) {
+ if (Z_TYPE_P(param->parameter) == IS_LONG) {
+ // no conversion
+ }else if (Z_TYPE_P(param->parameter) == IS_DOUBLE) {
+ if (sqlite3_bind_double(S->stmt, param->paramno + 1, Z_DVAL_P(param->parameter)) == SQLITE_OK) {
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
+ }
+ }else if (Z_TYPE_P(param->parameter) == IS_NULL) {
if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
- return 1;
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
- } else {
+ }else{
convert_to_long(param->parameter);
- if (SQLITE_OK == sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter))) {
- return 1;
+ }
+
+ if (Z_TYPE_P(param->parameter) == IS_LONG) {
+ if (sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter)) == SQLITE_OK) {
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
}
- pdo_sqlite_error_stmt(stmt);
- return 0;
-
+ break;
+ case PDO_PARAM_BOOL:
+ if (Z_TYPE_P(param->parameter) == IS_BOOL) {
+ // no conversion
+ }else if (Z_TYPE_P(param->parameter) == IS_NULL) {
+ if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
+ }
+ }else{
+ convert_to_boolean(param->parameter);
+ }
+
+ if (Z_TYPE_P(param->parameter) == IS_BOOL) {
+ if (sqlite3_bind_int(S->stmt, param->paramno + 1, Z_LVAL_P(param->parameter)) == SQLITE_OK) {
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
+ }
+ }
+ break;
case PDO_PARAM_LOB:
if (Z_TYPE_P(param->parameter) == IS_RESOURCE) {
php_stream *stm;
@@ -128,54 +188,70 @@
Z_TYPE_P(param->parameter) = IS_STRING;
Z_STRLEN_P(param->parameter) = php_stream_copy_to_mem(stm,
&Z_STRVAL_P(param->parameter), PHP_STREAM_COPY_ALL, 0);
- } else {
+ }else{
pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
- return 0;
}
} else if (Z_TYPE_P(param->parameter) == IS_NULL) {
if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
- return 1;
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
- pdo_sqlite_error_stmt(stmt);
- return 0;
} else {
convert_to_string(param->parameter);
+ if(
+ sqlite3_bind_blob(
+ S->stmt, param->paramno + 1,
+ Z_STRVAL_P(param->parameter),
+ Z_STRLEN_P(param->parameter),
+ SQLITE_STATIC
+ ) == SQLITE_OK
+ ){
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
+ }
}
-
- if (SQLITE_OK == sqlite3_bind_blob(S->stmt, param->paramno + 1,
- Z_STRVAL_P(param->parameter),
- Z_STRLEN_P(param->parameter),
- SQLITE_STATIC)) {
- return 1;
- }
- pdo_sqlite_error_stmt(stmt);
- return 0;
-
+ break;
+
case PDO_PARAM_STR:
default:
- if (Z_TYPE_P(param->parameter) == IS_NULL) {
+ if (Z_TYPE_P(param->parameter) == IS_STRING) {
+ // no conversion
+ } else if (Z_TYPE_P(param->parameter) == IS_NULL) {
if (sqlite3_bind_null(S->stmt, param->paramno + 1) == SQLITE_OK) {
- return 1;
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
} else {
convert_to_string(param->parameter);
- if(SQLITE_OK == sqlite3_bind_text(S->stmt, param->paramno + 1,
+ }
+
+ if(Z_TYPE_P(param->parameter) == IS_STRING){
+ if(
+ sqlite3_bind_text(
+ S->stmt, param->paramno + 1,
Z_STRVAL_P(param->parameter),
Z_STRLEN_P(param->parameter),
- SQLITE_STATIC)) {
- return 1;
+ SQLITE_STATIC
+ ) == SQLITE_OK
+ ){
+ hookResult = 1; // success
+ }else{
+ pdo_sqlite_error_stmt(stmt);
}
}
- pdo_sqlite_error_stmt(stmt);
- return 0;
+ break;
}
+ }else{
+ hookResult = 1; // success
}
- break;
-
+ break;
default:
- ;
+ hookResult = 1; // success
}
- return 1;
+ return hookResult;
}
static int pdo_sqlite_stmt_fetch(pdo_stmt_t *stmt,
Index: ext/pdo/pdo_stmt.c
===================================================================
--- ext/pdo/pdo_stmt.c (revision 308350)
+++ ext/pdo/pdo_stmt.c (working copy)
@@ -468,6 +468,13 @@
}
param.param_type = PDO_PARAM_STR;
+ if(strcmp(stmt->dbh->driver->driver_name, "sqlite") == 0){
+ // Sqlite does own mapping of zvals to pdo params now.
+ // Setting param type to a constant to signal that no explicit type was set
+ // gives the driver the opportunity to autodetect the type from the zval itself
+ param.param_type = PDO_PARAM_ZVAL;
+ }
+
MAKE_STD_ZVAL(param.parameter);
MAKE_COPY_ZVAL(tmp, param.parameter);
|