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

Generated by: LCOV version 1.10

Generated at Sun, 29 Mar 2015 03:45:53 +0000 (3 days ago)

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