Back to index

php5  5.3.10
mysqlnd_ps_codec.c
Go to the documentation of this file.
00001 /*
00002   +----------------------------------------------------------------------+
00003   | PHP Version 5                                                        |
00004   +----------------------------------------------------------------------+
00005   | Copyright (c) 2006-2012 The PHP Group                                |
00006   +----------------------------------------------------------------------+
00007   | This source file is subject to version 3.01 of the PHP license,      |
00008   | that is bundled with this package in the file LICENSE, and is        |
00009   | available through the world-wide-web at the following url:           |
00010   | http://www.php.net/license/3_01.txt                                  |
00011   | If you did not receive a copy of the PHP license and are unable to   |
00012   | obtain it through the world-wide-web, please send a note to          |
00013   | license@php.net so we can mail you a copy immediately.               |
00014   +----------------------------------------------------------------------+
00015   | Authors: Georg Richter <georg@mysql.com>                             |
00016   |          Andrey Hristov <andrey@mysql.com>                           |
00017   |          Ulf Wendel <uwendel@mysql.com>                              |
00018   +----------------------------------------------------------------------+
00019 */
00020 
00021 /* $Id: mysqlnd_ps_codec.c 321634 2012-01-01 13:15:04Z felipe $ */
00022 #include "php.h"
00023 #include "mysqlnd.h"
00024 #include "mysqlnd_wireprotocol.h"
00025 #include "mysqlnd_priv.h"
00026 #include "mysqlnd_debug.h"
00027 
00028 #define MYSQLND_SILENT
00029 
00030 
00031 enum mysqlnd_timestamp_type
00032 {
00033   MYSQLND_TIMESTAMP_NONE= -2,
00034   MYSQLND_TIMESTAMP_ERROR= -1,
00035   MYSQLND_TIMESTAMP_DATE= 0,
00036   MYSQLND_TIMESTAMP_DATETIME= 1,
00037   MYSQLND_TIMESTAMP_TIME= 2
00038 };
00039 
00040 
00041 struct st_mysqlnd_time
00042 {
00043   unsigned int  year, month, day, hour, minute, second;
00044   unsigned long second_part;
00045   zend_bool     neg;
00046   enum mysqlnd_timestamp_type time_type;
00047 };
00048 
00049 
00050 struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
00051 
00052 #define MYSQLND_PS_SKIP_RESULT_W_LEN      -1
00053 #define MYSQLND_PS_SKIP_RESULT_STR        -2
00054 
00055 /* {{{ ps_fetch_from_1_to_8_bytes */
00056 void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
00057                                                         unsigned int pack_len, zend_uchar **row, zend_bool as_unicode,
00058                                                         unsigned int byte_count TSRMLS_DC)
00059 {
00060        char tmp[22];
00061        size_t tmp_len = 0;
00062        zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
00063        DBG_ENTER("ps_fetch_from_1_to_8_bytes");
00064        DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count);
00065        if (field->flags & UNSIGNED_FLAG) {
00066               uint64_t uval = 0;
00067 
00068               switch (byte_count) {
00069                      case 8:uval = is_bit? (uint64_t) bit_uint8korr(*row):(uint64_t) uint8korr(*row);break;
00070                      case 7:uval = bit_uint7korr(*row);break;
00071                      case 6:uval = bit_uint6korr(*row);break;
00072                      case 5:uval = bit_uint5korr(*row);break;
00073                      case 4:uval = is_bit? (uint64_t) bit_uint4korr(*row):(uint64_t) uint4korr(*row);break;
00074                      case 3:uval = is_bit? (uint64_t) bit_uint3korr(*row):(uint64_t) uint3korr(*row);break;
00075                      case 2:uval = is_bit? (uint64_t) bit_uint2korr(*row):(uint64_t) uint2korr(*row);break;
00076                      case 1:uval = (uint64_t) uint1korr(*row);break;
00077               }
00078 
00079 #if SIZEOF_LONG==4
00080               if (uval > INT_MAX) {
00081                      DBG_INF("stringify");
00082                      tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
00083               } else 
00084 #endif /* #if SIZEOF_LONG==4 */
00085               {
00086                      if (byte_count < 8 || uval <= L64(9223372036854775807)) {
00087                             ZVAL_LONG(zv, (long) uval); /* the cast is safe, we are in the range */
00088                      } else {
00089                             DBG_INF("stringify");
00090                             tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
00091                      }
00092               }
00093        } else {
00094               /* SIGNED */
00095               int64_t lval = 0;
00096               switch (byte_count) {
00097                      case 8:lval = (int64_t) sint8korr(*row);break;
00098                      /*
00099                        7, 6 and 5 are not possible.
00100                        BIT is only unsigned, thus only uint5|6|7 macroses exist
00101                      */
00102                      case 4:lval = (int64_t) sint4korr(*row);break;
00103                      case 3:lval = (int64_t) sint3korr(*row);break;
00104                      case 2:lval = (int64_t) sint2korr(*row);break;
00105                      case 1:lval = (int64_t) *(int8_t*)*row;break;
00106               }
00107 
00108 #if SIZEOF_LONG==4
00109               if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) {
00110                      DBG_INF("stringify");
00111                      tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
00112               } else
00113 #endif /* SIZEOF */
00114               {
00115                      ZVAL_LONG(zv, (long) lval); /* the cast is safe, we are in the range */
00116               }
00117        }
00118 
00119        if (tmp_len) {
00120 #if MYSQLND_UNICODE
00121               if (as_unicode) {
00122                      DBG_INF("stringify");
00123                      ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE);
00124               } else
00125 #endif
00126               {
00127                      DBG_INF("stringify");
00128                      ZVAL_STRINGL(zv, tmp, tmp_len, 1);
00129               }
00130        }
00131        (*row)+= byte_count;
00132        DBG_VOID_RETURN;
00133 }
00134 /* }}} */
00135 
00136 
00137 /* {{{ ps_fetch_null */
00138 static
00139 void ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field,
00140                                unsigned int pack_len, zend_uchar **row,
00141                                zend_bool as_unicode TSRMLS_DC)
00142 {
00143        ZVAL_NULL(zv);
00144 }
00145 /* }}} */
00146 
00147 
00148 /* {{{ ps_fetch_int8 */
00149 static
00150 void ps_fetch_int8(zval *zv, const MYSQLND_FIELD * const field,
00151                                unsigned int pack_len, zend_uchar **row,
00152                                zend_bool as_unicode TSRMLS_DC)
00153 {
00154        ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1 TSRMLS_CC);
00155 }
00156 /* }}} */
00157 
00158 
00159 /* {{{ ps_fetch_int16 */
00160 static
00161 void ps_fetch_int16(zval *zv, const MYSQLND_FIELD * const field,
00162                                    unsigned int pack_len, zend_uchar **row,
00163                                    zend_bool as_unicode TSRMLS_DC)
00164 {
00165        ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2 TSRMLS_CC);
00166 }
00167 /* }}} */
00168 
00169 
00170 /* {{{ ps_fetch_int32 */
00171 static
00172 void ps_fetch_int32(zval *zv, const MYSQLND_FIELD * const field,
00173                                    unsigned int pack_len, zend_uchar **row,
00174                                    zend_bool as_unicode TSRMLS_DC)
00175 {
00176        ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4 TSRMLS_CC);
00177 }
00178 /* }}} */
00179 
00180 
00181 /* {{{ ps_fetch_int64 */
00182 static
00183 void ps_fetch_int64(zval *zv, const MYSQLND_FIELD * const field,
00184                                    unsigned int pack_len, zend_uchar **row,
00185                                    zend_bool as_unicode TSRMLS_DC)
00186 {
00187        ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8 TSRMLS_CC);
00188 }
00189 /* }}} */
00190 
00191 
00192 /* {{{ ps_fetch_float */
00193 static
00194 void ps_fetch_float(zval *zv, const MYSQLND_FIELD * const field,
00195                                    unsigned int pack_len, zend_uchar **row,
00196                                    zend_bool as_unicode TSRMLS_DC)
00197 {
00198        float value;
00199        DBG_ENTER("ps_fetch_float");
00200        float4get(value, *row);
00201        ZVAL_DOUBLE(zv, value);
00202        (*row)+= 4;
00203        DBG_INF_FMT("value=%f", value);
00204        DBG_VOID_RETURN;
00205 }
00206 /* }}} */
00207 
00208 
00209 /* {{{ ps_fetch_double */
00210 static
00211 void ps_fetch_double(zval *zv, const MYSQLND_FIELD * const field,
00212                                    unsigned int pack_len, zend_uchar **row,
00213                                    zend_bool as_unicode TSRMLS_DC)
00214 {
00215        double value;
00216        DBG_ENTER("ps_fetch_double");
00217        float8get(value, *row);
00218        ZVAL_DOUBLE(zv, value);
00219        (*row)+= 8;
00220        DBG_INF_FMT("value=%f", value);
00221        DBG_VOID_RETURN;
00222 }
00223 /* }}} */
00224 
00225 
00226 /* {{{ ps_fetch_time */
00227 static
00228 void ps_fetch_time(zval *zv, const MYSQLND_FIELD * const field,
00229                                unsigned int pack_len, zend_uchar **row,
00230                                zend_bool as_unicode TSRMLS_DC)
00231 {
00232        struct st_mysqlnd_time t;
00233        unsigned int length; /* First byte encodes the length*/
00234        char * value;
00235        DBG_ENTER("ps_fetch_time");
00236 
00237        if ((length = php_mysqlnd_net_field_length(row))) {
00238               zend_uchar *to= *row;
00239 
00240               t.time_type = MYSQLND_TIMESTAMP_TIME;
00241               t.neg                = (zend_bool) to[0];
00242 
00243               t.day                = (unsigned long) sint4korr(to+1);
00244               t.hour               = (unsigned int) to[5];
00245               t.minute             = (unsigned int) to[6];
00246               t.second             = (unsigned int) to[7];
00247               t.second_part = (length > 8) ? (unsigned long) sint4korr(to+8) : 0;
00248               t.year               = t.month= 0;
00249               if (t.day) {
00250                      /* Convert days to hours at once */
00251                      t.hour += t.day*24;
00252                      t.day  = 0;
00253               }
00254 
00255               (*row) += length;
00256        } else {
00257               memset(&t, 0, sizeof(t));
00258               t.time_type = MYSQLND_TIMESTAMP_TIME;
00259        }
00260 
00261        /*
00262          QQ : How to make this unicode without copying two times the buffer -
00263          Unicode equivalent of spprintf?
00264        */
00265        length = spprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
00266 
00267        DBG_INF_FMT("%s", value);
00268 #if MYSQLND_UNICODE
00269        if (!as_unicode) {
00270 #endif
00271               ZVAL_STRINGL(zv, value, length, 1);
00272               efree(value);  /* allocated by spprintf */
00273 #if MYSQLND_UNICODE
00274        } else {
00275               ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
00276        }
00277 #endif
00278        DBG_VOID_RETURN;
00279 }
00280 /* }}} */
00281 
00282 
00283 /* {{{ ps_fetch_date */
00284 static
00285 void ps_fetch_date(zval *zv, const MYSQLND_FIELD * const field,
00286                                unsigned int pack_len, zend_uchar **row,
00287                                zend_bool as_unicode TSRMLS_DC)
00288 {
00289        struct st_mysqlnd_time t = {0};
00290        unsigned int length; /* First byte encodes the length*/
00291        char * value;
00292        DBG_ENTER("ps_fetch_date");
00293 
00294        if ((length = php_mysqlnd_net_field_length(row))) {
00295               zend_uchar *to= *row;
00296 
00297               t.time_type= MYSQLND_TIMESTAMP_DATE;
00298               t.neg= 0;
00299 
00300               t.second_part = t.hour = t.minute = t.second = 0;
00301 
00302               t.year = (unsigned int) sint2korr(to);
00303               t.month = (unsigned int) to[2];
00304               t.day  = (unsigned int) to[3];
00305 
00306               (*row)+= length;
00307        } else {
00308               memset(&t, 0, sizeof(t));
00309               t.time_type = MYSQLND_TIMESTAMP_DATE;
00310        }
00311 
00312        /*
00313          QQ : How to make this unicode without copying two times the buffer -
00314          Unicode equivalent of spprintf?
00315        */
00316        length = spprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
00317 
00318        DBG_INF_FMT("%s", value);
00319 #if MYSQLND_UNICODE
00320        if (!as_unicode) {
00321 #endif
00322               ZVAL_STRINGL(zv, value, length, 1);
00323               efree(value); /* allocated by spprintf */
00324 #if MYSQLND_UNICODE
00325        } else {
00326               ZVAL_UTF8_STRINGL(zv, value, length, ZSTR_AUTOFREE);
00327        }
00328 #endif
00329        DBG_VOID_RETURN;
00330 }
00331 /* }}} */
00332 
00333 
00334 /* {{{ ps_fetch_datetime */
00335 static
00336 void ps_fetch_datetime(zval *zv, const MYSQLND_FIELD * const field,
00337                                       unsigned int pack_len, zend_uchar **row,
00338                                       zend_bool as_unicode TSRMLS_DC)
00339 {
00340        struct st_mysqlnd_time t;
00341        unsigned int length; /* First byte encodes the length*/
00342        char * value;
00343        DBG_ENTER("ps_fetch_datetime");
00344 
00345        if ((length = php_mysqlnd_net_field_length(row))) {
00346               zend_uchar *to= *row;
00347 
00348               t.time_type = MYSQLND_TIMESTAMP_DATETIME;
00349               t.neg   = 0;
00350 
00351               t.year  = (unsigned int) sint2korr(to);
00352               t.month = (unsigned int) to[2];
00353               t.day   = (unsigned int) to[3];
00354 
00355               if (length > 4) {
00356                      t.hour  = (unsigned int) to[4];
00357                      t.minute = (unsigned int) to[5];
00358                      t.second = (unsigned int) to[6];
00359               } else {
00360                      t.hour = t.minute = t.second= 0;
00361               }
00362               t.second_part = (length > 7) ? (unsigned long) sint4korr(to+7) : 0;
00363 
00364               (*row)+= length;
00365        } else {
00366               memset(&t, 0, sizeof(t));
00367               t.time_type = MYSQLND_TIMESTAMP_DATETIME;
00368        }
00369 
00370        /*
00371          QQ : How to make this unicode without copying two times the buffer -
00372          Unicode equivalent of spprintf?
00373        */
00374        length = spprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u",
00375                                      t.year, t.month, t.day, t.hour, t.minute, t.second);
00376 
00377        DBG_INF_FMT("%s", value);
00378 #if MYSQLND_UNICODE
00379        if (!as_unicode) {
00380 #endif
00381               ZVAL_STRINGL(zv, value, length, 1);
00382               efree(value); /* allocated by spprintf */
00383 #if MYSQLND_UNICODE
00384        } else {
00385               ZVAL_UTF8_STRINGL(zv, to, length, ZSTR_AUTOFREE);
00386        }
00387 #endif
00388        DBG_VOID_RETURN;
00389 }
00390 /* }}} */
00391 
00392 
00393 /* {{{ ps_fetch_string */
00394 static
00395 void ps_fetch_string(zval *zv, const MYSQLND_FIELD * const field,
00396                                     unsigned int pack_len, zend_uchar **row,
00397                                     zend_bool as_unicode TSRMLS_DC)
00398 {
00399        /*
00400          For now just copy, before we make it possible
00401          to write \0 to the row buffer
00402        */
00403        unsigned long length = php_mysqlnd_net_field_length(row);
00404        DBG_ENTER("ps_fetch_string");
00405        DBG_INF_FMT("len = %lu", length);
00406 #if MYSQLND_UNICODE
00407        if (field->charsetnr == MYSQLND_BINARY_CHARSET_NR) {
00408               DBG_INF("Binary charset");
00409               ZVAL_STRINGL(zv, (char *)*row, length, 1);
00410        } else {
00411               DBG_INF_FMT("copying from the row buffer");
00412               ZVAL_UTF8_STRINGL(zv, (char*)*row, length, ZSTR_DUPLICATE);
00413        }
00414 #else
00415        DBG_INF("copying from the row buffer");
00416        ZVAL_STRINGL(zv, (char *)*row, length, 1);
00417 #endif
00418 
00419        (*row) += length;
00420        DBG_VOID_RETURN;
00421 }
00422 /* }}} */
00423 
00424 
00425 /* {{{ ps_fetch_bit */
00426 static
00427 void ps_fetch_bit(zval *zv, const MYSQLND_FIELD * const field,
00428                               unsigned int pack_len, zend_uchar **row,
00429                               zend_bool as_unicode TSRMLS_DC)
00430 {
00431        unsigned long length= php_mysqlnd_net_field_length(row);
00432        ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, length TSRMLS_CC);
00433 }
00434 /* }}} */
00435 
00436 
00437 /* {{{ _mysqlnd_init_ps_fetch_subsystem */
00438 void _mysqlnd_init_ps_fetch_subsystem()
00439 {
00440        memset(mysqlnd_ps_fetch_functions, 0, sizeof(mysqlnd_ps_fetch_functions));
00441        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].func        = ps_fetch_null;
00442        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len    = 0;
00443        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].php_type    = IS_NULL;
00444        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].can_ret_as_str_in_uni     = TRUE;
00445 
00446        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func        = ps_fetch_int8;
00447        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len    = 1;
00448        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type    = IS_LONG;
00449        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni     = TRUE;
00450 
00451        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func              = ps_fetch_int16;
00452        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len   = 2;
00453        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type   = IS_LONG;
00454        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni    = TRUE;
00455 
00456        mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func        = ps_fetch_int16;
00457        mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len    = 2;
00458        mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type    = IS_LONG;
00459        mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni     = TRUE;
00460 
00461        mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func              = ps_fetch_int32;
00462        mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len   = 4;
00463        mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type   = IS_LONG;
00464        mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni    = TRUE;
00465 
00466        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func        = ps_fetch_int32;
00467        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len    = 4;
00468        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type    = IS_LONG;
00469        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni     = TRUE;
00470 
00471        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func    = ps_fetch_int64;
00472        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
00473        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_LONG;
00474        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni = TRUE;
00475 
00476        mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func              = ps_fetch_float;
00477        mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len   = 4;
00478        mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].php_type   = IS_DOUBLE;
00479        mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].can_ret_as_str_in_uni    = TRUE;
00480 
00481        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func             = ps_fetch_double;
00482        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len  = 8;
00483        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].php_type  = IS_DOUBLE;
00484        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].can_ret_as_str_in_uni   = TRUE;
00485 
00486        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].func        = ps_fetch_time;
00487        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len    = MYSQLND_PS_SKIP_RESULT_W_LEN;
00488        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].php_type    = IS_STRING;
00489        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].can_ret_as_str_in_uni     = TRUE;
00490 
00491        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].func        = ps_fetch_date;
00492        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len    = MYSQLND_PS_SKIP_RESULT_W_LEN;
00493        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].php_type    = IS_STRING;
00494        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].can_ret_as_str_in_uni     = TRUE;
00495 
00496        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func            = ps_fetch_string;
00497        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
00498        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].php_type = IS_STRING;
00499        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].can_ret_as_str_in_uni  = TRUE;
00500 
00501        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].func    = ps_fetch_datetime;
00502        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
00503        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].php_type= IS_STRING;
00504        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].can_ret_as_str_in_uni = TRUE;
00505 
00506        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func   = ps_fetch_datetime;
00507        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
00508        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].php_type= IS_STRING;
00509        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].can_ret_as_str_in_uni       = TRUE;
00510 
00511        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func   = ps_fetch_string;
00512        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
00513        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].php_type = IS_STRING;
00514        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].is_possibly_blob = TRUE;
00515        mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].can_ret_as_str_in_uni       = TRUE;
00516 
00517        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].func        = ps_fetch_string;
00518        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len    = MYSQLND_PS_SKIP_RESULT_STR;
00519        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].php_type    = IS_STRING;
00520        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].is_possibly_blob = TRUE;
00521        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].can_ret_as_str_in_uni     = TRUE;
00522 
00523        mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func        = ps_fetch_string;
00524        mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len    = MYSQLND_PS_SKIP_RESULT_STR;
00525        mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].php_type    = IS_STRING;
00526        mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].is_possibly_blob = TRUE;
00527        mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].can_ret_as_str_in_uni     = TRUE;
00528 
00529        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func          = ps_fetch_string;
00530        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len      = MYSQLND_PS_SKIP_RESULT_STR;
00531        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].php_type      = IS_STRING;
00532        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].is_possibly_blob = TRUE;
00533        mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].can_ret_as_str_in_uni       = TRUE;
00534 
00535        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func         = ps_fetch_bit;
00536        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len     = 8;
00537        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type     = IS_LONG;
00538        mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE;
00539 
00540        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func         = ps_fetch_string;
00541        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len     = MYSQLND_PS_SKIP_RESULT_STR;
00542        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].php_type = IS_STRING;
00543        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].is_possibly_blob = TRUE;
00544 
00545        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func            = ps_fetch_string;
00546        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
00547        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].php_type = IS_STRING;
00548        mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].is_possibly_blob = TRUE;
00549 
00550        mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].func                    = ps_fetch_string;
00551        mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len         = MYSQLND_PS_SKIP_RESULT_STR;
00552        mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].php_type  = IS_STRING;
00553        mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].is_possibly_blob = TRUE;
00554 
00555        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func            = ps_fetch_string;
00556        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
00557        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].php_type = IS_STRING;
00558        mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].can_ret_as_str_in_uni  = TRUE;
00559 
00560        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func         = ps_fetch_string;
00561        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len     = MYSQLND_PS_SKIP_RESULT_STR;
00562        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].php_type     = IS_STRING;
00563        mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].can_ret_as_str_in_uni      = TRUE;
00564 
00565        mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].func        = ps_fetch_string;
00566        mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len    = MYSQLND_PS_SKIP_RESULT_STR;
00567        mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].php_type    = IS_STRING;
00568 
00569        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].func                = ps_fetch_string;
00570        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].pack_len            = MYSQLND_PS_SKIP_RESULT_STR;
00571        mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].php_type            = IS_STRING;
00572 
00573        mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func    = ps_fetch_string;
00574        mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
00575        mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].php_type= IS_STRING;
00576 }
00577 /* }}} */
00578 
00579 
00580 /* {{{ mysqlnd_stmt_copy_it */
00581 static enum_func_status
00582 mysqlnd_stmt_copy_it(zval *** copies, zval *original, unsigned int param_count, unsigned int current TSRMLS_DC)
00583 {
00584        if (!*copies) {
00585               *copies = mnd_ecalloc(param_count, sizeof(zval *));
00586        }
00587        if (*copies) {
00588               MAKE_STD_ZVAL((*copies)[current]);
00589               *(*copies)[current] = *original;
00590               Z_SET_REFCOUNT_P((*copies)[current], 1);
00591               zval_copy_ctor((*copies)[current]);
00592               return PASS;
00593        }
00594        return FAIL;
00595 }
00596 /* }}} */
00597 
00598 
00599 /* {{{ mysqlnd_stmt_execute_store_params */
00600 static enum_func_status
00601 mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len  TSRMLS_DC)
00602 {
00603        MYSQLND_STMT_DATA * stmt = s->data;
00604        unsigned int i = 0;
00605        zend_uchar * provided_buffer = *buf;
00606        size_t left = (*buf_len - (*p - *buf));
00607        size_t data_size = 0;
00608        zval **copies = NULL;/* if there are different types */
00609        enum_func_status ret = FAIL;
00610        int resend_types_next_time = 0;
00611        size_t null_byte_offset;
00612 
00613        DBG_ENTER("mysqlnd_stmt_execute_store_params");
00614 
00615        {
00616               unsigned int null_count = (stmt->param_count + 7) / 8;
00617               /* give it some reserved space - 20 bytes */
00618               if (left < (null_count + 20)) {
00619                      unsigned int offset = *p - *buf;
00620                      zend_uchar *tmp_buf;
00621                      *buf_len = offset + null_count + 20;
00622                      tmp_buf = mnd_emalloc(*buf_len);
00623                      if (!tmp_buf) {
00624                             SET_OOM_ERROR(stmt->error_info);
00625                             goto end;
00626                      }
00627                      memcpy(tmp_buf, *buf, offset);
00628                      if (*buf != provided_buffer) {
00629                             mnd_efree(*buf);
00630                      }
00631                      *buf = tmp_buf;
00632 
00633                      /* Update our pos pointer */
00634                      *p = *buf + offset;
00635               }
00636               /* put `null` bytes */
00637               null_byte_offset = *p - *buf;
00638               memset(*p, 0, null_count);
00639               *p += null_count;
00640        }
00641 
00642 /* 1. Store type information */
00643        /*
00644          check if need to send the types even if stmt->send_types_to_server is 0. This is because
00645          if we send "i" (42) then the type will be int and the server will expect int. However, if next
00646          time we try to send > LONG_MAX, the conversion to string will send a string and the server
00647          won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values
00648          occur, and force resend for the next execution.
00649        */
00650        for (i = 0; i < stmt->param_count; i++) {
00651               if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL &&
00652                      (stmt->param_bind[i].type == MYSQL_TYPE_LONG || stmt->param_bind[i].type == MYSQL_TYPE_LONGLONG))
00653               {
00654                      /* always copy the var, because we do many conversions */
00655                      if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
00656                             PASS != mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
00657                      {
00658                             SET_OOM_ERROR(stmt->error_info);
00659                             goto end;
00660                      }
00661                      /*
00662                        if it doesn't fit in a long send it as a string.
00663                        Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
00664                      */
00665                      if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
00666                             zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
00667                             convert_to_double_ex(&tmp_data);
00668                             if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) {
00669                                    stmt->send_types_to_server = resend_types_next_time = 1;
00670                             }
00671                      }
00672               }
00673        }
00674 
00675        int1store(*p, stmt->send_types_to_server); 
00676        (*p)++;
00677 
00678        if (stmt->send_types_to_server) {
00679               /* 2 bytes per type, and leave 20 bytes for future use */
00680               if (left < ((stmt->param_count * 2) + 20)) {
00681                      unsigned int offset = *p - *buf;
00682                      zend_uchar *tmp_buf;
00683                      *buf_len = offset + stmt->param_count * 2 + 20;
00684                      tmp_buf = mnd_emalloc(*buf_len);
00685                      if (!tmp_buf) {
00686                             SET_OOM_ERROR(stmt->error_info);
00687                             goto end;
00688                      }
00689                      memcpy(tmp_buf, *buf, offset);
00690                      if (*buf != provided_buffer) {
00691                             mnd_efree(*buf);
00692                      }
00693                      *buf = tmp_buf;
00694 
00695                      /* Update our pos pointer */
00696                      *p = *buf + offset;
00697               }
00698               for (i = 0; i < stmt->param_count; i++) {
00699                      short current_type = stmt->param_bind[i].type;
00700                      /* our types are not unsigned */
00701 #if SIZEOF_LONG==8  
00702                      if (current_type == MYSQL_TYPE_LONG) {
00703                             current_type = MYSQL_TYPE_LONGLONG;
00704                      }
00705 #endif
00706                      if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
00707                             /*
00708                               if it doesn't fit in a long send it as a string.
00709                               Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
00710                             */
00711                             if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
00712                                    zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
00713 
00714                                    convert_to_double_ex(&tmp_data);
00715                                    if (Z_DVAL_P(tmp_data) > LONG_MAX || Z_DVAL_P(tmp_data) < LONG_MIN) {
00716                                           convert_to_string_ex(&tmp_data);
00717                                           current_type = MYSQL_TYPE_VAR_STRING;
00718                                           /*
00719                                             don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING
00720                                             we force convert_to_long_ex in all cases, thus the type will be right in the next switch.
00721                                             if the type is however not long, then we will do a goto in the next switch.
00722                                             We want to preserve the original bind type given by the user. Thus, we do these hacks.
00723                                           */
00724                                    } else {
00725                                           convert_to_long_ex(&tmp_data);
00726                                    }
00727                             }
00728                      }
00729                      int2store(*p, current_type);
00730                      *p+= 2;
00731               }
00732        }
00733        stmt->send_types_to_server = resend_types_next_time;
00734 
00735 /* 2. Store data */
00736        /* 2.1 Calculate how much space we need */
00737        for (i = 0; i < stmt->param_count; i++) {
00738               unsigned int j;
00739               zval *the_var = stmt->param_bind[i].zv;
00740 
00741               if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
00742                      continue;
00743               }
00744               for (j = i + 1; j < stmt->param_count; j++) {
00745                      if (stmt->param_bind[j].zv == the_var) {
00746                             /* Double binding of the same zval, make a copy */
00747                             if (!copies || !copies[i]) {
00748                                    if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
00749                                           SET_OOM_ERROR(stmt->error_info);
00750                                           goto end;
00751                                    }
00752                             }
00753                             break; 
00754                      }
00755               }
00756 
00757               switch (stmt->param_bind[i].type) {
00758                      case MYSQL_TYPE_DOUBLE:
00759                             data_size += 8;
00760                             if (Z_TYPE_P(the_var) != IS_DOUBLE) {
00761                                    if (!copies || !copies[i]) {
00762                                           if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
00763                                                  SET_OOM_ERROR(stmt->error_info);
00764                                                  goto end;
00765                                           }
00766                                    }
00767                             }
00768                             break;
00769                      case MYSQL_TYPE_LONGLONG:
00770                             {
00771                                    zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
00772                                    if (Z_TYPE_P(tmp_data) == IS_STRING) {
00773                                           goto use_string;
00774                                    }
00775                                    convert_to_long_ex(&tmp_data);
00776                             }
00777                             data_size += 8;
00778                             break;
00779                      case MYSQL_TYPE_LONG:
00780                             {
00781                                    zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
00782                                    if (Z_TYPE_P(tmp_data) == IS_STRING) {
00783                                           goto use_string;
00784                                    }
00785                                    convert_to_long_ex(&tmp_data);
00786                             }
00787                             data_size += 4;
00788                             break;
00789                      case MYSQL_TYPE_LONG_BLOB:
00790                             if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
00791                                    /*
00792                                      User hasn't sent anything, we will send empty string.
00793                                      Empty string has length of 0, encoded in 1 byte. No real
00794                                      data will follows after it.
00795                                    */
00796                                    data_size++;
00797                             }
00798                             break;
00799                      case MYSQL_TYPE_VAR_STRING:
00800 use_string:
00801                             data_size += 8; /* max 8 bytes for size */
00802 #if MYSQLND_UNICODE
00803                             if (Z_TYPE_P(the_var) != IS_STRING || Z_TYPE_P(the_var) == IS_UNICODE)
00804 #else
00805                             if (Z_TYPE_P(the_var) != IS_STRING)
00806 #endif
00807                             {
00808                                    if (!copies || !copies[i]) {
00809                                           if (PASS != mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i TSRMLS_CC)) {
00810                                                  SET_OOM_ERROR(stmt->error_info);
00811                                                  goto end;
00812                                           }
00813                                    }
00814                                    the_var = copies[i];
00815 #if MYSQLND_UNICODE
00816                                    if (Z_TYPE_P(the_var) == IS_UNICODE) {
00817                                           zval_unicode_to_string_ex(the_var, UG(utf8_conv) TSRMLS_CC);
00818                                    }
00819 #endif
00820                             }
00821                             convert_to_string_ex(&the_var);
00822                             data_size += Z_STRLEN_P(the_var);
00823                             break;
00824               }
00825        }
00826 
00827        /* 2.2 Enlarge the buffer, if needed */
00828        left = (*buf_len - (*p - *buf));
00829        if (left < data_size) {
00830               unsigned int offset = *p - *buf;
00831               zend_uchar *tmp_buf;
00832               *buf_len = offset + data_size + 10; /* Allocate + 10 for safety */
00833               tmp_buf = mnd_emalloc(*buf_len);
00834               if (!tmp_buf) {
00835                      SET_OOM_ERROR(stmt->error_info);
00836                      goto end;
00837               }
00838               memcpy(tmp_buf, *buf, offset);
00839               /*
00840                 When too many columns the buffer provided to the function might not be sufficient.
00841                 In this case new buffer has been allocated above. When we allocate a buffer and then
00842                 allocate a bigger one here, we should free the first one.
00843               */
00844               if (*buf != provided_buffer) {
00845                      mnd_efree(*buf);
00846               }
00847               *buf = tmp_buf;
00848               /* Update our pos pointer */
00849               *p = *buf + offset;
00850        }
00851 
00852        /* 2.3 Store the actual data */
00853        for (i = 0; i < stmt->param_count; i++) {
00854               zval *data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
00855               /* Handle long data */
00856               if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
00857                      (*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
00858               } else {
00859                      switch (stmt->param_bind[i].type) {
00860                             case MYSQL_TYPE_DOUBLE:
00861                                    convert_to_double_ex(&data);
00862                                    float8store(*p, Z_DVAL_P(data));
00863                                    (*p) += 8;
00864                                    break;
00865                             case MYSQL_TYPE_LONGLONG:
00866                                    if (Z_TYPE_P(data) == IS_STRING) {
00867                                           goto send_string;
00868                                    }
00869                                    /* data has alreade been converted to long */
00870                                    int8store(*p, Z_LVAL_P(data));
00871                                    (*p) += 8;
00872                                    break;
00873                             case MYSQL_TYPE_LONG:
00874                                    if (Z_TYPE_P(data) == IS_STRING) {
00875                                           goto send_string;
00876                                    }
00877                                    /* data has alreade been converted to long */
00878                                    int4store(*p, Z_LVAL_P(data));
00879                                    (*p) += 4;
00880                                    break;
00881                             case MYSQL_TYPE_LONG_BLOB:
00882                                    if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
00883                                           stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
00884                                    } else {
00885                                           /* send_long_data() not called, send empty string */
00886                                           *p = php_mysqlnd_net_store_length(*p, 0);
00887                                    }
00888                                    break;
00889                             case MYSQL_TYPE_VAR_STRING:
00890 send_string:
00891                                    {
00892                                           unsigned int len = Z_STRLEN_P(data);
00893                                           /* to is after p. The latter hasn't been moved */
00894                                           *p = php_mysqlnd_net_store_length(*p, len);
00895                                           memcpy(*p, Z_STRVAL_P(data), len);
00896                                           (*p) += len;
00897                                    }
00898                                    break;
00899                             default:
00900                                    /* Won't happen, but set to NULL */
00901                                    (*buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
00902                                    break;
00903                      }
00904               }
00905        }
00906        ret = PASS;
00907 end:
00908        if (copies) {
00909               for (i = 0; i < stmt->param_count; i++) {
00910                      if (copies[i]) {
00911                             zval_ptr_dtor(&copies[i]);
00912                      }
00913               }
00914               mnd_efree(copies);
00915        }
00916 
00917        DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
00918        DBG_RETURN(ret);
00919 }
00920 /* }}} */
00921 
00922 
00923 /* {{{ mysqlnd_stmt_execute_generate_request */
00924 enum_func_status
00925 mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC)
00926 {
00927        MYSQLND_STMT_DATA * stmt = s->data;
00928        zend_uchar    *p = stmt->execute_cmd_buffer.buffer,
00929                             *cmd_buffer = stmt->execute_cmd_buffer.buffer;
00930        size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
00931        enum_func_status ret;
00932 
00933        DBG_ENTER("mysqlnd_stmt_execute_generate_request");
00934 
00935        int4store(p, stmt->stmt_id);
00936        p += 4;
00937 
00938        /* flags is 4 bytes, we store just 1 */
00939        int1store(p, (zend_uchar) stmt->flags);
00940        p++;
00941 
00942        /* Make it all zero */
00943        int4store(p, 0); 
00944 
00945        int1store(p, 1); /* and send 1 for iteration count */
00946        p+= 4;
00947 
00948        ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length TSRMLS_CC);
00949 
00950        *free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
00951        *request_len = (p - cmd_buffer);
00952        *request = cmd_buffer;
00953        DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
00954        DBG_RETURN(ret);
00955 }
00956 /* }}} */
00957 
00958 /*
00959  * Local variables:
00960  * tab-width: 4
00961  * c-basic-offset: 4
00962  * End:
00963  * vim600: noet sw=4 ts=4 fdm=marker
00964  * vim<600: noet sw=4 ts=4
00965  */