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 5                                                        |
   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   unsigned long 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 TSRMLS_DC)
  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_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, (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_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, (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, 1);
 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 TSRMLS_DC)
 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 TSRMLS_DC)
 141 {
 142         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1 TSRMLS_CC);
 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 TSRMLS_DC)
 150 {
 151         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2 TSRMLS_CC);
 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 TSRMLS_DC)
 159 {
 160         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4 TSRMLS_CC);
 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 TSRMLS_DC)
 168 {
 169         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8 TSRMLS_CC);
 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 TSRMLS_DC)
 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 TSRMLS_DC)
 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 TSRMLS_DC)
 215 {
 216         struct st_mysqlnd_time t;
 217         unsigned long 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                   = (unsigned long) 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) ? (unsigned long) 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, 1);
 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 TSRMLS_DC)
 258 {
 259         struct st_mysqlnd_time t = {0};
 260         unsigned long 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, 1);
 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 TSRMLS_DC)
 295 {
 296         struct st_mysqlnd_time t;
 297         unsigned long 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) ? (unsigned long) 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, 1);
 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 TSRMLS_DC)
 339 {
 340         /*
 341           For now just copy, before we make it possible
 342           to write \0 to the row buffer
 343         */
 344         const unsigned long 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, 1);
 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 TSRMLS_DC)
 359 {
 360         unsigned long length = php_mysqlnd_net_field_length(row);
 361         ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length TSRMLS_CC);
 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 TSRMLS_DC)
 518 {
 519         if (!*copies) {
 520                 *copies = mnd_ecalloc(param_count, sizeof(zval *));
 521         }
 522         if (*copies) {
 523                 MAKE_STD_ZVAL((*copies)[current]);
 524                 *(*copies)[current] = *original;
 525                 Z_SET_REFCOUNT_P((*copies)[current], 1);
 526                 zval_copy_ctor((*copies)[current]);
 527                 return PASS;
 528         }
 529         return FAIL;
 530 }
 531 /* }}} */
 532 
 533 
 534 /* {{{ mysqlnd_stmt_free_copies */
 535 static void
 536 mysqlnd_stmt_free_copies(MYSQLND_STMT_DATA * stmt, zval ** copies TSRMLS_DC)
 537 {
 538         if (copies) {
 539                 unsigned int i;
 540                 for (i = 0; i < stmt->param_count; i++) {
 541                         if (copies[i]) {
 542                                 zval_ptr_dtor(&copies[i]);
 543                         }
 544                 }
 545                 mnd_efree(copies);
 546         }
 547 }
 548 /* }}} */
 549 
 550 
 551 /* {{{ mysqlnd_stmt_execute_check_n_enlarge_buffer */
 552 static enum_func_status
 553 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 TSRMLS_DC)
 554 {
 555         const size_t overalloc = 5;
 556         size_t left = (*buf_len - (*p - *buf));
 557 
 558         if (left < (needed_bytes + overalloc)) {
 559                 size_t offset = *p - *buf;
 560                 zend_uchar *tmp_buf;
 561                 *buf_len = offset + needed_bytes + overalloc;
 562                 tmp_buf = mnd_emalloc(*buf_len);
 563                 if (!tmp_buf) {
 564                         return FAIL;
 565                 }
 566                 memcpy(tmp_buf, *buf, offset);
 567                 if (*buf != provided_buffer) {
 568                         mnd_efree(*buf);
 569                 }
 570                 *buf = tmp_buf;
 571                 /* Update our pos pointer */
 572                 *p = *buf + offset;
 573         }
 574         return PASS;
 575 }
 576 /* }}} */
 577 
 578 
 579 /* {{{ mysqlnd_stmt_execute_prepare_param_types */
 580 static enum_func_status
 581 mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval *** copies_param, int * resend_types_next_time TSRMLS_DC)
 582 {
 583         unsigned int i;
 584         DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
 585         for (i = 0; i < stmt->param_count; i++) {
 586                 short current_type = stmt->param_bind[i].type;
 587 
 588                 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
 589                         zval ** copies;
 590                         /* always copy the var, because we do many conversions */
 591                         if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG &&
 592                                 PASS != mysqlnd_stmt_copy_it(copies_param, stmt->param_bind[i].zv, stmt->param_count, i TSRMLS_CC))
 593                         {
 594                                 SET_OOM_ERROR(*stmt->error_info);
 595                                 goto end;
 596                         }
 597                         copies = *copies_param;
 598                         /*
 599                           if it doesn't fit in a long send it as a string.
 600                           Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 601                         */
 602                         if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
 603                                 zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
 604                                 /*
 605                                   Because converting to double and back to long can lead
 606                                   to losing precision we need second variable. Conversion to double is to see if 
 607                                   value is too big for a long. As said, precision could be lost.
 608                                 */
 609                                 zval *tmp_data_copy;
 610                                 MAKE_STD_ZVAL(tmp_data_copy);
 611                                 *tmp_data_copy = *tmp_data;
 612                                 Z_SET_REFCOUNT_P(tmp_data_copy, 1);
 613                                 zval_copy_ctor(tmp_data_copy);
 614                                 convert_to_double_ex(&tmp_data_copy);
 615 
 616                                 /*
 617                                   if it doesn't fit in a long send it as a string.
 618                                   Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 619                                   We do transformation here, which will be used later when sending types. The code later relies on this.
 620                                 */
 621                                 if (Z_DVAL_P(tmp_data_copy) > LONG_MAX || Z_DVAL_P(tmp_data_copy) < LONG_MIN) {
 622                                         stmt->send_types_to_server = *resend_types_next_time = 1;
 623                                         convert_to_string_ex(&tmp_data);
 624                                 } else {
 625                                         convert_to_long_ex(&tmp_data);
 626                                 }
 627 
 628                                 zval_ptr_dtor(&tmp_data_copy);
 629                         }
 630                 }
 631         }
 632         DBG_RETURN(PASS);
 633 end:
 634         DBG_RETURN(FAIL);
 635 }
 636 /* }}} */
 637 
 638 
 639 /* {{{ mysqlnd_stmt_execute_store_types */
 640 static void
 641 mysqlnd_stmt_execute_store_types(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar ** p)
 642 {
 643         unsigned int i;
 644         for (i = 0; i < stmt->param_count; i++) {
 645                 short current_type = stmt->param_bind[i].type;
 646                 /* our types are not unsigned */
 647 #if SIZEOF_LONG==8  
 648                 if (current_type == MYSQL_TYPE_LONG) {
 649                         current_type = MYSQL_TYPE_LONGLONG;
 650                 }
 651 #endif
 652                 if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_NULL && (current_type == MYSQL_TYPE_LONG || current_type == MYSQL_TYPE_LONGLONG)) {
 653                         /*
 654                           if it doesn't fit in a long send it as a string.
 655                           Check bug #52891 : Wrong data inserted with mysqli/mysqlnd when using bind_param, value > LONG_MAX
 656                         */
 657                         if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
 658                                 const zval *tmp_data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
 659                                 /*
 660                                   In case of IS_LONG we do nothing, it is ok, in case of string, we just need to set current_type.
 661                                   The actual transformation has been performed several dozens line above.
 662                                 */
 663                                 if (Z_TYPE_P(tmp_data) == IS_STRING) {
 664                                         current_type = MYSQL_TYPE_VAR_STRING;
 665                                         /*
 666                                           don't change stmt->param_bind[i].type to MYSQL_TYPE_VAR_STRING
 667                                           we force convert_to_long_ex in all cases, thus the type will be right in the next switch.
 668                                           if the type is however not long, then we will do a goto in the next switch.
 669                                           We want to preserve the original bind type given by the user. Thus, we do these hacks.
 670                                         */
 671                                 }
 672                         }
 673                 }
 674                 int2store(*p, current_type);
 675                 *p+= 2;
 676         }
 677 }
 678 /* }}} */
 679 
 680 
 681 /* {{{ mysqlnd_stmt_execute_calculate_param_values_size */
 682 static enum_func_status
 683 mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval *** copies_param, size_t * data_size TSRMLS_DC)
 684 {
 685         unsigned int i;
 686         DBG_ENTER("mysqlnd_stmt_execute_calculate_param_values_size");
 687         for (i = 0; i < stmt->param_count; i++) {
 688                 unsigned short is_longlong = 0;
 689                 unsigned int j;
 690                 zval *the_var = stmt->param_bind[i].zv;
 691 
 692                 if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB && Z_TYPE_P(the_var) == IS_NULL)) {
 693                         continue;
 694                 }
 695                 for (j = i + 1; j < stmt->param_count; j++) {
 696                         if (stmt->param_bind[j].zv == the_var) {
 697                                 /* Double binding of the same zval, make a copy */
 698                                 if (!*copies_param || !(*copies_param)[i]) {
 699                                         if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
 700                                                 SET_OOM_ERROR(*stmt->error_info);
 701                                                 goto end;
 702                                         }
 703                                 }
 704                                 break;
 705                         }
 706                 }
 707 
 708                 switch (stmt->param_bind[i].type) {
 709                         case MYSQL_TYPE_DOUBLE:
 710                                 *data_size += 8;
 711                                 if (Z_TYPE_P(the_var) != IS_DOUBLE) {
 712                                         if (!*copies_param || !(*copies_param)[i]) {
 713                                                 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
 714                                                         SET_OOM_ERROR(*stmt->error_info);
 715                                                         goto end;
 716                                                 }
 717                                         }
 718                                 }
 719                                 break;
 720                         case MYSQL_TYPE_LONGLONG:
 721                                 is_longlong = 4;
 722                                 /* fall-through */
 723                         case MYSQL_TYPE_LONG:
 724                                 {
 725                                         zval *tmp_data = (*copies_param && (*copies_param)[i])? (*copies_param)[i]: stmt->param_bind[i].zv;
 726                                         if (Z_TYPE_P(tmp_data) == IS_STRING) {
 727                                                 goto use_string;
 728                                         }
 729                                         convert_to_long_ex(&tmp_data);
 730                                 }
 731                                 *data_size += 4 + is_longlong;
 732                                 break;
 733                         case MYSQL_TYPE_LONG_BLOB:
 734                                 if (!(stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED)) {
 735                                         /*
 736                                           User hasn't sent anything, we will send empty string.
 737                                           Empty string has length of 0, encoded in 1 byte. No real
 738                                           data will follows after it.
 739                                         */
 740                                         (*data_size)++;
 741                                 }
 742                                 break;
 743                         case MYSQL_TYPE_VAR_STRING:
 744 use_string:
 745                                 *data_size += 8; /* max 8 bytes for size */
 746                                 if (Z_TYPE_P(the_var) != IS_STRING) {
 747                                         if (!*copies_param || !(*copies_param)[i]) {
 748                                                 if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i TSRMLS_CC)) {
 749                                                         SET_OOM_ERROR(*stmt->error_info);
 750                                                         goto end;
 751                                                 }
 752                                         }
 753                                         the_var = (*copies_param)[i];
 754                                 }
 755                                 convert_to_string_ex(&the_var);
 756                                 *data_size += Z_STRLEN_P(the_var);
 757                                 break;
 758                 }
 759         }
 760         DBG_RETURN(PASS);
 761 end:
 762         DBG_RETURN(FAIL);
 763 }
 764 /* }}} */
 765 
 766 
 767 /* {{{ mysqlnd_stmt_execute_store_param_values */
 768 static void
 769 mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval ** copies, zend_uchar * buf, zend_uchar ** p, size_t null_byte_offset)
 770 {
 771         unsigned int i;
 772         for (i = 0; i < stmt->param_count; i++) {
 773                 zval * data = (copies && copies[i])? copies[i]: stmt->param_bind[i].zv;
 774                 /* Handle long data */
 775                 if (stmt->param_bind[i].zv && Z_TYPE_P(data) == IS_NULL) {
 776                         (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
 777                 } else {
 778                         switch (stmt->param_bind[i].type) {
 779                                 case MYSQL_TYPE_DOUBLE:
 780                                         convert_to_double_ex(&data);
 781                                         float8store(*p, Z_DVAL_P(data));
 782                                         (*p) += 8;
 783                                         break;
 784                                 case MYSQL_TYPE_LONGLONG:
 785                                         if (Z_TYPE_P(data) == IS_STRING) {
 786                                                 goto send_string;
 787                                         }
 788                                         /* data has alreade been converted to long */
 789                                         int8store(*p, Z_LVAL_P(data));
 790                                         (*p) += 8;
 791                                         break;
 792                                 case MYSQL_TYPE_LONG:
 793                                         if (Z_TYPE_P(data) == IS_STRING) {
 794                                                 goto send_string;
 795                                         }
 796                                         /* data has alreade been converted to long */
 797                                         int4store(*p, Z_LVAL_P(data));
 798                                         (*p) += 4;
 799                                         break;
 800                                 case MYSQL_TYPE_LONG_BLOB:
 801                                         if (stmt->param_bind[i].flags & MYSQLND_PARAM_BIND_BLOB_USED) {
 802                                                 stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
 803                                         } else {
 804                                                 /* send_long_data() not called, send empty string */
 805                                                 *p = php_mysqlnd_net_store_length(*p, 0);
 806                                         }
 807                                         break;
 808                                 case MYSQL_TYPE_VAR_STRING:
 809 send_string:
 810                                         {
 811                                                 size_t len = Z_STRLEN_P(data);
 812                                                 /* to is after p. The latter hasn't been moved */
 813                                                 *p = php_mysqlnd_net_store_length(*p, len);
 814                                                 memcpy(*p, Z_STRVAL_P(data), len);
 815                                                 (*p) += len;
 816                                         }
 817                                         break;
 818                                 default:
 819                                         /* Won't happen, but set to NULL */
 820                                         (buf + null_byte_offset)[i/8] |= (zend_uchar) (1 << (i & 7));
 821                                         break;
 822                         }
 823                 }
 824         }
 825 }
 826 /* }}} */
 827 
 828 
 829 /* {{{ mysqlnd_stmt_execute_store_params */
 830 static enum_func_status
 831 mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar **p, size_t *buf_len  TSRMLS_DC)
 832 {
 833         MYSQLND_STMT_DATA * stmt = s->data;
 834         unsigned int i = 0;
 835         zend_uchar * provided_buffer = *buf;
 836         size_t data_size = 0;
 837         zval **copies = NULL;/* if there are different types */
 838         enum_func_status ret = FAIL;
 839         int resend_types_next_time = 0;
 840         size_t null_byte_offset;
 841 
 842         DBG_ENTER("mysqlnd_stmt_execute_store_params");
 843 
 844         {
 845                 unsigned int null_count = (stmt->param_count + 7) / 8;
 846                 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count TSRMLS_CC)) {
 847                         SET_OOM_ERROR(*stmt->error_info);
 848                         goto end;
 849                 }
 850                 /* put `null` bytes */
 851                 null_byte_offset = *p - *buf;
 852                 memset(*p, 0, null_count);
 853                 *p += null_count;
 854         }
 855 
 856 /* 1. Store type information */
 857         /*
 858           check if need to send the types even if stmt->send_types_to_server is 0. This is because
 859           if we send "i" (42) then the type will be int and the server will expect int. However, if next
 860           time we try to send > LONG_MAX, the conversion to string will send a string and the server
 861           won't expect it and interpret the value as 0. Thus we need to resend the types, if any such values
 862           occur, and force resend for the next execution.
 863         */
 864         if (FAIL == mysqlnd_stmt_execute_prepare_param_types(stmt, &copies, &resend_types_next_time TSRMLS_CC)) {
 865                 goto end;
 866         }
 867 
 868         int1store(*p, stmt->send_types_to_server);
 869         (*p)++;
 870 
 871         if (stmt->send_types_to_server) {
 872                 if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2 TSRMLS_CC)) {
 873                         SET_OOM_ERROR(*stmt->error_info);
 874                         goto end;
 875                 }
 876                 mysqlnd_stmt_execute_store_types(stmt, copies, p);
 877         }
 878 
 879         stmt->send_types_to_server = resend_types_next_time;
 880 
 881 /* 2. Store data */
 882         /* 2.1 Calculate how much space we need */
 883         if (FAIL == mysqlnd_stmt_execute_calculate_param_values_size(stmt, &copies, &data_size TSRMLS_CC)) {
 884                 goto end;
 885         }
 886 
 887         /* 2.2 Enlarge the buffer, if needed */
 888         if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size TSRMLS_CC)) {
 889                 SET_OOM_ERROR(*stmt->error_info);
 890                 goto end;
 891         }
 892 
 893         /* 2.3 Store the actual data */
 894         mysqlnd_stmt_execute_store_param_values(stmt, copies, *buf, p, null_byte_offset);
 895 
 896         ret = PASS;
 897 end:
 898         mysqlnd_stmt_free_copies(stmt, copies TSRMLS_CC);
 899 
 900         DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
 901         DBG_RETURN(ret);
 902 }
 903 /* }}} */
 904 
 905 
 906 /* {{{ mysqlnd_stmt_execute_generate_request */
 907 enum_func_status
 908 mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer TSRMLS_DC)
 909 {
 910         MYSQLND_STMT_DATA * stmt = s->data;
 911         zend_uchar      *p = stmt->execute_cmd_buffer.buffer,
 912                                 *cmd_buffer = stmt->execute_cmd_buffer.buffer;
 913         size_t cmd_buffer_length = stmt->execute_cmd_buffer.length;
 914         enum_func_status ret;
 915 
 916         DBG_ENTER("mysqlnd_stmt_execute_generate_request");
 917 
 918         int4store(p, stmt->stmt_id);
 919         p += 4;
 920 
 921         /* flags is 4 bytes, we store just 1 */
 922         int1store(p, (zend_uchar) stmt->flags);
 923         p++;
 924 
 925         /* Make it all zero */
 926         int4store(p, 0); 
 927 
 928         int1store(p, 1); /* and send 1 for iteration count */
 929         p+= 4;
 930 
 931         ret = mysqlnd_stmt_execute_store_params(s, &cmd_buffer, &p, &cmd_buffer_length TSRMLS_CC);
 932 
 933         *free_buffer = (cmd_buffer != stmt->execute_cmd_buffer.buffer);
 934         *request_len = (p - cmd_buffer);
 935         *request = cmd_buffer;
 936         DBG_INF_FMT("ret=%s", ret == PASS? "PASS":"FAIL");
 937         DBG_RETURN(ret);
 938 }
 939 /* }}} */
 940 
 941 /*
 942  * Local variables:
 943  * tab-width: 4
 944  * c-basic-offset: 4
 945  * End:
 946  * vim600: noet sw=4 ts=4 fdm=marker
 947  * vim<600: noet sw=4 ts=4
 948  */

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