wez Sat Jul 2 22:20:09 2005 EDT
Modified files:
/php-src/ext/pdo_mysql config.m4 mysql_driver.c mysql_statement.c
pdo_mysql.c php_pdo_mysql.h
php_pdo_mysql_int.h
Log:
Enable native mysql 4.1.x prepared statement support
# the hardest part was installing 4.1.x on a gentoo box over a 56k modem
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/config.m4?r1=1.23&r2=1.24&ty=u
Index: php-src/ext/pdo_mysql/config.m4
diff -u php-src/ext/pdo_mysql/config.m4:1.23
php-src/ext/pdo_mysql/config.m4:1.24
--- php-src/ext/pdo_mysql/config.m4:1.23 Sat Jul 2 17:01:38 2005
+++ php-src/ext/pdo_mysql/config.m4 Sat Jul 2 22:20:08 2005
@@ -1,5 +1,5 @@
dnl
-dnl $Id: config.m4,v 1.23 2005/07/02 21:01:38 wez Exp $
+dnl $Id: config.m4,v 1.24 2005/07/03 02:20:08 wez Exp $
dnl
if test "$PHP_PDO" != "no"; then
@@ -58,7 +58,7 @@
_SAVE_LDFLAGS=$LDFLAGS
LDFLAGS="$LDFLAGS $PDO_MYSQL_LIBS"
- AC_CHECK_FUNCS([mysql_commit mysql_stmt_prepare mysql_next_result])
+ AC_CHECK_FUNCS([mysql_commit mysql_stmt_prepare mysql_next_result
mysql_sqlstate])
LDFLAGS=$_SAVE_LDFLAGS
PHP_CHECK_PDO_INCLUDES
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/mysql_driver.c?r1=1.50&r2=1.51&ty=u
Index: php-src/ext/pdo_mysql/mysql_driver.c
diff -u php-src/ext/pdo_mysql/mysql_driver.c:1.50
php-src/ext/pdo_mysql/mysql_driver.c:1.51
--- php-src/ext/pdo_mysql/mysql_driver.c:1.50 Sat Jul 2 17:01:38 2005
+++ php-src/ext/pdo_mysql/mysql_driver.c Sat Jul 2 22:20:08 2005
@@ -13,10 +13,11 @@
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: George Schlossnagle <[EMAIL PROTECTED]> |
+ | Wez Furlong <[EMAIL PROTECTED]>
|
+----------------------------------------------------------------------+
*/
-/* $Id: mysql_driver.c,v 1.50 2005/07/02 21:01:38 wez Exp $ */
+/* $Id: mysql_driver.c,v 1.51 2005/07/03 02:20:08 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -46,9 +47,10 @@
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
pdo_error_type *pdo_err;
pdo_mysql_error_info *einfo;
+ pdo_mysql_stmt *S = NULL;
if (stmt) {
- pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
+ S = (pdo_mysql_stmt*)stmt->driver_data;
pdo_err = &stmt->error_code;
einfo = &S->einfo;
} else {
@@ -69,14 +71,30 @@
if (2014 != einfo->errcode) {
einfo->errmsg = pestrdup(mysql_error(H->server),
dbh->is_persistent);
} else {
- einfo->errmsg = pestrdup("Cannot execute queries, while
other unbuffered queries are active. To enable query buffering set
PDO_MYSQL_ATTR_USE_BUFFERED_QUERY attribute.", dbh->is_persistent);
+ einfo->errmsg = pestrdup(
+ "Cannot execute queries while other unbuffered
queries are active. "
+ "Consider using PDOStatement::fetchAll().
Alternatively, if your code "
+ "is only ever going to run against mysql, you
may enable query "
+ "buffering by setting the
PDO_MYSQL_ATTR_USE_BUFFERED_QUERY attribute.",
+ dbh->is_persistent);
}
} else { /* no error */
strcpy(*pdo_err, PDO_ERR_NONE);
return 0;
}
+#if HAVE_MYSQL_SQLSTATE
+# if HAVE_MYSQL_STMT_PREPARE
+ if (S && S->stmt) {
+ strcpy(*pdo_err, mysql_stmt_sqlstate(S->stmt));
+ } else
+# endif
+ {
+ strcpy(*pdo_err, mysql_sqlstate(H->server));
+ }
+#else
strcpy(*pdo_err, pdo_mysql_get_sqlstate(einfo->errcode));
+#endif
if (!dbh->methods) {
zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
"SQLSTATE[%s] [%d] %s",
@@ -131,13 +149,67 @@
{
pdo_mysql_db_handle *H = (pdo_mysql_db_handle *)dbh->driver_data;
pdo_mysql_stmt *S = ecalloc(1, sizeof(pdo_mysql_stmt));
-
+#if HAVE_MYSQL_STMT_PREPARE
+ char *nsql = NULL;
+ int nsql_len = 0;
+ int ret;
+#endif
+
S->H = H;
- S->result = NULL;
-
stmt->driver_data = S;
stmt->methods = &mysql_stmt_methods;
+
+ /* TODO: add runtime check to determine if the server we are talking to
supports
+ * prepared statements; if it doesn't, we should set
stmt->supports_placeholders
+ * to PDO_PLACEHOLDER_NONE, and have the rest of the code look at
S->stmt to
+ * determine if we're using real prepared statements or the PDO
emulated version */
+#if HAVE_MYSQL_STMT_PREPARE
+ stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL;
+ ret = pdo_parse_params(stmt, (char*)sql, sql_len, &nsql, &nsql_len
TSRMLS_CC);
+
+ if (ret == 1) {
+ /* query was rewritten */
+ sql = nsql;
+ sql_len = nsql_len;
+ } else if (ret == -1) {
+ /* failed to parse */
+ strcpy(dbh->error_code, stmt->error_code);
+ return 0;
+ }
+
+ S->stmt = mysql_stmt_init(H->server);
+ if (!S->stmt) {
+ pdo_mysql_error(dbh);
+ if (nsql) {
+ efree(nsql);
+ }
+ return 0;
+ }
+
+ if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
+ /* TODO: might need to pull statement specific info here? */
+ pdo_mysql_error(dbh);
+ if (nsql) {
+ efree(nsql);
+ }
+ return 0;
+ }
+
+ S->num_params = mysql_stmt_param_count(S->stmt);
+
+ if (S->num_params) {
+ S->params = ecalloc(S->num_params, sizeof(MYSQL_BIND));
+ S->in_null = ecalloc(S->num_params, sizeof(my_bool));
+ S->in_length = ecalloc(S->num_params, sizeof(unsigned long));
+ }
+
+ dbh->alloc_own_columns = 1;
+
+ return 1;
+
+#else
stmt->supports_placeholders = PDO_PLACEHOLDER_NONE;
+#endif
return 1;
}
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/mysql_statement.c?r1=1.27&r2=1.28&ty=u
Index: php-src/ext/pdo_mysql/mysql_statement.c
diff -u php-src/ext/pdo_mysql/mysql_statement.c:1.27
php-src/ext/pdo_mysql/mysql_statement.c:1.28
--- php-src/ext/pdo_mysql/mysql_statement.c:1.27 Sat Jul 2 17:01:38 2005
+++ php-src/ext/pdo_mysql/mysql_statement.c Sat Jul 2 22:20:08 2005
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
+ | Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -13,10 +13,11 @@
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: George Schlossnagle <[EMAIL PROTECTED]> |
+ | Wez Furlong <[EMAIL PROTECTED]>
|
+----------------------------------------------------------------------+
*/
-/* $Id: mysql_statement.c,v 1.27 2005/07/02 21:01:38 wez Exp $ */
+/* $Id: mysql_statement.c,v 1.28 2005/07/03 02:20:08 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -44,6 +45,22 @@
efree(S->einfo.errmsg);
S->einfo.errmsg = NULL;
}
+#if HAVE_MYSQL_STMT_PREPARE
+ if (S->stmt) {
+ mysql_stmt_close(S->stmt);
+ S->stmt = NULL;
+ }
+ if (S->params) {
+ efree(S->params);
+ efree(S->in_null);
+ efree(S->in_length);
+ }
+ if (S->bound_result) {
+ efree(S->bound_result);
+ efree(S->out_null);
+ efree(S->out_length);
+ }
+#endif
efree(S);
return 1;
}
@@ -53,7 +70,52 @@
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
pdo_mysql_db_handle *H = S->H;
my_ulonglong row_count;
+#if HAVE_MYSQL_STMT_PREPARE
+ int i;
+ if (S->stmt) {
+ /* (re)bind the parameters */
+ if (mysql_stmt_bind_param(S->stmt, S->params)) {
+ pdo_mysql_error_stmt(stmt);
+ return 0;
+ }
+
+ if (mysql_stmt_execute(S->stmt)) {
+ pdo_mysql_error_stmt(stmt);
+ return 0;
+ }
+
+ if (!stmt->executed) {
+ /* figure out the result set format, if any */
+ S->result = mysql_stmt_result_metadata(S->stmt);
+ if (S->result) {
+ S->fields = mysql_fetch_fields(S->result);
+ stmt->column_count =
(int)mysql_num_fields(S->result);
+
+ S->bound_result = ecalloc(stmt->column_count,
sizeof(MYSQL_BIND));
+ S->out_null = ecalloc(stmt->column_count,
sizeof(my_bool));
+ S->out_length = ecalloc(stmt->column_count,
sizeof(unsigned long));
+
+ /* summon memory to hold the row */
+ for (i = 0; i < stmt->column_count; i++) {
+ S->bound_result[i].buffer_length =
S->fields[i].length;
+ S->bound_result[i].buffer =
emalloc(S->bound_result[i].buffer_length);
+ S->bound_result[i].is_null =
&S->out_null[i];
+ S->bound_result[i].length =
&S->out_length[i];
+ S->bound_result[i].buffer_type =
MYSQL_TYPE_STRING;
+ }
+
+ if (mysql_stmt_bind_result(S->stmt,
S->bound_result)) {
+ pdo_mysql_error_stmt(stmt);
+ return 0;
+ }
+ }
+ }
+
+ stmt->row_count = mysql_stmt_affected_rows(S->stmt);
+ return 1;
+ }
+#endif
/* ensure that we free any previous unfetched results */
if (S->result) {
mysql_free_result(S->result);
@@ -93,13 +155,12 @@
return 1;
}
-#if HAVE_MYSQL_NEXT_RESULT
static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt TSRMLS_DC)
{
+#if HAVE_MYSQL_NEXT_RESULT
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
pdo_mysql_db_handle *H = S->H;
my_ulonglong row_count;
- int debug=0;
int ret;
/* ensure that we free any previous unfetched results */
@@ -129,13 +190,79 @@
S->fields = mysql_fetch_fields(S->result);
return 1;
}
-}
+#else
+ strcpy(stmt->error_code, "HYC00");
+ return 0;
#endif
+}
static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct
pdo_bound_param_data *param,
enum pdo_param_event event_type TSRMLS_DC)
{
+#if HAVE_MYSQL_STMT_PREPARE
+ pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
+ MYSQL_BIND *b;
+
+ if (S->stmt && param->is_param) {
+ switch (event_type) {
+ case PDO_PARAM_EVT_ALLOC:
+ /* sanity check parameter number range */
+ if (param->paramno < 0 || param->paramno >=
S->num_params) {
+ strcpy(stmt->error_code, "HY093");
+ return 0;
+ }
+ b = &S->params[param->paramno];
+ param->driver_data = b;
+ b->is_null = &S->in_null[param->paramno];
+ b->length = &S->in_length[param->paramno];
+ return 1;
+
+ case PDO_PARAM_EVT_EXEC_PRE:
+ b = (MYSQL_BIND*)param->driver_data;
+
+ if (PDO_PARAM_TYPE(param->param_type) ==
PDO_PARAM_NULL ||
+ Z_TYPE_P(param->parameter) ==
IS_NULL) {
+ *b->is_null = 1;
+ b->buffer_type = MYSQL_TYPE_STRING;
+ b->buffer = NULL;
+ b->buffer_length = 0;
+ *b->length = 0;
+ return 1;
+ }
+
+ switch (PDO_PARAM_TYPE(param->param_type)) {
+ case PDO_PARAM_LOB:
+ case PDO_PARAM_STMT:
+ return 0;
+ default:
+ ;
+ }
+
+ switch (Z_TYPE_P(param->parameter)) {
+ case IS_STRING:
+ b->buffer_type =
MYSQL_TYPE_STRING;
+ b->buffer =
Z_STRVAL_P(param->parameter);
+ b->buffer_length =
Z_STRLEN_P(param->parameter);
+ *b->length =
Z_STRLEN_P(param->parameter);
+ return 1;
+
+ case IS_LONG:
+ b->buffer_type =
MYSQL_TYPE_LONG;
+ b->buffer =
&Z_LVAL_P(param->parameter);
+ return 1;
+
+ case IS_DOUBLE:
+ b->buffer_type =
MYSQL_TYPE_DOUBLE;
+ b->buffer =
&Z_DVAL_P(param->parameter);
+ return 1;
+
+ default:
+ return 0;
+ }
+ }
+ }
+#endif
return 1;
}
@@ -143,6 +270,29 @@
enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
{
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
+#if HAVE_MYSQL_STMT_PREPARE
+ int ret;
+
+ if (S->stmt) {
+ ret = mysql_stmt_fetch(S->stmt);
+
+#ifdef MYSQL_DATA_TRUNCATED
+ if (ret == MYSQL_DATA_TRUNCATED) {
+ ret = 0;
+ }
+#endif
+
+ if (ret) {
+ if (ret != MYSQL_NO_DATA) {
+ pdo_mysql_error_stmt(stmt);
+ }
+ return 0;
+ }
+
+ return 1;
+ }
+#endif
+
if (!S->result) {
return 0;
}
@@ -177,13 +327,13 @@
if (cols[0].name) {
return 1;
}
- for(i=0; i < stmt->column_count; i++) {
+ for (i=0; i < stmt->column_count; i++) {
int namelen;
namelen = strlen(S->fields[i].name);
cols[i].precision = S->fields[i].decimals;
cols[i].maxlen = S->fields[i].length;
cols[i].namelen = namelen;
- cols[i].name = estrndup(S->fields[i].name, namelen + 1);
+ cols[i].name = estrndup(S->fields[i].name, namelen);
cols[i].param_type = PDO_PARAM_STR;
}
return 1;
@@ -193,13 +343,31 @@
{
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
- if (S->current_data == NULL || !S->result) {
- return 0;
+#if HAVE_MYSQL_STMT_PREPARE
+ if (!S->stmt) {
+#endif
+ if (S->current_data == NULL || !S->result) {
+ return 0;
+ }
+#if HAVE_MYSQL_STMT_PREPARE
}
+#endif
if (colno >= stmt->column_count) {
/* error invalid column */
return 0;
}
+#if HAVE_MYSQL_STMT_PREPARE
+ if (S->stmt) {
+ if (S->out_null[colno]) {
+ *ptr = NULL;
+ *len = 0;
+ return 1;
+ }
+ *ptr = S->bound_result[colno].buffer;
+ *len = S->out_length[colno];
+ return 1;
+ }
+#endif
*ptr = S->current_data[colno];
*len = S->current_lengths[colno];
return 1;
@@ -297,9 +465,7 @@
NULL, /* set_attr */
NULL, /* get_attr */
pdo_mysql_stmt_col_meta,
-#if HAVE_MYSQL_NEXT_RESULT
pdo_mysql_stmt_next_rowset
-#endif
};
/*
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/pdo_mysql.c?r1=1.6&r2=1.7&ty=u
Index: php-src/ext/pdo_mysql/pdo_mysql.c
diff -u php-src/ext/pdo_mysql/pdo_mysql.c:1.6
php-src/ext/pdo_mysql/pdo_mysql.c:1.7
--- php-src/ext/pdo_mysql/pdo_mysql.c:1.6 Fri Jun 24 15:45:57 2005
+++ php-src/ext/pdo_mysql/pdo_mysql.c Sat Jul 2 22:20:08 2005
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
+ | Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: pdo_mysql.c,v 1.6 2005/06/24 19:45:57 iliaa Exp $ */
+/* $Id: pdo_mysql.c,v 1.7 2005/07/03 02:20:08 wez Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/php_pdo_mysql.h?r1=1.2&r2=1.3&ty=u
Index: php-src/ext/pdo_mysql/php_pdo_mysql.h
diff -u php-src/ext/pdo_mysql/php_pdo_mysql.h:1.2
php-src/ext/pdo_mysql/php_pdo_mysql.h:1.3
--- php-src/ext/pdo_mysql/php_pdo_mysql.h:1.2 Wed May 19 10:23:59 2004
+++ php-src/ext/pdo_mysql/php_pdo_mysql.h Sat Jul 2 22:20:08 2005
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
+ | Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_pdo_mysql.h,v 1.2 2004/05/19 14:23:59 edink Exp $ */
+/* $Id: php_pdo_mysql.h,v 1.3 2005/07/03 02:20:08 wez Exp $ */
#ifndef PHP_PDO_MYSQL_H
#define PHP_PDO_MYSQL_H
http://cvs.php.net/diff.php/php-src/ext/pdo_mysql/php_pdo_mysql_int.h?r1=1.14&r2=1.15&ty=u
Index: php-src/ext/pdo_mysql/php_pdo_mysql_int.h
diff -u php-src/ext/pdo_mysql/php_pdo_mysql_int.h:1.14
php-src/ext/pdo_mysql/php_pdo_mysql_int.h:1.15
--- php-src/ext/pdo_mysql/php_pdo_mysql_int.h:1.14 Fri Jun 24 15:45:57 2005
+++ php-src/ext/pdo_mysql/php_pdo_mysql_int.h Sat Jul 2 22:20:08 2005
@@ -2,7 +2,7 @@
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2004 The PHP Group |
+ | Copyright (c) 1997-2005 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.0 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -13,10 +13,11 @@
| [EMAIL PROTECTED] so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: George Schlossnagle <[EMAIL PROTECTED]> |
+ | Wez Furlong <[EMAIL PROTECTED]>
|
+----------------------------------------------------------------------+
*/
-/* $Id: php_pdo_mysql_int.h,v 1.14 2005/06/24 19:45:57 iliaa Exp $ */
+/* $Id: php_pdo_mysql_int.h,v 1.15 2005/07/03 02:20:08 wez Exp $ */
#ifndef PHP_PDO_MYSQL_INT_H
#define PHP_PDO_MYSQL_INT_H
@@ -52,14 +53,20 @@
MYSQL_ROW current_data;
long *current_lengths;
pdo_mysql_error_info einfo;
-} pdo_mysql_stmt;
+#if HAVE_MYSQL_STMT_PREPARE
+ MYSQL_STMT *stmt;
+
+ int num_params;
+ MYSQL_BIND *params;
+ my_bool *in_null;
+ unsigned long *in_length;
+
+ MYSQL_BIND *bound_result;
+ my_bool *out_null;
+ unsigned long *out_length;
-typedef struct {
- char *repr;
- long repr_len;
- int mysql_type;
- void *thing; /* for LOBS, REFCURSORS etc. */
-} pdo_mysql_bound_param;
+#endif
+} pdo_mysql_stmt;
extern pdo_driver_t pdo_mysql_driver;
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php