root/ext/mysqlnd/mysqlnd_ps_codec.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ps_fetch_from_1_to_8_bytes
  2. ps_fetch_null
  3. ps_fetch_int8
  4. ps_fetch_int16
  5. ps_fetch_int32
  6. ps_fetch_int64
  7. ps_fetch_float
  8. ps_fetch_double
  9. ps_fetch_time
  10. ps_fetch_date
  11. ps_fetch_datetime
  12. ps_fetch_string
  13. ps_fetch_bit
  14. _mysqlnd_init_ps_fetch_subsystem
  15. mysqlnd_stmt_copy_it
  16. mysqlnd_stmt_free_copies
  17. mysqlnd_stmt_execute_check_n_enlarge_buffer
  18. mysqlnd_stmt_execute_prepare_param_types
  19. mysqlnd_stmt_execute_store_types
  20. mysqlnd_stmt_execute_calculate_param_values_size
  21. mysqlnd_stmt_execute_store_param_values
  22. mysqlnd_stmt_execute_store_params
  23. mysqlnd_stmt_execute_generate_request

   1 /*
   2   +----------------------------------------------------------------------+
   3   | PHP Version 7                                                        |
   4   +----------------------------------------------------------------------+
   5   | Copyright (c) 2006-2016 The PHP Group                                |
   6   +----------------------------------------------------------------------+
   7   | This source file is subject to version 3.01 of the PHP license,      |
   8   | that is bundled with this package in the file LICENSE, and is        |
   9   | available through the world-wide-web at the following url:           |
  10   | http://www.php.net/license/3_01.txt                                  |
  11   | If you did not receive a copy of the PHP license and are unable to   |
  12   | obtain it through the world-wide-web, please send a note to          |
  13   | license@php.net so we can mail you a copy immediately.               |
  14   +----------------------------------------------------------------------+
  15   | Authors: Andrey Hristov <andrey@mysql.com>                           |
  16   |          Ulf Wendel <uwendel@mysql.com>                              |
  17   |          Georg Richter <georg@mysql.com>                             |
  18   +----------------------------------------------------------------------+
  19 */
  20 
  21 /* $Id$ */
  22 #include "php.h"
  23 #include "mysqlnd.h"
  24 #include "mysqlnd_wireprotocol.h"
  25 #include "mysqlnd_priv.h"
  26 #include "mysqlnd_debug.h"
  27 #include "ext/mysqlnd/mysql_float_to_double.h"
  28 
  29 #define MYSQLND_SILENT
  30 
  31 
  32 enum mysqlnd_timestamp_type
  33 {
  34   MYSQLND_TIMESTAMP_NONE= -2,
  35   MYSQLND_TIMESTAMP_ERROR= -1,
  36   MYSQLND_TIMESTAMP_DATE= 0,
  37   MYSQLND_TIMESTAMP_DATETIME= 1,
  38   MYSQLND_TIMESTAMP_TIME= 2
  39 };
  40 
  41 
  42 struct st_mysqlnd_time
  43 {
  44   unsigned int  year, month, day, hour, minute, second;
  45   zend_ulong second_part;
  46   zend_bool     neg;
  47   enum mysqlnd_timestamp_type time_type;
  48 };
  49 
  50 
  51 struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
  52 
  53 #define MYSQLND_PS_SKIP_RESULT_W_LEN    -1
  54 #define MYSQLND_PS_SKIP_RESULT_STR              -2
  55 
  56 /* {{{ ps_fetch_from_1_to_8_bytes */
  57 void
  58 ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len,
  59                                                    zend_uchar ** row, unsigned int byte_count)
  60 {
  61         char tmp[22];
  62         size_t tmp_len = 0;
  63         zend_bool is_bit = field->type == MYSQL_TYPE_BIT;
  64         DBG_ENTER("ps_fetch_from_1_to_8_bytes");
  65         DBG_INF_FMT("zv=%p byte_count=%u", zv, byte_count);
  66         if (field->flags & UNSIGNED_FLAG) {
  67                 uint64_t uval = 0;
  68 
  69                 switch (byte_count) {
  70                         case 8:uval = is_bit? (uint64_t) bit_uint8korr(*row):(uint64_t) uint8korr(*row);break;
  71                         case 7:uval = bit_uint7korr(*row);break;
  72                         case 6:uval = bit_uint6korr(*row);break;
  73                         case 5:uval = bit_uint5korr(*row);break;
  74                         case 4:uval = is_bit? (uint64_t) bit_uint4korr(*row):(uint64_t) uint4korr(*row);break;
  75                         case 3:uval = is_bit? (uint64_t) bit_uint3korr(*row):(uint64_t) uint3korr(*row);break;
  76                         case 2:uval = is_bit? (uint64_t) bit_uint2korr(*row):(uint64_t) uint2korr(*row);break;
  77                         case 1:uval = (uint64_t) uint1korr(*row);break;
  78                 }
  79 
  80 #if SIZEOF_ZEND_LONG==4
  81                 if (uval > INT_MAX) {
  82                         DBG_INF("stringify");
  83                         tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
  84                 } else
  85 #endif /* #if SIZEOF_LONG==4 */
  86                 {
  87                         if (byte_count < 8 || uval <= L64(9223372036854775807)) {
  88                                 ZVAL_LONG(zv, (zend_long) uval); /* the cast is safe, we are in the range */
  89                         } else {
  90                                 DBG_INF("stringify");
  91                                 tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
  92                         }
  93                 }
  94         } else {
  95                 /* SIGNED */
  96                 int64_t lval = 0;
  97                 switch (byte_count) {
  98                         case 8:lval = (int64_t) sint8korr(*row);break;
  99                         /*
 100                           7, 6 and 5 are not possible.
 101                           BIT is only unsigned, thus only uint5|6|7 macroses exist
 102                         */
 103                         case 4:lval = (int64_t) sint4korr(*row);break;
 104                         case 3:lval = (int64_t) sint3korr(*row);break;
 105                         case 2:lval = (int64_t) sint2korr(*row);break;
 106                         case 1:lval = (int64_t) *(int8_t*)*row;break;
 107                 }
 108 
 109 #if SIZEOF_ZEND_LONG==4
 110                 if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) {
 111                         DBG_INF("stringify");
 112                         tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
 113                 } else
 114 #endif /* SIZEOF */
 115                 {
 116                         ZVAL_LONG(zv, (zend_long) lval); /* the cast is safe, we are in the range */
 117                 }
 118         }
 119 
 120         if (tmp_len) {
 121                 ZVAL_STRINGL(zv, tmp, tmp_len);
 122         }
 123         (*row)+= byte_count;
 124         DBG_VOID_RETURN;
 125 }
 126 /* }}} */
 127 
 128 
 129 /* {{{ ps_fetch_null */
 130 static void
 131 ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 132 {
 133         ZVAL_NULL(zv);
 134 }
 135 /* }}} */
 136 
 137 
 138 /* {{{ ps_fetch_int8 */
 139 static void
 140 ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 141 {
 142         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1);
 143 }
 144 /* }}} */
 145 
 146 
 147 /* {{{ ps_fetch_int16 */
 148 static void
 149 ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 150 {
 151         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2);
 152 }
 153 /* }}} */
 154 
 155 
 156 /* {{{ ps_fetch_int32 */
 157 static void
 158 ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 159 {
 160         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4);
 161 }
 162 /* }}} */
 163 
 164 
 165 /* {{{ ps_fetch_int64 */
 166 static void
 167 ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 168 {
 169         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8);
 170 }
 171 /* }}} */
 172 
 173 
 174 /* {{{ ps_fetch_float */
 175 static void
 176 ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 177 {
 178         float fval;
 179         double dval;
 180         DBG_ENTER("ps_fetch_float");
 181         float4get(fval, *row);
 182         (*row)+= 4;
 183         DBG_INF_FMT("value=%f", fval);
 184 
 185 #ifndef NOT_FIXED_DEC
 186 # define NOT_FIXED_DEC 31
 187 #endif
 188 
 189         dval = mysql_float_to_double(fval, (field->decimals >= NOT_FIXED_DEC) ? -1 : field->decimals);
 190 
 191         ZVAL_DOUBLE(zv, dval);
 192         DBG_VOID_RETURN;
 193 }
 194 /* }}} */
 195 
 196 
 197 /* {{{ ps_fetch_double */
 198 static void
 199 ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 200 {
 201         double value;
 202         DBG_ENTER("ps_fetch_double");
 203         float8get(value, *row);
 204         ZVAL_DOUBLE(zv, value);
 205         (*row)+= 8;
 206         DBG_INF_FMT("value=%f", value);
 207         DBG_VOID_RETURN;
 208 }
 209 /* }}} */
 210 
 211 
 212 /* {{{ ps_fetch_time */
 213 static void
 214 ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 215 {
 216         struct st_mysqlnd_time t;
 217         zend_ulong length; /* First byte encodes the length*/
 218         char * value;
 219         DBG_ENTER("ps_fetch_time");
 220 
 221         if ((length = php_mysqlnd_net_field_length(row))) {
 222                 zend_uchar * to= *row;
 223 
 224                 t.time_type = MYSQLND_TIMESTAMP_TIME;
 225                 t.neg                   = (zend_bool) to[0];
 226 
 227                 t.day                   = (zend_ulong) sint4korr(to+1);
 228                 t.hour                  = (unsigned int) to[5];
 229                 t.minute                = (unsigned int) to[6];
 230                 t.second                = (unsigned int) to[7];
 231                 t.second_part   = (length > 8) ? (zend_ulong) sint4korr(to+8) : 0;
 232                 t.year                  = t.month= 0;
 233                 if (t.day) {
 234                         /* Convert days to hours at once */
 235                         t.hour += t.day*24;
 236                         t.day   = 0;
 237                 }
 238 
 239                 (*row) += length;
 240         } else {
 241                 memset(&t, 0, sizeof(t));
 242                 t.time_type = MYSQLND_TIMESTAMP_TIME;
 243         }
 244 
 245         length = mnd_sprintf(&value, 0, "%s%02u:%02u:%02u", (t.neg ? "-" : ""), t.hour, t.minute, t.second);
 246 
 247         DBG_INF_FMT("%s", value);
 248         ZVAL_STRINGL(zv, value, length);
 249         mnd_sprintf_free(value);
 250         DBG_VOID_RETURN;
 251 }
 252 /* }}} */
 253 
 254 
 255 /* {{{ ps_fetch_date */
 256 static void
 257 ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 258 {
 259         struct st_mysqlnd_time t = {0};
 260         zend_ulong length; /* First byte encodes the length*/
 261         char * value;
 262         DBG_ENTER("ps_fetch_date");
 263 
 264         if ((length = php_mysqlnd_net_field_length(row))) {
 265                 zend_uchar *to= *row;
 266 
 267                 t.time_type= MYSQLND_TIMESTAMP_DATE;
 268                 t.neg= 0;
 269 
 270                 t.second_part = t.hour = t.minute = t.second = 0;
 271 
 272                 t.year  = (unsigned int) sint2korr(to);
 273                 t.month = (unsigned int) to[2];
 274                 t.day   = (unsigned int) to[3];
 275 
 276                 (*row)+= length;
 277         } else {
 278                 memset(&t, 0, sizeof(t));
 279                 t.time_type = MYSQLND_TIMESTAMP_DATE;
 280         }
 281 
 282         length = mnd_sprintf(&value, 0, "%04u-%02u-%02u", t.year, t.month, t.day);
 283 
 284         DBG_INF_FMT("%s", value);
 285         ZVAL_STRINGL(zv, value, length);
 286         mnd_sprintf_free(value);
 287         DBG_VOID_RETURN;
 288 }
 289 /* }}} */
 290 
 291 
 292 /* {{{ ps_fetch_datetime */
 293 static void
 294 ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 295 {
 296         struct st_mysqlnd_time t;
 297         zend_ulong length; /* First byte encodes the length*/
 298         char * value;
 299         DBG_ENTER("ps_fetch_datetime");
 300 
 301         if ((length = php_mysqlnd_net_field_length(row))) {
 302                 zend_uchar * to = *row;
 303 
 304                 t.time_type = MYSQLND_TIMESTAMP_DATETIME;
 305                 t.neg    = 0;
 306 
 307                 t.year   = (unsigned int) sint2korr(to);
 308                 t.month = (unsigned int) to[2];
 309                 t.day    = (unsigned int) to[3];
 310 
 311                 if (length > 4) {
 312                         t.hour   = (unsigned int) to[4];
 313                         t.minute = (unsigned int) to[5];
 314                         t.second = (unsigned int) to[6];
 315                 } else {
 316                         t.hour = t.minute = t.second= 0;
 317                 }
 318                 t.second_part = (length > 7) ? (zend_ulong) sint4korr(to+7) : 0;
 319 
 320                 (*row)+= length;
 321         } else {
 322                 memset(&t, 0, sizeof(t));
 323                 t.time_type = MYSQLND_TIMESTAMP_DATETIME;
 324         }
 325 
 326         length = mnd_sprintf(&value, 0, "%04u-%02u-%02u %02u:%02u:%02u", t.year, t.month, t.day, t.hour, t.minute, t.second);
 327 
 328         DBG_INF_FMT("%s", value);
 329         ZVAL_STRINGL(zv, value, length);
 330         mnd_sprintf_free(value);
 331         DBG_VOID_RETURN;
 332 }
 333 /* }}} */
 334 
 335 
 336 /* {{{ ps_fetch_string */
 337 static void
 338 ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 339 {
 340         /*
 341           For now just copy, before we make it possible
 342           to write \0 to the row buffer
 343         */
 344         const zend_ulong length = php_mysqlnd_net_field_length(row);
 345         DBG_ENTER("ps_fetch_string");
 346         DBG_INF_FMT("len = %lu", length);
 347         DBG_INF("copying from the row buffer");
 348         ZVAL_STRINGL(zv, (char *)*row, length);
 349 
 350         (*row) += length;
 351         DBG_VOID_RETURN;
 352 }
 353 /* }}} */
 354 
 355 
 356 /* {{{ ps_fetch_bit */
 357 static void
 358 ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
 359 {
 360         zend_ulong length = php_mysqlnd_net_field_length(row);
 361         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length);
 362 }
 363 /* }}} */
 364 
 365 
 366 /* {{{ _mysqlnd_init_ps_fetch_subsystem */
 367 void _mysqlnd_init_ps_fetch_subsystem()
 368 {
 369         memset(mysqlnd_ps_fetch_functions, 0, sizeof(mysqlnd_ps_fetch_functions));
 370         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].func                = ps_fetch_null;
 371         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].pack_len    = 0;
 372         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].php_type    = IS_NULL;
 373         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NULL].can_ret_as_str_in_uni       = TRUE;
 374 
 375         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].func                = ps_fetch_int8;
 376         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].pack_len    = 1;
 377         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].php_type    = IS_LONG;
 378         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY].can_ret_as_str_in_uni       = TRUE;
 379 
 380         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].func               = ps_fetch_int16;
 381         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].pack_len   = 2;
 382         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].php_type   = IS_LONG;
 383         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SHORT].can_ret_as_str_in_uni      = TRUE;
 384 
 385         mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].func                = ps_fetch_int16;
 386         mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].pack_len    = 2;
 387         mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].php_type    = IS_LONG;
 388         mysqlnd_ps_fetch_functions[MYSQL_TYPE_YEAR].can_ret_as_str_in_uni       = TRUE;
 389 
 390         mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].func               = ps_fetch_int32;
 391         mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].pack_len   = 4;
 392         mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].php_type   = IS_LONG;
 393         mysqlnd_ps_fetch_functions[MYSQL_TYPE_INT24].can_ret_as_str_in_uni      = TRUE;
 394 
 395         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].func                = ps_fetch_int32;
 396         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].pack_len    = 4;
 397         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].php_type    = IS_LONG;
 398         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG].can_ret_as_str_in_uni       = TRUE;
 399 
 400         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].func    = ps_fetch_int64;
 401         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].pack_len= 8;
 402         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].php_type= IS_LONG;
 403         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONGLONG].can_ret_as_str_in_uni   = TRUE;
 404 
 405         mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].func               = ps_fetch_float;
 406         mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].pack_len   = 4;
 407         mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].php_type   = IS_DOUBLE;
 408         mysqlnd_ps_fetch_functions[MYSQL_TYPE_FLOAT].can_ret_as_str_in_uni      = TRUE;
 409 
 410         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].func              = ps_fetch_double;
 411         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].pack_len  = 8;
 412         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].php_type  = IS_DOUBLE;
 413         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DOUBLE].can_ret_as_str_in_uni     = TRUE;
 414 
 415         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].func                = ps_fetch_time;
 416         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].pack_len    = MYSQLND_PS_SKIP_RESULT_W_LEN;
 417         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].php_type    = IS_STRING;
 418         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIME].can_ret_as_str_in_uni       = TRUE;
 419 
 420         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].func                = ps_fetch_date;
 421         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].pack_len    = MYSQLND_PS_SKIP_RESULT_W_LEN;
 422         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].php_type    = IS_STRING;
 423         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATE].can_ret_as_str_in_uni       = TRUE;
 424 
 425         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].func             = ps_fetch_string;
 426         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].pack_len = MYSQLND_PS_SKIP_RESULT_W_LEN;
 427         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].php_type = IS_STRING;
 428         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDATE].can_ret_as_str_in_uni    = TRUE;
 429 
 430         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].func    = ps_fetch_datetime;
 431         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
 432         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].php_type= IS_STRING;
 433         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DATETIME].can_ret_as_str_in_uni   = TRUE;
 434 
 435         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].func   = ps_fetch_datetime;
 436         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].pack_len= MYSQLND_PS_SKIP_RESULT_W_LEN;
 437         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].php_type= IS_STRING;
 438         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TIMESTAMP].can_ret_as_str_in_uni  = TRUE;
 439 
 440         mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].func        = ps_fetch_string;
 441         mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
 442         mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].php_type = IS_STRING;
 443         mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].is_possibly_blob = TRUE;
 444         mysqlnd_ps_fetch_functions[MYSQL_TYPE_JSON].can_ret_as_str_in_uni       = TRUE;
 445 
 446         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].func   = ps_fetch_string;
 447         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
 448         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].php_type = IS_STRING;
 449         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].is_possibly_blob = TRUE;
 450         mysqlnd_ps_fetch_functions[MYSQL_TYPE_TINY_BLOB].can_ret_as_str_in_uni  = TRUE;
 451 
 452         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].func                = ps_fetch_string;
 453         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].pack_len    = MYSQLND_PS_SKIP_RESULT_STR;
 454         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].php_type    = IS_STRING;
 455         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].is_possibly_blob = TRUE;
 456         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BLOB].can_ret_as_str_in_uni       = TRUE;
 457 
 458         mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].func         = ps_fetch_string;
 459         mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].pack_len     = MYSQLND_PS_SKIP_RESULT_STR;
 460         mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].php_type     = IS_STRING;
 461         mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].is_possibly_blob = TRUE;
 462         mysqlnd_ps_fetch_functions[MYSQL_TYPE_MEDIUM_BLOB].can_ret_as_str_in_uni        = TRUE;
 463 
 464         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].func           = ps_fetch_string;
 465         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].pack_len       = MYSQLND_PS_SKIP_RESULT_STR;
 466         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].php_type       = IS_STRING;
 467         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].is_possibly_blob = TRUE;
 468         mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].can_ret_as_str_in_uni  = TRUE;
 469 
 470         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func         = ps_fetch_bit;
 471         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len     = 8;
 472         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type     = IS_LONG;
 473         mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE;
 474 
 475         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func          = ps_fetch_string;
 476         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len      = MYSQLND_PS_SKIP_RESULT_STR;
 477         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].php_type = IS_STRING;
 478         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].is_possibly_blob = TRUE;
 479 
 480         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].func             = ps_fetch_string;
 481         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
 482         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].php_type = IS_STRING;
 483         mysqlnd_ps_fetch_functions[MYSQL_TYPE_VARCHAR].is_possibly_blob = TRUE;
 484 
 485         mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].func                      = ps_fetch_string;
 486         mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].pack_len          = MYSQLND_PS_SKIP_RESULT_STR;
 487         mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].php_type  = IS_STRING;
 488         mysqlnd_ps_fetch_functions[MYSQL_TYPE_STRING].is_possibly_blob = TRUE;
 489 
 490         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].func             = ps_fetch_string;
 491         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].pack_len = MYSQLND_PS_SKIP_RESULT_STR;
 492         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].php_type = IS_STRING;
 493         mysqlnd_ps_fetch_functions[MYSQL_TYPE_DECIMAL].can_ret_as_str_in_uni    = TRUE;
 494 
 495         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].func          = ps_fetch_string;
 496         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].pack_len      = MYSQLND_PS_SKIP_RESULT_STR;
 497         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].php_type      = IS_STRING;
 498         mysqlnd_ps_fetch_functions[MYSQL_TYPE_NEWDECIMAL].can_ret_as_str_in_uni = TRUE;
 499 
 500         mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].func                = ps_fetch_string;
 501         mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].pack_len    = MYSQLND_PS_SKIP_RESULT_STR;
 502         mysqlnd_ps_fetch_functions[MYSQL_TYPE_ENUM].php_type    = IS_STRING;
 503 
 504         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].func                 = ps_fetch_string;
 505         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].pack_len             = MYSQLND_PS_SKIP_RESULT_STR;
 506         mysqlnd_ps_fetch_functions[MYSQL_TYPE_SET].php_type             = IS_STRING;
 507 
 508         mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].func    = ps_fetch_string;
 509         mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].pack_len= MYSQLND_PS_SKIP_RESULT_STR;
 510         mysqlnd_ps_fetch_functions[MYSQL_TYPE_GEOMETRY].php_type= IS_STRING;
 511 }
 512 /* }}} */
 513 
 514 
 515 /* {{{ mysqlnd_stmt_copy_it */
 516 static enum_func_status
 517 mysqlnd_stmt_copy_it(zval ** copies, zval * original, unsigned int param_count, unsigned int current)
 518 {
 519         if (!*copies) {
 520                 *copies = mnd_ecalloc(param_count, sizeof(zval));
 521         }
 522         if (*copies) {
 523                 ZVAL_COPY(&(*copies)[current], original);
 524                 return PASS;
 525         }
 526         return FAIL;
 527 }
 528 /* }}} */
 529 
 530 
 531 /* {{{ mysqlnd_stmt_free_copies */
 532 static void
 533 mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval *copies)
 534 {
 535         if (copies) {
 536                 unsigned int i;
 537                 for (i = 0; i < stmt->param_count; i++) {
 538                         zval_ptr_dtor(&copies[i]);
 539                 }
 540                 mnd_efree(copies);
 541         }
 542 }
 543 /* }}} */
 544 
 545 
 546 /* {{{ mysqlnd_stmt_execute_check_n_enlarge_buffer */
 547 static enum_func_status
 548 mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, size_t * buf_len, zend_uchar * const provided_buffer, size_t needed_bytes)
 549 {
 550         const size_t overalloc = 5;
 551         size_t left = (*buf_len - (*p - *buf));
 552 
 553         if (left < (needed_bytes + overalloc)) {
 554                 size_t offset = *p - *buf;
 555                 zend_uchar *tmp_buf;
 556                 *buf_len = offset + needed_bytes + overalloc;
 557                 tmp_buf = mnd_emalloc(*buf_len);
 558                 if (!tmp_buf) {
 559                         return FAIL;
 560                 }
 561                 memcpy(tmp_buf, *buf, offset);
 562                 if (*buf != provided_buffer) {
 563                         mnd_efree(*buf);
 564                 }
 565                 *buf = tmp_buf;
 566                 /* Update our pos pointer */
 567                 *p = *buf + offset;
 568         }
 569         return PASS;
 570 }
 571 /* }}} */
 572 
 573 
 574 /* {{{ mysqlnd_stmt_execute_prepare_param_types */
 575 static enum_func_status
 576 mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copies_param, int * resend_types_next_time)
 577 {
 578         unsigned int i;
 579         DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
 580         for (i = 0; i < stmt->param_count; i++) {
 581                 short current_type = stmt->param_bind[i].type;
 582                 zval *parameter = &stmt->param_bind[i].zv;
 583 
 584                 ZVAL_DEREF(parameter);
 585                 if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
 586                         /* always copy the var, because we do many conversions */
 587                         if (Z_TYPE_P(parameter) != IS_LONG &&
 588                                 PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i))
 589                         {
 590                                 SET_OOM_ERROR(*stmt->error_info);
 591                                 goto end;
 592                         }
 593                         /*
 594                           if it doesn't fit in a long send it as a string.
 595                           Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 596                         */
 597                         if (Z_TYPE_P(parameter) != IS_LONG) {
 598                                 zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: parameter;
 599                                 /*
 600                                   Because converting to double and back to long can lead
 601                                   to losing precision we need second variable. Conversion to double is to see if
 602                                   value is too big for a long. As said, precision could be lost.
 603                                 */
 604                                 zval tmp_data_copy;
 605                                 ZVAL_COPY(&tmp_data_copy, tmp_data);
 606                                 convert_to_double_ex(&tmp_data_copy);
 607 
 608                                 /*
 609                                   if it doesn't fit in a long send it as a string.
 610                                   Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 611                                   We do transformation here, which will be used later when sending types. The code later relies on this.
 612                                 */
 613                                 if (Z_DVAL(tmp_data_copy) > ZEND_LONG_MAX || Z_DVAL(tmp_data_copy) < ZEND_LONG_MIN) {
 614                                         stmt->send_types_to_server = *resend_types_next_time = 1;
 615                                         convert_to_string_ex(tmp_data);
 616                                 } else {
 617                                         convert_to_long_ex(tmp_data);
 618                                 }
 619 
 620                                 zval_ptr_dtor(&tmp_data_copy);
 621                         }
 622                 }
 623         }
 624         DBG_RETURN(PASS);
 625 end:
 626         DBG_RETURN(FAIL);
 627 }
 628 /* }}} */
 629 
 630 
 631 /* {{{ mysqlnd_stmt_execute_store_types */
 632 static void
 633 mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar ** p)
 634 {
 635         unsigned int i;
 636         for (i = 0; i < stmt->param_count; i++) {
 637                 short current_type = stmt->param_bind[i].type;
 638                 zval *parameter = &stmt->param_bind[i].zv;
 639                 /* our types are not unsigned */
 640 #if SIZEOF_ZEND_LONG==8
 641                 if (current_type == MYSQL_TYPE_LONG) {
 642                         current_type = MYSQL_TYPE_LONGLONG;
 643                 }
 644 #endif
 645                 ZVAL_DEREF(parameter);
 646                 if (!Z_ISNULL_P(parameter) && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
 647                         /*
 648                           if it doesn't fit in a long send it as a string.
 649                           Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 650                         */
 651                         if (Z_TYPE_P(parameter) != IS_LONG) {
 652                                 const zval *tmp_data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i] : parameter;
 653                                 /*
 654                                   In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type.
 655                                   The actual transformation has been performed several dozens line above.
 656                                 */
 657                                 if (Z_TYPE_P(tmp_data) == IS_STRING) {
 658                                         current_type = MYSQL_TYPE_VAR_STRING;
 659                                         /*
 660                                           don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING
 661                                           we force convert_to_long_ex in all cases, thus the type will be right in the next switch.
 662                                           if the type is however not long, then we will do a goto in the next switch.
 663                                           We want to preserve the original bind type given by the user. Thus, we do these hacks.
 664                                         */
 665                                 }
 666                         }
 667                 }
 668                 int2store(*p, current_type);
 669                 *p+= 2;
 670         }
 671 }
 672 /* }}} */
 673 
 674 
 675 /* {{{ mysqlnd_stmt_execute_calculate_param_values_size */
 676 static enum_func_status
 677 mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval ** copies_param, size_t * data_size)
 678 {
 679         unsigned int i;
 680         DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size");
 681         for (i = 0; i < stmt->param_count; i++) {
 682                 unsigned short is_longlong = 0;
 683                 unsigned int j;
 684                 zval *bind_var, *the_var = &stmt->param_bind[i].zv;
 685 
 686                 bind_var = the_var;
 687                 ZVAL_DEREF(the_var);
 688                 if ((stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
 689                         continue;
 690                 }
 691 
 692                 if (Z_ISREF_P(bind_var)) {
 693                         for (j = i + 1; j < stmt->param_count; j++) {
 694                                 if (Z_ISREF(stmt->param_bind[j].zv) && Z_REFVAL(stmt->param_bind[j].zv) == the_var) {
 695                                         /* Double binding of the same zval, make a copy */
 696                                         if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
 697                                                 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
 698                                                         SET_OOM_ERROR(*stmt->error_info);
 699                                                         goto end;
 700                                                 }
 701                                         }
 702                                         break;
 703                                 }
 704                         }
 705                 }
 706 
 707                 switch (stmt->param_bind[i].type) {
 708                         case MYSQL_TYPE_DOUBLE:
 709                                 *data_size += 8;
 710                                 if (Z_TYPE_P(the_var) != IS_DOUBLE) {
 711                                         if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
 712                                                 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
 713                                                         SET_OOM_ERROR(*stmt->error_info);
 714                                                         goto end;
 715                                                 }
 716                                         }
 717                                 }
 718                                 break;
 719                         case MYSQL_TYPE_LONGLONG:
 720                                 is_longlong = 4;
 721                                 /* fall-through */
 722                         case MYSQL_TYPE_LONG:
 723                                 {
 724                                         zval *tmp_data = (*copies_param && !Z_ISUNDEF((*copies_param)[i]))? &(*copies_param)[i]: the_var;
 725                                         if (Z_TYPE_P(tmp_data) == IS_STRING) {
 726                                                 goto use_string;
 727                                         }
 728                                         convert_to_long_ex(tmp_data);
 729                                 }
 730                                 *data_size += 4 + is_longlong;
 731                                 break;
 732                         case MYSQL_TYPE_LONG_BLOB:
 733                                 if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
 734                                         /*
 735                                           User hasn't sent anything, we will send empty string.
 736                                           Empty string has length of 0, encoded in 1 byte. No real
 737                                           data will follows after it.
 738                                         */
 739                                         (*data_size)++;
 740                                 }
 741                                 break;
 742                         case MYSQL_TYPE_VAR_STRING:
 743 use_string:
 744                                 *data_size += 8; /* max 8 bytes for size */
 745                                 if (Z_TYPE_P(the_var) != IS_STRING) {
 746                                         if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
 747                                                 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
 748                                                         SET_OOM_ERROR(*stmt->error_info);
 749                                                         goto end;
 750                                                 }
 751                                         }
 752                                         the_var = &((*copies_param)[i]);
 753                                 }
 754                                 convert_to_string_ex(the_var);
 755                                 *data_size += Z_STRLEN_P(the_var);
 756                                 break;
 757                 }
 758         }
 759         DBG_RETURN(PASS);
 760 end:
 761         DBG_RETURN(FAIL);
 762 }
 763 /* }}} */
 764 
 765 
 766 /* {{{ mysqlnd_stmt_execute_store_param_values */
 767 static void
 768 mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
 769 {
 770         unsigned int i;
 771         for (i = 0; i < stmt->param_count; i++) {
 772                 zval *data, *parameter = &stmt->param_bind[i].zv;
 773 
 774                 ZVAL_DEREF(parameter);
 775                 data = (copies && !Z_ISUNDEF(copies[i]))? &copies[i]: parameter;
 776                 /* Handle long data */
 777                 if (!Z_ISUNDEF_P(parameter) && Z_TYPE_P(data) == IS_NULL) {
 778                         (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
 779                 } else {
 780                         switch (stmt->param_bind[i].type) {
 781                                 case MYSQL_TYPE_DOUBLE:
 782                                         convert_to_double_ex(data);
 783                                         float8store(*p, Z_DVAL_P(data));
 784                                         (*p) += 8;
 785                                         break;
 786                                 case MYSQL_TYPE_LONGLONG:
 787                                         if (Z_TYPE_P(data) == IS_STRING) {
 788                                                 goto send_string;
 789                                         }
 790                                         /* data has alreade been converted to long */
 791                                         int8store(*p, Z_LVAL_P(data));
 792                                         (*p) += 8;
 793                                         break;
 794                                 case MYSQL_TYPE_LONG:
 795                                         if (Z_TYPE_P(data) == IS_STRING) {
 796                                                 goto send_string;
 797                                         }
 798                                         /* data has alreade been converted to long */
 799                                         int4store(*p, Z_LVAL_P(data));
 800                                         (*p) += 4;
 801                                         break;
 802                                 case MYSQL_TYPE_LONG_BLOB:
 803                                         if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
 804                                                 stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
 805                                         } else {
 806                                                 /* send_long_data() not called, send empty string */
 807                                                 *p = php_mysqlnd_net_store_length(*p, 0);
 808                                         }
 809                                         break;
 810                                 case MYSQL_TYPE_VAR_STRING:
 811 send_string:
 812                                         {
 813                                                 size_t len = Z_STRLEN_P(data);
 814                                                 /* to is after p. The latter hasn't been moved */
 815                                                 *p = php_mysqlnd_net_store_length(*p, len);
 816                                                 memcpy(*p, Z_STRVAL_P(data), len);
 817                                                 (*p) += len;
 818                                         }
 819                                         break;
 820                                 default:
 821                                         /* Won't happen, but set to NULL */
 822                                         (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
 823                                         break;
 824                         }
 825                 }
 826         }
 827 }
 828 /* }}} */
 829 
 830 
 831 /* {{{ mysqlnd_stmt_execute_store_params */
 832 static enum_func_status
 833 mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len )
 834 {
 835         MYSQLND_STMT_DATA * stmt = s->data;
 836         zend_uchar * provided_buffer = *buf;
 837         size_t data_size = 0;
 838         zval *copies = NULL;/* if there are different types */
 839         enum_func_status ret = FAIL;
 840         int resend_types_next_time = 0;
 841         size_t null_byte_offset;
 842 
 843         DBG_ENTER("mysqlnd_stmt_execute_store_params");
 844 
 845         {
 846                 unsigned int null_count = (stmt->param_count + 7) / 8;
 847                 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count)) {
 848                         SET_OOM_ERROR(*stmt->error_info);
 849                         goto end;
 850                 }
 851                 /* put `null` bytes */
 852                 null_byte_offset = *p - *buf;
 853                 memset(*p, 0, null_count);
 854                 *p += null_count;
 855         }
 856 
 857 /* 1. Store type information */
 858         /*
 859           check if need to send the types even if stmt->send_types_to_server is 0. This is because
 860           if we send "i" (42) then the type will be int and the server will expect int. However, if next
 861           time we try to send > LONG_MAX, the conversion to string will send a string and the server
 862           won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values
 863           occur, and force resend for the next execution.
 864         */
 865         if (FAIL == mysqlnd_stmt_execute_prepare_param_types(stmt, &copies, &resend_types_next_time)) {
 866                 goto end;
 867         }
 868 
 869         int1store(*p, stmt->send_types_to_server);
 870         (*p)++;
 871 
 872         if (stmt->send_types_to_server) {
 873                 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2)) {
 874                         SET_OOM_ERROR(*stmt->error_info);
 875                         goto end;
 876                 }
 877                 mysqlnd_stmt_execute_store_types(stmt, copies, p);
 878         }
 879 
 880         stmt->send_types_to_server = resend_types_next_time;
 881 
 882 /* 2. Store data */
 883         /* 2.1 Calculate how much space we need */
 884         if (FAIL == mysqlnd_stmt_execute_calculate_param_values_size(stmt, &copies, &data_size)) {
 885                 goto end;
 886         }
 887 
 888         /* 2.2 Enlarge the buffer, if needed */
 889         if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size)) {
 890                 SET_OOM_ERROR(*stmt->error_info);
 891                 goto end;
 892         }
 893 
 894         /* 2.3 Store the actual data */
 895         mysqlnd_stmt_execute_store_param_values(stmt, copies, *buf, p, null_byte_offset);
 896 
 897         ret = PASS;
 898 end:
 899         mysqlnd_stmt_free_copies(stmt, copies);
 900 
 901         DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
 902         DBG_RETURN(ret);
 903 }
 904 /* }}} */
 905 
 906 
 907 /* {{{ mysqlnd_stmt_execute_generate_request */
 908 enum_func_status
 909 mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer)
 910 {
 911         MYSQLND_STMT_DATA * stmt = s->data;
 912         zend_uchar      *p = stmt->execute_cmd_buffer.buffer,
 913                                 *cmd_buffer = stmt->execute_cmd_buffer.buffer;
 914         size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
 915         enum_func_status ret;
 916 
 917         DBG_ENTER("mysqlnd_stmt_execute_generate_request");
 918 
 919         int4store(p, stmt->stmt_id);
 920         p += 4;
 921 
 922         /* flags is 4 bytes, we store just 1 */
 923         int1store(p, (zend_uchar) stmt->flags);
 924         p++;
 925 
 926         /* Make it all zero */
 927         int4store(p, 0);
 928 
 929         int1store(p, 1); /* and send 1 for iteration count */
 930         p+= 4;
 931 
 932         ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length);
 933 
 934         *free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
 935         *request_len = (p - cmd_buffer);
 936         *request = cmd_buffer;
 937         DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
 938         DBG_RETURN(ret);
 939 }
 940 /* }}} */
 941 
 942 /*
 943  * Local variables:
 944  * tab-width: 4
 945  * c-basic-offset: 4
 946  * End:
 947  * vim600: noet sw=4 ts=4 fdm=marker
 948  * vim<600: noet sw=4 ts=4
 949  */

/* [<][>][^][v][top][bottom][index][help] */