Annotation of embedaddon/php/ext/mysqlnd/mysqlnd_ps_codec.c, revision 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>