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

Reply via email to