Return to mysqlnd_ps_codec.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / mysqlnd |
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: */