/* {{{ ps_fetch_int64 */ static void ps_fetch_int64(MYSQL_BIND *r_param, const MYSQL_FIELD * const field, unsigned char **row) { switch(r_param->buffer_type) { /* case MYSQL_TYPE_TINY: ps_fetch_from_1_to_8_bytes(r_param, field, row, 1); break; case MYSQL_TYPE_YEAR: case MYSQL_TYPE_SHORT: ps_fetch_from_1_to_8_bytes(r_param, field, row, 2); break; case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: ps_fetch_from_1_to_8_bytes(r_param, field, row, 4); break; */ case MYSQL_TYPE_LONGLONG: ps_fetch_from_1_to_8_bytes(r_param, field, row, 8); break; default: { longlong sval= (longlong)sint8korr(*row); longlong lval= field->flags & UNSIGNED_FLAG ? (ulonglong) sval : (longlong)sval; convert_from_long(r_param, field, lval, field->flags & UNSIGNED_FLAG); (*row) += 8; } break; } }
/* {{{ ps_fetch_from_1_to_8_bytes */ void ps_fetch_from_1_to_8_bytes(MYSQL_BIND *r_param, const MYSQL_FIELD * const field, unsigned char **row, unsigned int byte_count) { my_bool is_unsigned= test(field->flags & UNSIGNED_FLAG); r_param->buffer_length= byte_count; switch (byte_count) { case 1: *(uchar *)r_param->buffer= **row; *r_param->error= is_unsigned != r_param->is_unsigned && *(uchar *)r_param->buffer > INT_MAX8; break; case 2: shortstore(r_param->buffer, ((ushort) sint2korr(*row))); *r_param->error= is_unsigned != r_param->is_unsigned && *(ushort *)r_param->buffer > INT_MAX16; break; case 4: { longstore(r_param->buffer, ((uint32)sint4korr(*row))); *r_param->error= is_unsigned != r_param->is_unsigned && *(uint32 *)r_param->buffer > INT_MAX32; } break; case 8: { ulonglong val= (ulonglong)sint8korr(*row); longlongstore(r_param->buffer, val); *r_param->error= is_unsigned != r_param->is_unsigned && val > LONGLONG_MAX ; } break; default: r_param->buffer_length= 0; break; } (*row)+= byte_count; }
/* {{{ ps_fetch_from_1_to_8_bytes */ void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar **row, zend_bool as_unicode, unsigned int byte_count TSRMLS_DC) { char tmp[22]; size_t tmp_len = 0; zend_bool is_bit = field->type == MYSQL_TYPE_BIT; DBG_ENTER("ps_fetch_from_1_to_8_bytes"); DBG_INF_FMT("zv=%p byte_count=%d", zv, byte_count); if (field->flags & UNSIGNED_FLAG) { uint64_t uval = 0; switch (byte_count) { case 8:uval = is_bit? (uint64_t) bit_uint8korr(*row):(uint64_t) uint8korr(*row);break; case 7:uval = bit_uint7korr(*row);break; case 6:uval = bit_uint6korr(*row);break; case 5:uval = bit_uint5korr(*row);break; case 4:uval = is_bit? (uint64_t) bit_uint4korr(*row):(uint64_t) uint4korr(*row);break; case 3:uval = is_bit? (uint64_t) bit_uint3korr(*row):(uint64_t) uint3korr(*row);break; case 2:uval = is_bit? (uint64_t) bit_uint2korr(*row):(uint64_t) uint2korr(*row);break; case 1:uval = (uint64_t) uint1korr(*row);break; } #if SIZEOF_LONG==4 if (uval > INT_MAX) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); } else #endif /* #if SIZEOF_LONG==4 */ { if (byte_count < 8 || uval <= L64(9223372036854775807)) { ZVAL_LONG(zv, uval); } else { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval); } } } else { /* SIGNED */ int64_t lval = 0; switch (byte_count) { case 8:lval = (int64_t) sint8korr(*row);break; /* 7, 6 and 5 are not possible. BIT is only unsigned, thus only uint5|6|7 macroses exist */ case 4:lval = (int64_t) sint4korr(*row);break; case 3:lval = (int64_t) sint3korr(*row);break; case 2:lval = (int64_t) sint2korr(*row);break; case 1:lval = (int64_t) *(int8_t*)*row;break; } #if SIZEOF_LONG==4 if ((L64(2147483647) < (int64_t) lval) || (L64(-2147483648) > (int64_t) lval)) { DBG_INF("stringify"); tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval); } else #endif /* SIZEOF */ { ZVAL_LONG(zv, lval); } } if (tmp_len) { #if PHP_MAJOR_VERSION >= 6 if (as_unicode) { DBG_INF("stringify"); ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE); } else #endif { DBG_INF("stringify"); ZVAL_STRINGL(zv, tmp, tmp_len, 1); } } (*row)+= byte_count; DBG_VOID_RETURN; }
/************************************************** read data in binary type **************************************************/ int mysac_decode_binary_row(char *buf, int packet_len, MYSAC_RES *res, MYSAC_ROWS *row) { int j; int i; char nul; unsigned long len; int tmp_len; char *wh; char _null_ptr[16]; char *null_ptr; unsigned char bit; wh = buf; null_ptr = _null_ptr; bit = 4; /* first 2 bits are reserved */ /* first bit is unused */ i = 1; /* skip null bits */ tmp_len = ( (res->nb_cols + 9) / 8 ); if (i + tmp_len > packet_len) return -1; memcpy(_null_ptr, &buf[i], tmp_len); i += tmp_len; for (j = 0; j < res->nb_cols; j++) { /* We should set both row_ptr and is_null to be able to see nulls in mysql_stmt_fetch_column. This is because is_null may point to user data which can be overwritten between mysql_stmt_fetch and mysql_stmt_fetch_column, and in this case nullness of column will be lost. See mysql_stmt_fetch_column for details. */ if ( (*null_ptr & bit) != 0 ) { /* do nothing */ } else { switch (res->cols[j].type) { /* read null */ case MYSQL_TYPE_NULL: row->data[j].blob = NULL; /* read blob */ case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: /* decimal ? maybe for very big num ... crypto key ? */ case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: /* .... */ case MYSQL_TYPE_BIT: /* read text */ case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: /* read date */ case MYSQL_TYPE_NEWDATE: tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i); if (tmp_len == -1) return -1; i += tmp_len; if (i + len > (unsigned int)packet_len) return -1; if (nul == 1) row->data[j].blob = NULL; else { memmove(wh, &buf[i], len); row->data[j].blob = wh; row->data[j].blob[len] = '\0'; i += len; wh += len + 1; } row->lengths[j] = len; break; case MYSQL_TYPE_TINY: if (i > packet_len - 1) return -1; row->data[j].stiny = buf[i]; i++; break; case MYSQL_TYPE_SHORT: if (i > packet_len - 2) return -1; row->data[j].ssmall = sint2korr(&buf[i]); i += 2; break; case MYSQL_TYPE_INT24: case MYSQL_TYPE_LONG: if (i > packet_len - 4) return -1; row->data[j].sint = sint4korr(&buf[i]); i += 4; break; case MYSQL_TYPE_LONGLONG: if (i > packet_len - 8) return -1; row->data[j].sbigint = sint8korr(&buf[i]); i += 8; break; case MYSQL_TYPE_FLOAT: if (i > packet_len - 4) return -1; float4get(row->data[j].mfloat, &buf[i]); i += 4; break; case MYSQL_TYPE_DOUBLE: if (i > packet_len - 8) return -1; float8get(row->data[j].mdouble, &buf[i]); i += 8; break; /* libmysql/libmysql.c:3370 * static void read_binary_time(MYSQL_TIME *tm, uchar **pos) */ case MYSQL_TYPE_TIME: tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i); if (tmp_len == -1) return -1; i += tmp_len; if (i + len > (unsigned int)packet_len) return -1; if (nul == 1) row->data[j].blob = NULL; if (len > 0) { row->data[j].tv.tv_sec = ( uint4korr(&buf[i+1]) * 86400 ) + ( buf[i+5] * 3600 ) + ( buf[i+6] * 60 ) + buf[i+7]; if (buf[i] != 0) row->data[j].tv.tv_sec = - row->data[j].tv.tv_sec; if (len > 8) row->data[j].tv.tv_usec = uint4korr(&buf[i+8]); else row->data[j].tv.tv_usec = 0; } i += len; break; case MYSQL_TYPE_YEAR: row->data[j].tm->tm_year = uint2korr(&buf[i]) - 1900; row->data[j].tm->tm_mday = 1; i += 2; break; /* libmysql/libmysql.c:3400 * static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos) */ case MYSQL_TYPE_TIMESTAMP: case MYSQL_TYPE_DATETIME: tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i); if (tmp_len == -1) return -1; i += tmp_len; if (i + len > (unsigned int)packet_len) return -1; if (nul == 1) row->data[j].blob = NULL; row->data[j].tm->tm_year = uint2korr(&buf[i+0]) - 1900; row->data[j].tm->tm_mon = buf[i+2] - 1; row->data[j].tm->tm_mday = buf[i+3]; if (len > 4) { row->data[j].tm->tm_hour = buf[i+4]; row->data[j].tm->tm_min = buf[i+5]; row->data[j].tm->tm_sec = buf[i+6]; } if (len > 7) { /* les microsecondes ... */ } i += len; break; /* libmysql/libmysql.c:3430 * static void read_binary_date(MYSQL_TIME *tm, uchar **pos) */ case MYSQL_TYPE_DATE: tmp_len = my_lcb(&buf[i], &len, &nul, packet_len-i); if (tmp_len == -1) return -1; i += tmp_len; if (i + len > (unsigned int)packet_len) return -1; if (nul == 1) row->data[j].blob = NULL; row->data[j].tm->tm_year = uint2korr(&buf[i+0]) - 1900; row->data[j].tm->tm_mon = buf[i+2] - 1; row->data[j].tm->tm_mday = buf[i+3]; i += len; break; case MYSQL_TYPE_ENUM: case MYSQL_TYPE_SET: case MYSQL_TYPE_GEOMETRY: break; } } /* To next bit */ bit <<= 1; /* To next byte */ if ( (bit & 255) == 0 ) { bit = 1; null_ptr++; } } return wh - buf; }