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: 402 448 89.7 %
Date: 2014-09-21 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10

Generated at Sun, 21 Sep 2014 15:27:38 +0000 (2 days ago)

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