Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_ps_codec.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>