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