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

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:52 +0000 (3 days ago)

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