PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mysqlnd - mysqlnd_ps_codec.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 410 454 90.3 %
Date: 2016-07-26 Functions: 22 23 95.7 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:38 +0000 (3 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.