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

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

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