/* {{{ 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; }
static void convert_from_long(MYSQL_BIND *r_param, const MYSQL_FIELD *field, longlong val, my_bool is_unsigned) { switch (r_param->buffer_type) { case MYSQL_TYPE_TINY: *(uchar *)r_param->buffer= (uchar)val; *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8); r_param->buffer_length= 1; break; case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: shortstore(r_param->buffer, (short)val); *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16); r_param->buffer_length= 2; break; case MYSQL_TYPE_LONG: longstore(r_param->buffer, (int32)val); *r_param->error= r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32); r_param->buffer_length= 4; break; case MYSQL_TYPE_LONGLONG: *r_param->error= (val < 0 && r_param->is_unsigned != is_unsigned); longlongstore(r_param->buffer, val); r_param->buffer_length= 8; break; case MYSQL_TYPE_DOUBLE: { volatile double dbl; dbl= (is_unsigned) ? ulonglong2double((ulonglong)val) : (double)val; doublestore(r_param->buffer, dbl); *r_param->error= is_unsigned ? (ulonglong )dbl != (ulonglong)val : (longlong)dbl != (longlong)val; r_param->buffer_length= 8; break; } case MYSQL_TYPE_FLOAT: { float fval; fval= is_unsigned ? (float)(ulonglong)(val) : (float)val; float4store(r_param->buffer, fval); *r_param->error= is_unsigned ? (ulonglong)fval != (ulonglong)val : (longlong)fval != val; r_param->buffer_length= 4; } break; default: { char buffer[22]; char *endptr; uint len; endptr= ma_ll2str(val, buffer, is_unsigned ? 10 : -10); len= (uint)(endptr - buffer); /* check if field flag is zerofill */ convert_froma_string(r_param, buffer, len); } break; } }
static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size) { double check_trunc_val= (val > 0) ? floor(val) : -floor(-val); char *buf= (char *)r_param->buffer; switch (r_param->buffer_type) { case MYSQL_TYPE_TINY: *buf= (r_param->is_unsigned) ? (uint8)val : (int8)val; *r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) : (double)((int8)*buf)); r_param->buffer_length= 1; break; case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: { if (r_param->is_unsigned) { ushort sval= (ushort)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } else { short sval= (short)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } r_param->buffer_length= 2; } break; case MYSQL_TYPE_LONG: { if (r_param->is_unsigned) { uint32 lval= (uint32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } else { int32 lval= (int32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } r_param->buffer_length= 4; } break; case MYSQL_TYPE_LONGLONG: { if (r_param->is_unsigned) { ulonglong llval= (ulonglong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } else { longlong llval= (longlong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } r_param->buffer_length= 8; } break; case MYSQL_TYPE_FLOAT: { float fval= (float)val; memcpy(buf, &fval, sizeof(float)); *r_param->error= (*(float*)buf != fval); r_param->buffer_length= 4; } break; default: { char buff[MAX_DOUBLE_STRING_REP_LENGTH]; size_t length; length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length); if (field->decimals >= NOT_FIXED_DEC) { length= ma_gcvt(val, MY_GCVT_ARG_DOUBLE, length, buff, NULL); } else { length= ma_fcvt(val, field->decimals, buff, NULL); } /* check if ZEROFILL flag is active */ if (field->flags & ZEROFILL_FLAG) { /* enough space available ? */ if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1) break; ma_bmove_upp(buff + field->length, buff + length, length); memset((char*) buff, 0, field->length - length); } convert_froma_string(r_param, buff, strlen(buff)); } break; } }
static void convert_froma_string(MYSQL_BIND *r_param, char *buffer, size_t len) { int error= 0; switch (r_param->buffer_type) { case MYSQL_TYPE_TINY: { longlong val= my_atoll(buffer, buffer + len, &error); *r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX8) : NUMERIC_TRUNCATION(val, INT_MIN8, INT_MAX8) || error > 0; int1store(r_param->buffer, (uchar) val); r_param->buffer_length= sizeof(uchar); } break; case MYSQL_TYPE_YEAR: case MYSQL_TYPE_SHORT: { longlong val= my_atoll(buffer, buffer + len, &error); *r_param->error= error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX16) : NUMERIC_TRUNCATION(val, INT_MIN16, INT_MAX16) || error > 0; shortstore(r_param->buffer, (short)val); r_param->buffer_length= sizeof(short); } break; case MYSQL_TYPE_LONG: { longlong val= my_atoll(buffer, buffer + len, &error); *r_param->error=error ? 1 : r_param->is_unsigned ? NUMERIC_TRUNCATION(val, 0, UINT_MAX32) : NUMERIC_TRUNCATION(val, INT_MIN32, INT_MAX32) || error > 0; longstore(r_param->buffer, (int32)val); r_param->buffer_length= sizeof(uint32); } break; case MYSQL_TYPE_LONGLONG: { longlong val= my_atoll(buffer, buffer + len, &error); *r_param->error= error > 0; /* no need to check for truncation */ longlongstore(r_param->buffer, val); r_param->buffer_length= sizeof(longlong); } break; case MYSQL_TYPE_DOUBLE: { double val= my_atod(buffer, buffer + len, &error); *r_param->error= error > 0; /* no need to check for truncation */ float8store(r_param->buffer, val); r_param->buffer_length= sizeof(double); } break; case MYSQL_TYPE_FLOAT: { float val= (float)my_atod(buffer, buffer + len, &error); *r_param->error= error > 0; /* no need to check for truncation */ float4store(r_param->buffer, val); r_param->buffer_length= sizeof(float); } break; case MYSQL_TYPE_TIME: case MYSQL_TYPE_DATE: case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: { MYSQL_TIME *tm= (MYSQL_TIME *)r_param->buffer; str_to_TIME(buffer, len, tm); break; } break; case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: default: { char *start= buffer + r_param->offset; /* stmt_fetch_column sets offset */ char *end= buffer + len; size_t copylen= 0; if (start < end) { copylen= end - start; if (r_param->buffer_length) memcpy(r_param->buffer, start, MIN(copylen, r_param->buffer_length)); } if (copylen < r_param->buffer_length) ((char *)r_param->buffer)[copylen]= '\0'; *r_param->error= (copylen > r_param->buffer_length); *r_param->length= (ulong)len; } break; } }
static void convert_from_double(MYSQL_BIND *r_param, const MYSQL_FIELD *field, double val, int size) { double check_trunc_val= (val > 0) ? floor(val) : -floor(-val); char *buf= (char *)r_param->buffer; switch (r_param->buffer_type) { case MYSQL_TYPE_TINY: *buf= (r_param->is_unsigned) ? (uint8)val : (int8)val; *r_param->error= check_trunc_val != (r_param->is_unsigned ? (double)((uint8)*buf) : (double)((int8)*buf)); r_param->buffer_length= 1; break; case MYSQL_TYPE_SHORT: case MYSQL_TYPE_YEAR: { if (r_param->is_unsigned) { ushort sval= (ushort)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } else { short sval= (short)val; shortstore(buf, sval); *r_param->error= check_trunc_val != (double)sval; } r_param->buffer_length= 2; } break; case MYSQL_TYPE_LONG: { if (r_param->is_unsigned) { uint32 lval= (uint32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } else { int32 lval= (int32)val; longstore(buf, lval); *r_param->error= (check_trunc_val != (double)lval); } r_param->buffer_length= 4; } break; case MYSQL_TYPE_LONGLONG: { if (r_param->is_unsigned) { ulonglong llval= (ulonglong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } else { longlong llval= (longlong)val; longlongstore(buf, llval); *r_param->error= (check_trunc_val != (double)llval); } r_param->buffer_length= 8; } break; case MYSQL_TYPE_FLOAT: { float fval= (float)val; memcpy(buf, &fval, sizeof(float)); *r_param->error= (*(float*)buf != fval); r_param->buffer_length= 4; } break; default: { #define MAX_DOUBLE_STRING_REP_LENGTH 300 char buff[MAX_DOUBLE_STRING_REP_LENGTH]; size_t length; char *end; length= MIN(MAX_DOUBLE_STRING_REP_LENGTH - 1, r_param->buffer_length); if (field->decimals >= NOT_FIXED_DEC) { sprintf(buff, "%-*.*g", (int) length-1, DBL_DIG, val); length= strlen(buff); } else { #ifdef _WIN32 #else gcvt(val, field->decimals, buff); #endif // sprintf(buff, "%.*f", field->decimals, val); length= strlen(buff); } /* remove trailing blanks */ end= strchr(buff, '\0') - 1; while (end > buff && *end == ' ') *end--= '\0'; /* check if ZEROFILL flag is active */ if (field->flags & ZEROFILL_FLAG) { /* enough space available ? */ if (field->length < length || field->length > MAX_DOUBLE_STRING_REP_LENGTH - 1) break; ma_bmove_upp(buff + field->length, buff + length, length); memset((char*) buff, 0, field->length - length); } convert_froma_string(r_param, buff, strlen(buff)); } break; } }