maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #04069
Dynamic column for review
Hi!
Here is 2 patches: one cut version - to review, other one full version.
=== added file 'include/ma_dyncol.h'
--- include/ma_dyncol.h 1970-01-01 00:00:00 +0000
+++ include/ma_dyncol.h 2011-04-29 09:52:28 +0000
@@ -0,0 +1,101 @@
+#ifndef ma_dyncol_h
+#define ma_dyncol_h
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <decimal.h>
+#include <my_decimal_limits.h>
+#include <mysql_time.h>
+
+#define ER_DYNCOL_YES 1
+/* NO and OK is the same used just to show semantics */
+#define ER_DYNCOL_NO 0
+#define ER_DYNCOL_OK 0
+/* Wrong format of the string with encoded columns */
+#define ER_DYNCOL_FORMAT -1
+/* Some limit reached */
+#define ER_DYNCOL_LIMIT -2
+/* Out of resourses */
+#define ER_DYNCOL_RESOURCE -3
+/* Incorrect input data */
+#define ER_DYNCOL_DATA -4
+
+typedef DYNAMIC_STRING DYNAMIC_COLUMN;
+
+enum enum_dynamic_column_type
+{
+ DYN_COL_NULL= 0,
+ DYN_COL_INT,
+ DYN_COL_UINT,
+ DYN_COL_DOUBLE,
+ DYN_COL_STRING,
+ DYN_COL_DECIMAL,
+ DYN_COL_DATETIME,
+ DYN_COL_DATE,
+ DYN_COL_TIME
+};
+
+typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE;
+
+struct st_dynamic_column_value
+{
+ DYNAMIC_COLUMN_TYPE type;
+ union
+ {
+ long long long_value;
+ unsigned long long ulong_value;
+ double double_value;
+ struct {
+ LEX_STRING string_value;
+ CHARSET_INFO *charset;
+ };
+ struct {
+ decimal_digit_t decimal_buffer[DECIMAL_BUFF_LENGTH];
+ decimal_t decimal_value;
+ };
+ MYSQL_TIME time_value;
+ };
+};
+
+typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE;
+
+int dynamic_column_create(DYNAMIC_COLUMN *str,
+ uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value);
+
+int dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+
+int dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value);
+int dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+
+int dynamic_column_delete(DYNAMIC_COLUMN *org, uint column_nr);
+
+int dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
+
+/* List of not NULL columns */
+int dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
+
+/*
+ if the column do not exists it is NULL
+*/
+int dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here);
+
+#define dynamic_column_column_free(V) dynstr_free(V)
+
+#define dynamic_column_value_init(V) (V)->type= DYN_COL_NULL
+
+/*
+ Prepare value for using as decimal
+*/
+void dynamic_column_prepare_decimal(DYNAMIC_COLUMN_VALUE *value);
+
+#endif
=== added file 'mysql-test/r/dyncol.result'
--- mysql-test/r/dyncol.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/dyncol.result 2011-04-29 11:07:51 +0000
[skip]
+# column add
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer))
+00020001000002001078097809
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer))
+0001000100007809
+select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer))
+000000
+select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer))
+0001000100007809
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer))
+000200010000020008167809
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer);
+column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer)
+11
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer);
+column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer)
+1212
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer))
+000200010000020010780916
+select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer));
+hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer))
+000200010000020010780916
+select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer))
+000200010000020008167809
+# column delete
+select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1));
+hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1))
+0001000200007809
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2))
+0002000100000300080206
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3))
+0002000100000200080204
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4))
+000300010000020008030010020406
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1))
+00010003000006
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3))
+00010001000002
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3))
+000000
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10))
+000000
+# column exists
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1);
+column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1)
+1
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4);
+column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4)
+0
+# column list
+select column_list(column_create(1, 1212 as integer, 2, 1212 as integer));
+column_list(column_create(1, 1212 as integer, 2, 1212 as integer))
+1,2
+select column_list(column_create(1, 1212 as integer));
+column_list(column_create(1, 1212 as integer))
+1
+select column_list(column_create(1, NULL as integer));
+column_list(column_create(1, NULL as integer))
+
=== added file 'mysql-test/t/dyncol.test'
--- mysql-test/t/dyncol.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/dyncol.test 2011-04-29 11:02:53 +0000
[skip]
+-- echo # column add
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer));
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer));
+select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer));
+select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer));
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer));
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer);
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer);
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer));
+select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer));
+select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer));
+
+-- echo # column delete
+select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10));
+
+-- echo # column exists
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1);
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4);
+
+-- echo # column list
+select column_list(column_create(1, 1212 as integer, 2, 1212 as integer));
+select column_list(column_create(1, 1212 as integer));
+select column_list(column_create(1, NULL as integer));
=== added file 'mysys/ma_dyncol.c'
--- mysys/ma_dyncol.c 1970-01-01 00:00:00 +0000
+++ mysys/ma_dyncol.c 2011-04-29 09:52:28 +0000
@@ -0,0 +1,1831 @@
+#include <ma_dyncol.h>
+
+/*
+ Flag byte bits
+
+ 2 bits which determinate size of offset in the header -1
+*/
+/* mask to get above bits */
+#define DYNCOL_FLG_OFFSET 3
+/* All known flags mask */
+#define DYNCOL_FLG_KNOWN 3
+
+/* dynamic column size reserve */
+#define DYNCOL_SYZERESERVE 80
+
+/* length of fixed string header 1 byte - flags, 2 bytes - columns counter */
+#define FIXED_HEADER_SIZE 3
+
+#define COLUMN_NUMBER_SIZE 2
+
+
+static int dynamic_column_time_add(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value);
+static int dynamic_column_date_add(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value);
+static int
+dynamic_column_time_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+static int
+dynamic_column_date_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+
+/**
+ Initialize dynamic column string with (make it empty but correct format)
+
+ @param str The string to initialize
+ @param size Amount of preallocated memory for the string
+
+ @retval FALSE OK
+ @retval TRUE error
+*/
+
+my_bool dynamic_column_init_str(DYNAMIC_COLUMN *str, size_t size)
+{
+ if (!size)
+ size= DYNCOL_SYZERESERVE;
+ /*
+ Make string with no fields (empty header)
+ - First \0 is flags
+ - other four \0 is 0 fileds counter
+ */
+ if (init_dynamic_string(str, NULL,
+ size + FIXED_HEADER_SIZE, DYNCOL_SYZERESERVE))
+ return TRUE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ return FALSE;
+}
+
+
+/**
+ Calculate how many bytes needed to store val as variable length integer
+ where fist bit indicate continuation of the sequence.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+static size_t dynamic_column_var_uint_bytes(ulonglong val)
+{
+ size_t len= 0;
+ do
+ {
+ len++;
+ val>>= 7;
+ } while (val);
+ return len;
+}
+
+
+/**
+ Add variable value int to the string.
+
+ @param str The string where to put the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_var_uint_add(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (dynstr_realloc(str, 10)) // max what we can use
+ return ER_DYNCOL_RESOURCE;
+
+ do
+ {
+ ulonglong rest= val >> 7;
+ str->str[str->length++]= ((val & 0x7f) | (rest ? 0x80 : 0x00));
+ val= rest;
+ } while (val);
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Reads variable length unsigned int value from the string
+
+ @param data The string which should be read
+ @param len Where to put length of the string read in bytes
+
+ @return value of the unsigned integer read from the string
+*/
+
+ulonglong dynamic_column_var_uint_get(uchar *data, size_t *len)
+{
+ ulonglong val= 0;
+ *len= 0;
+ for(;;)
+ {
+ val+= (((ulonglong)(data[len[0]] & 0x7f)) << (len[0]*7));
+ if (!(data[len[0]] & 0x80))
+ break;
+ len[0]++;
+ }
+ len[0]++;
+ return val;
+}
+
+/**
+ Calculate how many bytes needed to store val as unsigned.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_uint_bytes(ulonglong val)
+{
+ size_t len= 0;
+ do
+ {
+ len++;
+ val>>= 8;
+ } while (val);
+ return len;
+}
+
+
+/**
+ Append the string with given unsigned int value.
+
+ @param str The string where to put the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_uint_add(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (dynstr_realloc(str, 8)) // max what we can use
+ return ER_DYNCOL_RESOURCE;
+ do
+ {
+ str->str[str->length++]= val & 0xff;
+ val>>= 8;
+ } while (val);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read unsigned int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_uint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ ulonglong value= 0;
+ size_t i;
+ for (i= 0; i < length; i++)
+ {
+ value+= ((ulonglong)data[i]) << (i*8);
+ }
+ store_it_here->ulong_value= value;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Calculate how many bytes needed to store val as signed in following encoding:
+ 0 -> 0
+ -1 -> 1
+ 1 -> 2
+ -2 -> 3
+ 2 -> 4
+ ...
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_sint_bytes(longlong val)
+{
+ return dynamic_column_uint_bytes((val << 1) ^
+ (val < 0 ? ULL(0xffffffffffffffff) : 0));
+}
+
+
+/**
+ Append the string with given signed int value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_sint_add(DYNAMIC_COLUMN *str, longlong val)
+{
+ return dynamic_column_uint_add(str,
+ (val << 1) ^
+ (val < 0 ? ULL(0xffffffffffffffff) : 0));
+}
+
+
+/**
+ Read signed int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_sint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ ulonglong val;
+ dynamic_column_uint_read(store_it_here, data, length);
+ val= store_it_here->ulong_value;
+ if (val & 1)
+ val= (val >> 1) ^ ULL(0xffffffffffffffff);
+ else
+ val>>= 1;
+ store_it_here->long_value= (longlong)(val);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Calculate how many bytes needed to store the value.
+
+ @param value The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_value_len(DYNAMIC_COLUMN_VALUE *value)
+{
+ switch (value->type) {
+ case DYN_COL_NULL:
+ return 0;
+ case DYN_COL_INT:
+ return dynamic_column_sint_bytes(value->long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_bytes(value->ulong_value);
+ case DYN_COL_DOUBLE:
+ return 8;
+ case DYN_COL_STRING:
+ return (dynamic_column_var_uint_bytes(value->charset->number) +
+ value->string_value.length);
+ case DYN_COL_DECIMAL:
+ return (dynamic_column_var_uint_bytes(value->decimal_value.intg) +
+ dynamic_column_var_uint_bytes(value->decimal_value.frac) +
+ decimal_bin_size(value->decimal_value.intg +
+ value->decimal_value.frac,
+ value->decimal_value.frac));
+ case DYN_COL_DATETIME:
+ /* date+time in bits: 14 + 4 + 5 + 10 + 6 + 6 + 20 + 1 66bits ~= 9 bytes */
+ return 9;
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return 3;
+ case DYN_COL_TIME:
+ /* time in bits: 10 + 6 + 6 + 20 + 1 = 43bits ~= 6bytes*/
+ return 6;
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+
+/**
+ Append the string with given double value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_double_add(DYNAMIC_COLUMN *str, double val)
+{
+ if (dynstr_realloc(str, 8))
+ return ER_DYNCOL_RESOURCE;
+ float8store(str->str + str->length, val);
+ str->length+= 8;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Read double value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_double_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 8)
+ return ER_DYNCOL_FORMAT;
+ float8get(store_it_here->double_value, data);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given string value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_string_add(DYNAMIC_COLUMN *str, LEX_STRING *string,
+ CHARSET_INFO *charset)
+{
+ int rc;
+ if ((rc= dynamic_column_var_uint_add(str, charset->number)))
+ return rc;
+ if (dynstr_append_mem(str, string->str, string->length))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read string value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_string_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ size_t len;
+ store_it_here->charset= get_charset(dynamic_column_var_uint_get(data, &len),
+ MYF(0));
+ if (store_it_here->charset == NULL || len > length)
+ return ER_DYNCOL_FORMAT;
+ data+= len;
+ store_it_here->string_value.length= (length-= len);
+ store_it_here->string_value.str= (char*)data;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given decimal value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_decimal_add(DYNAMIC_COLUMN *str,
+ decimal_t *value)
+{
+ int rc;
+ uint bin_size= decimal_bin_size(value->intg + value->frac, value->frac);
+ if ((rc= dynamic_column_var_uint_add(str, value->intg)) ||
+ (rc= dynamic_column_var_uint_add(str, value->frac)))
+ return rc;
+ if (dynstr_realloc(str, bin_size))
+ return ER_DYNCOL_RESOURCE;
+ decimal2bin(value, (uchar *)str->str + str->length, value->intg + value->frac,
+ value->frac);
+ str->length+= bin_size;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Prepare the value to be used as decimal.
+
+ @param value The value structure which sould be setup.
+*/
+
+void dynamic_column_prepare_decimal(DYNAMIC_COLUMN_VALUE *value)
+{
+ value->decimal_value.buf= value->decimal_buffer;
+ value->decimal_value.len= DECIMAL_BUFF_LENGTH;
+ // just to be safe
+ value->type= DYN_COL_DECIMAL;
+ decimal_make_zero(&value->decimal_value);
+}
+
+
+/**
+ Read decimal value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_decimal_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length __attribute__((unused)))
+{
+ size_t len;
+ uint intg, frac;
+
+ dynamic_column_prepare_decimal(store_it_here);
+ intg= dynamic_column_var_uint_get(data, &len);
+ data+= len;
+ frac= dynamic_column_var_uint_get(data, &len);
+ data+= len;
+ if (bin2decimal(data, &store_it_here->decimal_value, intg + frac, frac) !=
+ E_DEC_OK)
+ return ER_DYNCOL_FORMAT;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given datetime value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_time_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ int rc;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if ((rc= dynamic_column_date_add(str, value)) ||
+ (rc= dynamic_column_time_add(str, value)))
+ return rc;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read datetime value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ uint rc= ER_DYNCOL_FORMAT;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if (length != 9)
+ goto err;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ if ((rc= dynamic_column_date_read_int(store_it_here, data, 3)) ||
+ (rc= dynamic_column_time_read_int(store_it_here, data + 3, 6)))
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return rc;
+}
+
+
+/**
+ Append the string with given time value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ uchar *buf= ((uchar *)str->str) + str->length;
+ if (dynstr_realloc(str, 6))
+ return ER_DYNCOL_RESOURCE;
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_DATE)
+ value->neg= value->second_part= value->hour=
+ value->minute= value->second= 0;
+ DBUG_ASSERT(value->hour <= 838);
+ DBUG_ASSERT(value->minute <= 59);
+ DBUG_ASSERT(value->second <= 59);
+ DBUG_ASSERT(value->second_part <= 999999);
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ buf[0]= (value->second_part & 0xff);
+ buf[1]= ((value->second_part & 0xff00) >> 8);
+ buf[2]= (((value->second & 0xf) << 4) |
+ ((value->second_part & 0xf0000) >> 16));
+ buf[3]= ((value->minute << 2) | ((value->second & 0x30) >> 4));
+ buf[4]= (value->hour & 0xff);
+ buf[5]= ((value->neg ? 0x4 : 0) | (value->hour >> 8));
+ str->length+= 6;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read time value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ store_it_here->time_value.year= store_it_here->time_value.month=
+ store_it_here->time_value.day= 0;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ return dynamic_column_time_read_int(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading time part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 6)
+ goto err;
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ store_it_here->time_value.second_part= (data[0] |
+ (data[1] << 8) |
+ ((data[2] & 0xf) << 16));
+ store_it_here->time_value.second= ((data[2] >> 4) |
+ ((data[3] & 0x3) << 4));
+ store_it_here->time_value.minute= (data[3] >> 2);
+ store_it_here->time_value.hour= (((((uint)data[5]) & 0x3 ) << 8) | data[4]);
+ store_it_here->time_value.neg= ((data[5] & 0x4) ? 1 : 0);
+ if (store_it_here->time_value.second > 59 ||
+ store_it_here->time_value.minute > 59 ||
+ store_it_here->time_value.hour > 838 ||
+ store_it_here->time_value.second_part > 999999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given date value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ uchar *buf= ((uchar *)str->str) + str->length;
+ if (dynstr_realloc(str, 3))
+ return ER_DYNCOL_RESOURCE;
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_TIME)
+ value->year= value->month= value->day = 0;
+ DBUG_ASSERT(value->year <= 9999);
+ DBUG_ASSERT(value->month <= 12);
+ DBUG_ASSERT(value->day <= 31);
+ /*
+ 0<----year----><mn><day>
+ 012345678901234123412345
+ <123456><123456><123456>
+ */
+ buf[0]= (value->day |
+ ((value->month & 0x7) << 5));
+ buf[1]= ((value->month >> 3) | ((value->year & 0x7F) << 1));
+ buf[2]= (value->year >> 7);
+ str->length+= 3;
+ return ER_DYNCOL_OK;
+}
+
+
+
+/**
+ Read date value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+my_bool dynamic_column_date_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ store_it_here->time_value.neg= store_it_here->time_value.second_part=
+ store_it_here->time_value.hour= store_it_here->time_value.minute=
+ store_it_here->time_value.second= 0;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ return dynamic_column_date_read_int(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading date part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 3)
+ goto err;
+ /*
+ 0<----year----><mn><day>
+ 12345678901234123412345
+ <123456><123456><123456>
+ */
+ store_it_here->time_value.day= (data[0] & 0x1f);
+ store_it_here->time_value.month= (((data[1] & 0x1) << 3) |
+ (data[0] >> 5));
+ store_it_here->time_value.year= ((((uint)data[2]) << 7) |
+ (data[1] >> 1));
+ if (store_it_here->time_value.day > 31 ||
+ store_it_here->time_value.month > 12 ||
+ store_it_here->time_value.year > 9999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int data_add(DYNAMIC_COLUMN *str, DYNAMIC_COLUMN_VALUE *value)
+{
+ switch (value->type) {
+ case DYN_COL_INT:
+ return dynamic_column_sint_add(str, value->long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_add(str, value->ulong_value);
+ case DYN_COL_DOUBLE:
+ return dynamic_column_double_add(str, value->double_value);
+ case DYN_COL_STRING:
+ return dynamic_column_string_add(str, &value->string_value,
+ value->charset);
+ case DYN_COL_DECIMAL:
+ return dynamic_column_decimal_add(str, &value->decimal_value);
+ case DYN_COL_DATETIME:
+ /* date+time in bits: 14 + 4 + 5 + 5 + 6 + 6 40bits = 5 bytes */
+ return dynamic_column_date_time_add(str, &value->time_value);
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return dynamic_column_date_add(str, &value->time_value);
+ case DYN_COL_TIME:
+ /* time in bits: 5 + 6 + 6 = 17bits ~= 3bytes*/
+ return dynamic_column_time_add(str, &value->time_value);
+ default:
+ DBUG_ASSERT(0);
+ return ER_DYNCOL_DATA;
+ }
+}
+
+
+/**
+ Calculate length of offset field for given data length
+
+ @param data_length Length of the data segment
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_offset_bytes(size_t data_length)
+{
+ if (data_length < 0x1f) // all 1 value is reserved
+ return 1;
+ if (data_length < 0x1fff) // all 1 value is reserved
+ return 2;
+ if (data_length < 0x1fffff) // all 1 value is reserved
+ return 3;
+ if (data_length < 0x1fffffff) // all 1 value is reserved
+ return 4;
+ return 5;
+}
+
+/**
+ Store offset and type information in the given place
+
+ @param place Beginning of the index entry
+ @param offset_size Size of offset field in bytes
+ @param type Type to be written
+ @param offset Offset to be written
+*/
+
+void type_and_offset_store(uchar *place, size_t offset_size,
+ DYNAMIC_COLUMN_TYPE type,
+ size_t offset)
+{
+ ulong val = (((ulong) offset) << 3) | (type - 1);;
+ place+= COLUMN_NUMBER_SIZE;
+ DBUG_ASSERT(type != DYN_COL_NULL);
+ DBUG_ASSERT(((type - 1) & (~7)) == 0); // fit in 3 bits
+ switch (offset_size) {
+ case 1:
+ DBUG_ASSERT(offset < 0x1f); // all 1 value is reserved
+ place[0]= (uchar)val;
+ break;
+ case 2:
+ DBUG_ASSERT(offset < 0x1fff); // all 1 value is reserved
+ int2store(place, val);
+ break;
+ case 3:
+ DBUG_ASSERT(offset < 0x1fffff); // all 1 value is reserved
+ int3store(place, val);
+ break;
+ case 4:
+ DBUG_ASSERT(offset < 0x1fffffff); // all 1 value is reserved
+ int4store(place, val);
+ break;
+ default:
+ DBUG_ASSERT(0); // impossible
+ }
+}
+
+
+/**
+ Read offset and type information from index entry
+
+ @param type Where to put type info
+ @param offset Where to put offset info
+ @param place Beginning of the index entry
+ @param offset_size Size of offset field in bytes
+*/
+
+void type_and_offset_read(DYNAMIC_COLUMN_TYPE *type,
+ size_t *offset,
+ uchar *place, size_t offset_size)
+{
+ ulong val;
+ place+= COLUMN_NUMBER_SIZE; // skip column number
+ switch (offset_size) {
+ case 1:
+ val= (ulong)place[0];
+ break;
+ case 2:
+ val= uint2korr(place);
+ break;
+ case 3:
+ val= uint3korr(place);
+ break;
+ case 4:
+ val= uint4korr(place);
+ break;
+ default:
+ DBUG_ASSERT(0); // impossible
+ }
+ *type= (val & 0x7) + 1;
+ *offset= val >> 3;
+}
+
+/**
+ Comparator function for references on column numbers for qsort
+*/
+
+int column_sort(const void *a, const void *b)
+{
+ return **((uint **)a) - **((uint **)b);
+}
+
+/**
+ Write information to the fixed header
+
+ @param str String where to write the header
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of columns
+*/
+
+static void set_fixed_header(DYNAMIC_COLUMN *str,
+ uint offset_size,
+ uint column_count)
+{
+ DBUG_ASSERT(column_count <= 0xffff);
+ DBUG_ASSERT(offset_size <= 4);
+ str->str[0]= ((str->str[0] & ~DYNCOL_FLG_OFFSET) |
+ (offset_size - 1)); // size of offset
+ int2store(str->str + 1, column_count); // columns number
+ DBUG_ASSERT((str->str[0] & (~DYNCOL_FLG_KNOWN)) == 0);
+}
+
+
+/*
+ Read offset size (O) and column count (C) from string (S)
+*/
+
+#define read_fixed_header(S,O,C) do { \
+ (O)= ((S)->str[0] & DYNCOL_FLG_OFFSET) + 1; \
+ (C)= uint2korr((S)->str + 1); \
+}while(0);
+
+
+/*
+ Calculete entry size (E) and header size (H) by offset size (O) and column
+ count (C).
+*/
+
+#define calc_param(E,H,O,C) do { \
+ (E)= (O) + COLUMN_NUMBER_SIZE; \
+ (H)= (E) * (C); \
+}while(0);
+
+
+/**
+ Adds columns into the empty string
+
+ @param str String where to write the data
+ @param header_size Size of the header without fixed part
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of columns in the arrays
+ @parem non_null_count Number of non-null columns in the arrays
+ @param data_size Size of the data segment
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+ @param new_str True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_new_column_add(DYNAMIC_COLUMN *str,
+ size_t header_size,
+ size_t offset_size,
+ uint column_count,
+ uint non_null_count,
+ size_t data_size,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str)
+{
+ uchar *header_end;
+ uint **columns_order;
+ uint i;
+ uint entry_size= COLUMN_NUMBER_SIZE + offset_size;
+ int err= ER_DYNCOL_RESOURCE;
+ if (!(columns_order= malloc(sizeof(uint*)*column_count)))
+ return ER_DYNCOL_RESOURCE;
+ if (new_str)
+ {
+ if (dynamic_column_init_str(str,
+ data_size + header_size + DYNCOL_SYZERESERVE))
+ goto err;
+ }
+ else
+ {
+ str->length= 0;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ if (dynstr_realloc(str, data_size + header_size + DYNCOL_SYZERESERVE))
+ goto err;
+ }
+
+ /* sort columns for the header */
+ for (i= 0; i < column_count; i++)
+ columns_order[i]= column_numbers + i;
+ qsort(columns_order, (size_t)column_count, sizeof(uint*), &column_sort);
+ /* check numbers */
+ for (i= 0; i < column_count - 1; i++)
+ {
+ if (columns_order[i][0] == columns_order[i + 1][0])
+ {
+ err= ER_DYNCOL_DATA;
+ goto err;
+ }
+ }
+
+ DBUG_ASSERT(str->length == FIXED_HEADER_SIZE);
+ set_fixed_header(str, offset_size, non_null_count);
+ DBUG_ASSERT(str->max_length > str->length + header_size);
+ str->length+= header_size; // reserve place for header
+ header_end= (uchar *)str->str + FIXED_HEADER_SIZE;
+ for (i= 0; i < column_count; i++)
+ {
+ uint ord= columns_order[i] - column_numbers;
+ if (values[ord].type != DYN_COL_NULL)
+ {
+ int2store(header_end, column_numbers[ord]);
+ type_and_offset_store(header_end, offset_size,
+ values[ord].type,
+ str->length - header_size - FIXED_HEADER_SIZE);
+ if ((err= data_add(str, values + ord)))
+ goto err;
+ header_end+= entry_size;
+ }
+ }
+ err= ER_DYNCOL_OK;
+err:
+ free(columns_order);
+ return err;
+}
+
+/**
+ Create packed string which contains given columns (internal)
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+ @param new_str True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create_many_int(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str)
+{
+ size_t data_size= 0;
+ size_t header_size, offset_size;
+ uint i;
+ int not_null_column_count= column_count;
+ if (new_str)
+ bzero(str, sizeof(DYNAMIC_COLUMN)); // to make dynstr_free() working;
+ for (i= 0; i < column_count; i++)
+ {
+ data_size+= dynamic_column_value_len(values + i);
+ if (values[i].type == DYN_COL_NULL)
+ not_null_column_count--;
+ }
+
+ if ((offset_size= dynamic_column_offset_bytes(data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+
+ /* header entry is column number + offset&type */
+ header_size= not_null_column_count * (offset_size + 2);
+
+ return dynamic_new_column_add(str,
+ header_size, offset_size,
+ column_count,
+ not_null_column_count,
+ data_size,
+ column_numbers, values,
+ new_str);
+}
+
+
+/**
+ Create packed string which contains given columns
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return dynamic_column_create_many_int(str, column_count,
+ column_numbers, values,
+ TRUE);
+}
+
+
+/**
+ Create packed string which contains given column
+
+ @param str String where to write the data
+ @param column_number Column number
+ @param value The columns value
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return dynamic_column_create_many(str, 1, &column_nr, value);
+}
+
+
+/**
+ Calculate length of data between given two header entries
+
+ @param entry Pointer to the first entry
+ @param entry_next Pointer to the last entry
+ @param header_end Pointer to the header end
+ @param offset_size Size of offset field in bytes
+ @param last_offset Size of the data segment
+
+ @return number of bytes
+*/
+
+size_t get_length_interval (uchar *entry, uchar *entry_next,
+ uchar *header_end, size_t offset_size,
+ size_t last_offset)
+{
+ size_t offset, offset_next;
+ DYNAMIC_COLUMN_TYPE type, type_next;
+ DBUG_ASSERT(entry < entry_next);
+ type_and_offset_read(&type, &offset, entry, offset_size);
+ if (entry_next >= header_end)
+ return last_offset - offset;
+ type_and_offset_read(&type_next, &offset_next, entry_next, offset_size);
+ return offset_next - offset;
+}
+
+/*
+ Calculate length of data of one column
+
+
+ @param entry Pointer to the first entry
+ @param header_end Pointer to the header end
+ @param offset_size Size of offset field in bytes
+ @param last_offset Size of the data segment
+
+ @return number of bytes
+*/
+
+size_t get_length(uchar *entry, uchar *header_end,
+ size_t offset_size,
+ size_t last_offset)
+{
+ return get_length_interval(entry,
+ entry + offset_size + COLUMN_NUMBER_SIZE,
+ header_end, offset_size, last_offset);
+}
+
+
+/**
+ Comparator function for references to header entries for qsort
+*/
+
+int header_compar(const void *a, const void *b)
+{
+ uint va= uint2korr((uchar*)a), vb= uint2korr((uchar*)b);
+ return (va > vb ? 1 : (va < vb ? -1 : 0));
+}
+
+
+/**
+ Find column and fill information about it
+
+ @param type Returns type of the column
+ @param data Returns a pointer to the data
+ @param length Returns length of the data
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of column in the packed string
+ @param data_end Pointer to the data end
+ @param num Number of the column we want to fetch
+ @param entry_pos NULL or place where to put reference to the entry
+*/
+
+void find_column(DYNAMIC_COLUMN_TYPE *type, uchar **data, size_t *length,
+ uchar *header, size_t offset_size, uint column_count,
+ uchar *data_end, uint num, uchar **entry_pos)
+{
+ uchar *entry;
+ size_t offset;
+ size_t header_size, entry_size;
+ uchar key[2+4];
+ if (!entry_pos)
+ entry_pos= &entry;
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ int2store(key, num);
+ entry= bsearch(key, header, (size_t)column_count, entry_size,
+ &header_compar);
+ if (!entry)
+ {
+ *type= DYN_COL_NULL;
+ *entry_pos= NULL;
+ return;
+ }
+ type_and_offset_read(type, &offset, entry, offset_size);
+ *data= header + header_size + offset;
+ DBUG_ASSERT(*data < data_end);
+ *length= get_length(entry, header + header_size, offset_size,
+ data_end - (header + header_size));
+ *entry_pos= entry;
+ return;
+}
+
+
+/**
+ Make simple check of the packed string format
+
+ @param str The string to check
+
+ @retval FALSE OK
+ @retval TRUE error
+*/
+
+static my_bool dynamic_column_str_check(DYNAMIC_COLUMN *str)
+{
+ if (str == NULL)
+ return TRUE;
+ if (str->length == 0)
+ return FALSE;
+ return ((str->length < FIXED_HEADER_SIZE) ||
+ (str->str[0] & (~DYNCOL_FLG_KNOWN)));
+}
+
+/**
+ Get dynamic column value
+
+ @param str The packed string to extract the column
+ @param column_nr Number of column to fetch
+ @param store_it_here Where to store the extracted value
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_get(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ uchar *data;
+ size_t offset_size, length;
+ uint column_count;
+ int rc= ER_DYNCOL_FORMAT;
+
+ if (dynamic_column_str_check(str))
+ goto err;
+
+ if (str->length == 0)
+ goto null;
+
+ read_fixed_header(str, offset_size, column_count);
+ if (column_count == 0)
+ goto null;
+
+ find_column(&store_it_here->type, &data, &length,
+ (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, NULL);
+
+ switch (store_it_here->type)
+ {
+ case DYN_COL_INT:
+ rc= dynamic_column_sint_read(store_it_here, data, length);
+ break;
+ case DYN_COL_UINT:
+ rc= dynamic_column_uint_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DOUBLE:
+ rc= dynamic_column_double_read(store_it_here, data, length);
+ break;
+ case DYN_COL_STRING:
+ rc= dynamic_column_string_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DECIMAL:
+ rc= dynamic_column_decimal_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DATETIME:
+ rc= dynamic_column_date_time_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DATE:
+ rc= dynamic_column_date_read(store_it_here, data, length);
+ break;
+ case DYN_COL_TIME:
+ rc= dynamic_column_time_read(store_it_here, data, length);
+ break;
+ case DYN_COL_NULL:
+ rc= ER_DYNCOL_OK;
+ break;
+ default:
+ goto err;
+ }
+ return rc;
+
+null:
+ rc= ER_DYNCOL_OK;
+err:
+ store_it_here->type= DYN_COL_NULL;
+ return rc;
+}
+
+/**
+ Delete column with given number from the packed string
+
+ @param str The packed string to delete the column
+ @param column_nr Number of column to delete
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_delete(DYNAMIC_COLUMN *str, uint column_nr)
+{
+ uchar *data, *header_entry, *read, *write;
+ size_t offset_size, new_offset_size, length, entry_size, new_entry_size,
+ header_size, new_header_size, data_size, new_data_size,
+ deleted_entry_offset;
+ uint column_count, i;
+ DYNAMIC_COLUMN_TYPE type;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ return ER_DYNCOL_OK; // no columns
+
+ read_fixed_header(str, offset_size, column_count);
+
+ if (column_count == 0)
+ return ER_DYNCOL_OK; // no columns
+
+ find_column(&type, &data, &length, (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, &header_entry);
+
+ if (type == DYN_COL_NULL)
+ return ER_DYNCOL_OK; // no such column
+
+ if (column_count == 1)
+ {
+ /* delete the only column */
+ str->length= FIXED_HEADER_SIZE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ return ER_DYNCOL_OK;
+ }
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ entry_size= 2 + offset_size;
+ header_size= entry_size * column_count;
+ data_size= str->length - FIXED_HEADER_SIZE - header_size;
+
+ new_data_size= data_size - length;
+ if ((new_offset_size= dynamic_column_offset_bytes(new_data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+ DBUG_ASSERT(new_offset_size <= offset_size);
+ calc_param(new_entry_size, new_header_size,
+ new_offset_size, column_count - 1);
+
+ deleted_entry_offset= (data - (uchar*)str->str) -
+ header_size - FIXED_HEADER_SIZE;
+
+
+ /* rewrite header*/
+ set_fixed_header(str, new_offset_size, column_count - 1);
+ for (i= 0, write= read= (uchar *)str->str + FIXED_HEADER_SIZE;
+ i < column_count;
+ i++, read+= entry_size, write+= new_entry_size)
+ {
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+ if (read == header_entry)
+ {
+#ifndef DBUG_OFF
+ nm= uint2korr(read);
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+ DBUG_ASSERT(nm == column_nr);
+ DBUG_ASSERT(offs == deleted_entry_offset);
+#endif
+ write-= new_entry_size; // do not move writer
+ continue; // skip removed field
+ }
+
+ nm= uint2korr(read),
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+
+ if (offs > deleted_entry_offset)
+ offs-= length; // data stored after removed data
+
+ int2store(write, nm);
+ type_and_offset_store(write, new_offset_size, tp, offs);
+ }
+
+ /* move data */
+ {
+ size_t first_chunk_len= (data - (uchar *)str->str) -
+ FIXED_HEADER_SIZE - header_size;
+ size_t second_chunk_len= new_data_size - first_chunk_len;
+ if (first_chunk_len)
+ memmove(str->str + FIXED_HEADER_SIZE + new_header_size,
+ str->str + FIXED_HEADER_SIZE + header_size,
+ first_chunk_len);
+ if (second_chunk_len)
+ memmove(str->str +
+ FIXED_HEADER_SIZE + new_header_size + first_chunk_len,
+ str->str +
+ FIXED_HEADER_SIZE + header_size + first_chunk_len + length,
+ second_chunk_len);
+ }
+
+ /* fix str length */
+ DBUG_ASSERT(str->length >=
+ FIXED_HEADER_SIZE + new_header_size + new_data_size);
+ str->length= FIXED_HEADER_SIZE + new_header_size + new_data_size;
+
+ return FALSE;
+}
+
+
+/**
+ Check existence of the column in the packed string
+
+ @param str The packed string to check the column
+ @param column_nr Number of column to check
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_exists(DYNAMIC_COLUMN *str, uint column_nr)
+{
+ uchar *data;
+ size_t offset_size, length;
+ uint column_count;
+ DYNAMIC_COLUMN_TYPE type;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ return ER_DYNCOL_NO; // no columns
+
+ read_fixed_header(str, offset_size, column_count);
+
+ if (column_count == 0)
+ return ER_DYNCOL_NO; // no columns
+
+ find_column(&type, &data, &length, (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, NULL);
+
+ return (type != DYN_COL_NULL ? ER_DYNCOL_YES : ER_DYNCOL_NO);
+}
+
+/**
+ List not-null columns in the packed string
+
+ @param str The packed string
+ @param array_of_uint Where to put reference on created array
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_list(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_uint)
+{
+ uchar *read;
+ size_t offset_size, entry_size;
+ uint column_count, i;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ {
+ if (init_dynamic_array(array_of_uint, sizeof(uint),
+ 0, 10 CALLER_INFO))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK; // no columns
+ }
+
+
+ read_fixed_header(str, offset_size, column_count);
+ entry_size= COLUMN_NUMBER_SIZE + offset_size;
+
+ if (init_dynamic_array(array_of_uint, sizeof(uint),
+ column_count, 10 CALLER_INFO))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0, read= (uchar *)str->str + FIXED_HEADER_SIZE;
+ i < column_count;
+ i++, read+= entry_size)
+ {
+ uint nm= uint2korr(read);
+ if (insert_dynamic(array_of_uint, (uchar *)&nm))
+ {
+ delete_dynamic(array_of_uint);
+ return ER_DYNCOL_RESOURCE;
+ }
+ }
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Find the place of the column in the header or place where it should be put
+
+ @param num Number of the column
+ @param header Pointer to the header
+ @param entry_size Size of a header entry
+ @param column_count Number of columns in the packed string
+ @param entry Return pointer to the entry or next entry
+
+ @retval TRUE found
+ @retval FALSE pointer set to the next row
+*/
+
+my_bool find_place(uint num,
+ uchar *header, size_t entry_size, uint column_count,
+ uchar **entry)
+{
+ uint mid, start, end, val;
+ int flag;
+
+ start= 0;
+ end= column_count -1;
+ mid= 1;
+ while (start != end)
+ {
+ uint val;
+ mid= (start + end) / 2;
+ val= uint2korr(header + mid * entry_size);
+ if ((flag= CMP_NUM(num, val)) <= 0)
+ end= mid;
+ else
+ start= mid + 1;
+ }
+ if (start != mid)
+ {
+ val= uint2korr(header + start * entry_size);
+ flag= CMP_NUM(num, val);
+ }
+ *entry= header + start * entry_size;
+ if (flag > 0)
+ *entry+= entry_size; /* Point at next bigger key */
+ return flag == 0;
+}
+
+/*
+ Description of plan of adding/removing/updating a packed string
+*/
+
+typedef enum {PLAN_REPLACE, PLAN_ADD, PLAN_DELETE, PLAN_NOP} PLAN_ACT;
+
+struct st_plan {
+ DYNAMIC_COLUMN_VALUE *val;
+ uint *num;
+ uchar *place;
+ size_t length;
+ int hdelta, ddelta;
+ PLAN_ACT act;
+};
+typedef struct st_plan PLAN;
+
+
+int plan_sort(const void *a, const void *b)
+{
+ return ((PLAN *)a)->num[0] - ((PLAN *)b)->num[0];
+}
+
+#define DELTA_CHECK(S, D, C) \
+ if ((S) == 0) \
+ (S)= (D); \
+ else if (((S) > 0 && (D) < 0) || \
+ ((S) < 0 && (D) > 0)) \
+ { \
+ (C)= TRUE; \
+ break; \
+ } \
+
+/**
+ Update the packed string with the given columns
+
+ @param str String where to write the data
+ @param add_column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ PLAN *plan;
+ uchar *header_end;
+ long data_delta= 0;
+ uint i, j, k;
+ uint new_column_count, column_count,
+ not_null= add_column_count;
+ int rc;
+ int header_delta= 0;
+ int header_delta_sign, data_delta_sign;
+ size_t offset_size, entry_size, header_size, data_size;
+ size_t new_offset_size, new_entry_size, new_header_size, new_data_size;
+ size_t max_offset;
+ my_bool copy;
+
+
+ if (add_column_count == 0)
+ return ER_DYNCOL_OK;
+
+ if (!(plan= malloc(sizeof(PLAN) * (add_column_count + 1))))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0; i < add_column_count; i++)
+ {
+ plan[i].val= values + i;
+ plan[i].num= column_numbers + i;
+ if (values[i].type == DYN_COL_NULL)
+ not_null--;
+ }
+ qsort(plan, (size_t)add_column_count, sizeof(PLAN), &plan_sort);
+
+ if (str->length == 0)
+ {
+ /* There is no columns so we just add them */
+ if (not_null == 0)
+ {
+ if (str->str)
+ {
+ if (dynstr_realloc(str, FIXED_HEADER_SIZE + DYNCOL_SYZERESERVE))
+ return ER_DYNCOL_RESOURCE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ }
+ else
+ {
+ if (dynamic_column_init_str(str,
+ FIXED_HEADER_SIZE + DYNCOL_SYZERESERVE))
+ return ER_DYNCOL_RESOURCE;
+ }
+ return ER_DYNCOL_OK;
+ }
+ return dynamic_column_create_many_int(str, add_column_count,
+ column_numbers, values,
+ str->str == NULL);
+ }
+
+ read_fixed_header(str, offset_size, column_count);
+ new_column_count= column_count;
+
+ if (column_count == 0)
+ {
+ /* There is no columns so we just add them */
+ if (not_null == 0)
+ return ER_DYNCOL_OK;
+ return dynamic_column_create_many_int(str, add_column_count,
+ column_numbers, values,
+ FALSE);
+ }
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ max_offset= str->length - (FIXED_HEADER_SIZE + header_size);
+ header_end= (uchar *)str->str + FIXED_HEADER_SIZE + header_size;
+
+ /* check numbers */
+ for (i= 0; i < add_column_count; i++)
+ {
+ uchar *entry;
+ if (i < add_column_count - 1 && plan[i].num[0] == plan[i + 1].num[0])
+ {
+ rc= ER_DYNCOL_DATA;
+ goto err;
+ }
+
+ if (find_place(plan[i].num[0],
+ (uchar *)str->str + FIXED_HEADER_SIZE,
+ entry_size, column_count, &entry))
+ {
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ size_t entry_data_size;
+ new_column_count--;
+ /* replace the value */
+ plan[i].act= PLAN_DELETE;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta--;
+ /* get data delta in bytes */
+ entry_data_size= get_length(entry, header_end,
+ offset_size, max_offset);
+ plan[i].length= 0;
+ plan[i].ddelta= data_delta;
+ data_delta-= entry_data_size;
+ }
+ else
+ {
+ size_t entry_data_size;
+ /* replace the value */
+ plan[i].act= PLAN_REPLACE;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta;
+ /* get data delta in bytes */
+ entry_data_size= get_length(entry, header_end,
+ offset_size, max_offset);
+ plan[i].length= dynamic_column_value_len(plan[i].val);
+ plan[i].ddelta= data_delta;
+ data_delta+= plan[i].length - entry_data_size;
+ }
+ }
+ else
+ {
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ plan[i].act= PLAN_NOP;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta;
+ /* get data delta in bytes */
+ plan[i].length= 0;
+ plan[i].ddelta= data_delta;
+ }
+ else
+ {
+ new_column_count++;
+ /* replace the value */
+ plan[i].act= PLAN_ADD;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta++;
+ /* get data delta in bytes */
+ plan[i].length= dynamic_column_value_len(plan[i].val);
+ plan[i].ddelta= data_delta;
+ data_delta+= plan[i].length;
+ }
+ }
+ plan[i].place= entry;
+ }
+ plan[add_column_count].hdelta= header_delta;
+ plan[add_column_count].ddelta= data_delta;
+ /*
+ check if it is only "incising" or only "decreasing" plan for (header
+ and data separately).
+ */
+ data_size= str->length - header_size - FIXED_HEADER_SIZE;
+ new_data_size= data_size + data_delta;
+ if ((new_offset_size= dynamic_column_offset_bytes(new_data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+ //if (new_offset_size != offset_size) rewrite_header= TRUE;
+ header_delta_sign= new_offset_size - offset_size;
+ data_delta_sign= 0;
+ copy= FALSE;
+ for (i= 0; i < add_column_count; i++)
+ {
+ DELTA_CHECK(header_delta_sign, plan[i].hdelta, copy);
+ DELTA_CHECK(data_delta_sign, plan[i].ddelta, copy);
+ }
+
+ calc_param(new_entry_size, new_header_size,
+ new_offset_size, new_column_count);
+
+ //if (copy)
+ {
+ DYNAMIC_COLUMN tmp;
+ uchar *header_base= (uchar *)str->str + FIXED_HEADER_SIZE,
+ *write;
+ if (dynamic_column_init_str(&tmp,
+ (FIXED_HEADER_SIZE + new_header_size +
+ new_data_size + DYNCOL_SYZERESERVE)))
+ {
+ rc= ER_DYNCOL_RESOURCE;
+ goto err;
+ }
+ write= (uchar *)tmp.str + FIXED_HEADER_SIZE;
+ tmp.length= FIXED_HEADER_SIZE + new_header_size;
+ set_fixed_header(&tmp, new_offset_size, new_column_count);
+ data_delta= 0;
+ /* Copy data to the new string */
+ for (i= 0, j= 0; i < add_column_count || j < column_count; i++)
+ {
+ size_t first_offset;
+ uint start= j, end;
+ /* skip NOP */
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++;
+ /* old data portion */
+ while (j < column_count &&
+ (i >= add_column_count ||
+ header_base + j * entry_size < plan[i].place))
+ j++;
+ end= j;
+ if (plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE)
+ j++;
+ for (k= start; k < end; k++)
+ {
+ uchar *read= header_base + k * entry_size;
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+ nm= uint2korr(read);
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+ if (k == start)
+ first_offset= offs;
+ offs+= plan[i].ddelta;
+ int2store(write, nm);
+ type_and_offset_store(write, new_offset_size, tp, offs);
+ write+= new_entry_size;
+ }
+ if (start < end)
+ {
+ size_t data_size=
+ get_length_interval(header_base + start * entry_size,
+ header_base + end * entry_size,
+ header_end, offset_size, max_offset);
+ memcpy(tmp.str + tmp.length, (char *)header_end + first_offset,
+ data_size);
+ tmp.length+= data_size;
+ }
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if(plan[i].act == PLAN_ADD ||
+ plan[i].act == PLAN_REPLACE)
+ {
+ int2store(write, plan[i].num[0]);
+ type_and_offset_store(write, new_offset_size,
+ plan[i].val[0].type,
+ tmp.length -
+ (FIXED_HEADER_SIZE + new_header_size));
+ write+= new_entry_size;
+ data_add(&tmp, plan[i].val);
+ }
+ data_delta= plan[i].ddelta;
+ }
+ }
+ dynamic_column_column_free(str);
+ *str= tmp;
+ }
+
+ rc= ER_DYNCOL_OK;
+err:
+ free(plan);
+ return rc;
+}
+
+
+/**
+ Update the packed string with the given column
+
+ @param str String where to write the data
+ @param column_number Array of columns number
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+
+int dynamic_column_update(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return dynamic_column_update_many(str, 1, &column_nr, value);
+}
=== modified file 'sql/item.h'
--- sql/item.h 2011-04-27 04:11:06 +0000
+++ sql/item.h 2011-04-29 09:52:28 +0000
@@ -18,6 +18,10 @@
#pragma interface /* gcc class implementation */
#endif
+C_MODE_START
+#include <ma_dyncol.h>
+C_MODE_END
+
inline
bool trace_unsupported_func(const char *where, const char *processor_name)
{
@@ -471,6 +475,17 @@
};
+struct st_dyncall_create_def
+{
+ Item *num, *value;
+ CHARSET_INFO *cs;
+ uint len, frac;
+ DYNAMIC_COLUMN_TYPE type;
+};
+
+typedef struct st_dyncall_create_def DYNCALL_CREATE_DEF;
+
+
typedef bool (Item::*Item_processor) (uchar *arg);
/*
Analyzer function
@@ -804,7 +819,11 @@
{ return val_decimal(val); }
virtual bool val_bool_result() { return val_bool(); }
virtual bool is_null_result() { return is_null(); }
-
+ /*
+ Returns 1 if result type and collation for val_str() can change between
+ calls
+ */
+ virtual bool dynamic_result() { return 0; }
/*
Bitmap of tables used by item
(note: if you need to check dependencies on individual columns, check out
=== modified file 'sql/item_cmpfunc.cc'
--- sql/item_cmpfunc.cc 2011-04-27 04:11:06 +0000
+++ sql/item_cmpfunc.cc 2011-04-29 09:52:28 +0000
@@ -6074,3 +6074,34 @@
DBUG_ASSERT(0);
return NULL;
}
+
+
+longlong Item_func_dyncol_exists::val_int()
+{
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+ DYNAMIC_COLUMN col;
+ String *str;
+ uint num;
+ int rc;
+
+ num= args[1]->val_int();
+ str= args[0]->val_str(&tmp);
+ if (args[0]->null_value || args[1]->null_value)
+ goto null;
+ col.length= str->length();
+ /* We do not change the string, so could do this trick */
+ col.str= (char *)str->ptr();
+ rc= dynamic_column_exists(&col, num);
+ if (rc < 0)
+ {
+ dynamic_column_error_message(rc);
+ goto null;
+ }
+ null_value= FALSE;
+ return rc == ER_DYNCOL_YES;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
=== modified file 'sql/item_cmpfunc.h'
--- sql/item_cmpfunc.h 2011-04-27 04:11:06 +0000
+++ sql/item_cmpfunc.h 2011-04-29 09:52:28 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+/*dyncol_exists Copyright (c) 2000, 2010, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1869,3 +1869,11 @@
bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
const char *warn_name, MYSQL_TIME *l_time);
+
+class Item_func_dyncol_exists :public Item_bool_func
+{
+public:
+ Item_func_dyncol_exists(Item *str, Item *num) :Item_bool_func(str, num) {}
+ longlong val_int();
+ const char *func_name() const { return "column_exists"; }
+};
=== modified file 'sql/item_create.cc'
--- sql/item_create.cc 2011-02-20 16:51:43 +0000
+++ sql/item_create.cc 2011-04-29 09:52:28 +0000
@@ -27,6 +27,50 @@
/*
=============================================================================
+ HELPER FUNCTIONS
+=============================================================================
+*/
+
+/*
+ Get precision and scale for a declaration
+
+ return
+ 0 ok
+ 1 error
+*/
+
+bool get_length_and_scale(ulonglong length, ulonglong decimals,
+ ulong *out_length, uint *out_decimals,
+ uint max_precision, uint max_scale,
+ const char *name)
+{
+ if (length > (ulonglong) max_precision)
+ {
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), (int) length, name,
+ max_precision);
+ return 1;
+ }
+ if (decimals > (ulonglong) max_scale)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), (int) decimals, name,
+ DECIMAL_MAX_SCALE);
+ return 1;
+ }
+
+ *out_length= (ulong) length;
+ *out_decimals= (uint) decimals;
+ my_decimal_trim(out_length, out_decimals);
+
+ if (*out_length < *out_decimals)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+=============================================================================
LOCAL DECLARATIONS
=============================================================================
*/
@@ -5054,6 +5098,17 @@
CHARSET_INFO *cs)
{
Item *UNINIT_VAR(res);
+ ulonglong length= 0, decimals= 0;
+ int error;
+
+ /*
+ We don't have to check for error here as sql_yacc.yy has guaranteed
+ that the values are in range of ulonglong
+ */
+ if (c_len)
+ length= (ulonglong) my_strtoll10(c_len, NULL, &error);
+ if (c_dec)
+ decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
switch (cast_type) {
case ITEM_CAST_BINARY:
@@ -5076,72 +5131,45 @@
break;
case ITEM_CAST_DECIMAL:
{
- ulong len= 0;
- uint dec= 0;
-
- if (c_len)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if (errno != 0)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name,
- DECIMAL_MAX_PRECISION);
- return NULL;
- }
- len= decoded_size;
- }
-
- if (c_dec)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_dec, NULL, 10);
- if ((errno != 0) || (decoded_size > UINT_MAX))
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name,
- DECIMAL_MAX_SCALE);
- return NULL;
- }
- dec= decoded_size;
- }
- my_decimal_trim(&len, &dec);
- if (len < dec)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
- return 0;
- }
- if (len > DECIMAL_MAX_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), len, a->name,
- DECIMAL_MAX_PRECISION);
- return 0;
- }
- if (dec > DECIMAL_MAX_SCALE)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), dec, a->name,
- DECIMAL_MAX_SCALE);
- return 0;
- }
+ ulong len;
+ uint dec;
+ if (get_length_and_scale(length, decimals, &len, &dec,
+ DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE,
+ a->name))
+ return NULL;
res= new (thd->mem_root) Item_decimal_typecast(a, len, dec);
break;
}
+ case ITEM_CAST_DOUBLE:
+ {
+ ulong len;
+ uint dec;
+
+ if (!c_len)
+ {
+ length= DBL_DIG+7;
+ decimals= NOT_FIXED_DEC;
+ }
+ else if (get_length_and_scale(length, decimals, &len, &dec,
+ DECIMAL_MAX_PRECISION, NOT_FIXED_DEC-1,
+ a->name))
+ return NULL;
+ res= new (thd->mem_root) Item_double_typecast(a, length, decimals);
+ break;
+ }
case ITEM_CAST_CHAR:
{
int len= -1;
CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
if (c_len)
{
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if ((errno != 0) || (decoded_size > MAX_FIELD_BLOBLENGTH))
+ if (length > MAX_FIELD_BLOBLENGTH)
{
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH);
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char",
+ MAX_FIELD_BLOBLENGTH);
return NULL;
}
- len= (int) decoded_size;
+ len= (int) length;
}
res= new (thd->mem_root) Item_char_typecast(a, len, real_cs);
break;
@@ -5155,3 +5183,99 @@
}
return res;
}
+
+
+static List<Item> *create_func_dyncol_prepare(THD *thd,
+ DYNCALL_CREATE_DEF **dfs,
+ List<DYNCALL_CREATE_DEF> &list)
+{
+ List_iterator_fast<DYNCALL_CREATE_DEF> li(list);
+ List<Item> *args= new (thd->mem_root) List<Item>;
+
+ *dfs=
+ (DYNCALL_CREATE_DEF *)alloc_root(thd->mem_root,
+ sizeof(DYNCALL_CREATE_DEF) *
+ list.elements);
+ DYNCALL_CREATE_DEF *def;
+ uint i= 0;
+
+ if (!args || !dfs)
+ return NULL;
+
+ while ((def= li++))
+ {
+ dfs[0][i++]= *def;
+ args->push_back(def->num);
+ args->push_back(def->value);
+ }
+ return args;
+}
+
+Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list)
+{
+ List<Item> *args;
+ DYNCALL_CREATE_DEF *dfs;
+ if (!(args= create_func_dyncol_prepare(thd, &dfs, list)))
+ return NULL;
+
+ return new (thd->mem_root) Item_func_dyncol_create(*args, dfs);
+}
+
+
+Item *create_func_dyncol_add(THD *thd, Item *str,
+ List<DYNCALL_CREATE_DEF> &list)
+{
+ List<Item> *args;
+ DYNCALL_CREATE_DEF *dfs;
+
+ if (!(args= create_func_dyncol_prepare(thd, &dfs, list)))
+ return NULL;
+
+ args->push_back(str);
+
+ return new (thd->mem_root) Item_func_dyncol_add(*args, dfs);
+}
+
+
+
+Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
+{
+ DYNCALL_CREATE_DEF *dfs;
+ List<Item> *args= new (thd->mem_root) List<Item>;
+ List_iterator_fast<Item> it(nums);
+ Item *num;
+ uint i;
+
+ dfs=
+ (DYNCALL_CREATE_DEF *)alloc_root(thd->mem_root,
+ sizeof(DYNCALL_CREATE_DEF) *
+ nums.elements);
+ if (!args || !dfs)
+ return NULL;
+
+ for (i= 0; (num= it++); i++)
+ {
+ dfs[i].num= num;
+ dfs[i].value= new Item_null();
+ dfs[i].type= DYN_COL_INT;
+ args->push_back(dfs[i].num);
+ args->push_back(dfs[i].value);
+ }
+
+ args->push_back(str);
+
+ return new (thd->mem_root) Item_func_dyncol_add(*args, dfs);
+}
+
+
+Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
+ Cast_target cast_type,
+ const char *c_len, const char *c_dec,
+ CHARSET_INFO *cs)
+{
+ Item *res;
+
+ if (!(res= new (thd->mem_root) Item_dyncol_get(str, num)))
+ return res; // Return NULL
+ return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);
+}
=== modified file 'sql/item_create.h'
--- sql/item_create.h 2011-02-20 16:51:43 +0000
+++ sql/item_create.h 2011-04-29 09:52:28 +0000
@@ -164,5 +164,15 @@
create_func_cast(THD *thd, Item *a, Cast_target cast_type,
const char *len, const char *dec,
CHARSET_INFO *cs);
+
+Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list);
+Item *create_func_dyncol_add(THD *thd, Item *str,
+ List<DYNCALL_CREATE_DEF> &list);
+Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums);
+Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
+ Cast_target cast_type,
+ const char *c_len, const char *c_dec,
+ CHARSET_INFO *cs);
+
#endif
=== modified file 'sql/item_func.cc'
--- sql/item_func.cc 2011-03-24 14:34:06 +0000
+++ sql/item_func.cc 2011-04-29 09:52:28 +0000
@@ -989,9 +989,24 @@
null_value= args[0]->null_value;
return value;
}
+ else if (args[0]->dynamic_result())
+ {
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 0; // Mark that we want to have a signed value
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag && value < 0)
+ goto err; // Warn about overflow
+ return value;
+ }
value= val_int_from_str(&error);
if (value < 0 && error == 0)
+ goto err;
+ return value;
+
+err:
+ if (value < 0 && error == 0)
{
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Cast to signed converted positive out-of-range integer to "
@@ -1024,19 +1039,36 @@
value= 0;
return value;
}
+ else if (args[0]->dynamic_result())
+ {
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 1; // Mark that we want to have an unsigned value
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
+ return value;
+ }
else if (args[0]->cast_to_int_type() != STRING_RESULT ||
args[0]->result_as_longlong())
{
value= args[0]->val_int();
null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
return value;
}
value= val_int_from_str(&error);
if (error < 0)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Cast to unsigned converted negative integer to it's "
- "positive complement");
+ goto err;
+
+ return value;
+
+err:
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to unsigned converted negative integer to it's "
+ "positive complement");
return value;
}
@@ -1134,6 +1166,51 @@
}
+double Item_double_typecast::val_real()
+{
+ int error;
+ double tmp= args[0]->val_real();
+ if ((null_value= args[0]->null_value))
+ return 0.0;
+
+ if ((error= truncate_double(&tmp, max_length, decimals, 0, DBL_MAX)))
+ {
+ push_warning_printf(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ ER(ER_WARN_DATA_OUT_OF_RANGE),
+ name, 1);
+ if (error < 0)
+ {
+ null_value= 1; // Illegal value
+ tmp= 0.0;
+ }
+ }
+ return tmp;
+}
+
+
+void Item_double_typecast::print(String *str, enum_query_type query_type)
+{
+ char len_buf[20*3 + 1];
+ char *end;
+
+ str->append(STRING_WITH_LEN("cast("));
+ args[0]->print(str, query_type);
+ str->append(STRING_WITH_LEN(" as double"));
+ if (decimals != NOT_FIXED_DEC)
+ {
+ str->append('(');
+ end= int10_to_str(max_length, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(',');
+ end= int10_to_str(decimals, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(')');
+ }
+ str->append(')');
+}
+
double Item_func_plus::real_op()
{
double value= args[0]->val_real() + args[1]->val_real();
=== modified file 'sql/item_func.h'
--- sql/item_func.h 2011-03-24 14:34:06 +0000
+++ sql/item_func.h 2011-04-29 09:52:28 +0000
@@ -470,12 +470,29 @@
my_decimal *val_decimal(my_decimal*);
enum Item_result result_type () const { return DECIMAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
- void fix_length_and_dec() {};
+ void fix_length_and_dec() {}
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
};
+class Item_double_typecast :public Item_real_func
+{
+public:
+ Item_double_typecast(Item *a, int len, int dec) :Item_real_func(a)
+ {
+ decimals= dec;
+ max_length= len;
+ }
+ double val_real();
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ void fix_length_and_dec() { maybe_null= 1; }
+ const char *func_name() const { return "double_typecast"; }
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+
class Item_func_additive_op :public Item_num_op
{
public:
@@ -1713,7 +1730,7 @@
{
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
- ITEM_CAST_DECIMAL
+ ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE
};
@@ -1877,4 +1894,3 @@
return trace_unsupported_by_check_vcol_func_processor(func_name());
}
};
-
=== modified file 'sql/item_strfunc.cc'
--- sql/item_strfunc.cc 2011-03-24 14:34:06 +0000
+++ sql/item_strfunc.cc 2011-04-29 09:52:28 +0000
@@ -3451,3 +3451,740 @@
return str;
}
+
+
+Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args,
+ DYNCALL_CREATE_DEF *dfs)
+ : Item_str_func(args), defs(dfs), vals(0), nums(0)
+{
+ DBUG_ASSERT((args.elements & 0x1) == 0); // even number of arguments
+}
+
+
+bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref)
+{
+ bool res= Item_func::fix_fields(thd, ref); // no need Item_str_func here
+ vals= (DYNAMIC_COLUMN_VALUE *) alloc_root(thd->mem_root,
+ sizeof(DYNAMIC_COLUMN_VALUE) *
+ (arg_count / 2));
+ nums= (uint *) alloc_root(thd->mem_root,
+ sizeof(uint) * (arg_count / 2));
+ return res || vals == 0 || nums == 0;
+}
+
+
+void Item_func_dyncol_create::fix_length_and_dec()
+{
+ maybe_null= TRUE;
+ collation.set(&my_charset_bin);
+ decimals= 0;
+}
+
+void Item_func_dyncol_create::prepare_arguments()
+{
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String *res, tmp(buff, sizeof(buff), &my_charset_bin);
+ uint column_count= (arg_count / 2);
+ uint i;
+ my_decimal dtmp, *dres;
+
+ /* get values */
+ for (i= 0; i < column_count; i++)
+ {
+ uint valpos= i * 2 + 1;
+ DYNAMIC_COLUMN_TYPE type= defs[i].type;
+ if (type == DYN_COL_NULL) // auto detect
+ {
+ switch (args[valpos]->field_type()) {
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ type= DYN_COL_DECIMAL;
+ break;
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_BIT:
+ type= DYN_COL_INT;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ type= DYN_COL_DOUBLE;
+ break;
+ case MYSQL_TYPE_NULL:
+ type= DYN_COL_NULL;
+ break;
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ type= DYN_COL_DATETIME;
+ break;
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_NEWDATE:
+ type= DYN_COL_DATE;
+ break;
+ case MYSQL_TYPE_TIME:
+ type= DYN_COL_TIME;
+ break;
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_GEOMETRY:
+ type= DYN_COL_STRING;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ type= DYN_COL_STRING;
+ }
+ }
+ nums[i]= args[i * 2]->val_int();
+ vals[i].type= type;
+ switch (type) {
+ case DYN_COL_NULL:
+ break;
+ case DYN_COL_INT:
+ vals[i].long_value= args[valpos]->val_int();
+ break;
+ case DYN_COL_UINT:
+ vals[i].ulong_value= args[valpos]->val_int();
+ break;
+ case DYN_COL_DOUBLE:
+ vals[i].double_value= args[valpos]->val_real();
+ break;
+ case DYN_COL_STRING:
+ res= args[valpos]->val_str(&tmp);
+ if (res)
+ {
+ vals[i].string_value.str= (char *)my_malloc(res->length(), MYF(0));
+ if (vals[i].string_value.str)
+ memcpy(vals[i].string_value.str, res->ptr(), res->length());
+ vals[i].string_value.length= res->length();
+ vals[i].charset= res->charset();
+ }
+ else
+ {
+ vals[i].string_value.str= NULL;
+ vals[i].string_value.length= 0; // just to be safe
+ DBUG_ASSERT(args[valpos]->null_value);
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ dres= args[valpos]->val_decimal(&dtmp);
+ if (dres)
+ {
+ dynamic_column_prepare_decimal(&vals[i]);
+ DBUG_ASSERT(vals[i].decimal_value.len == dres->len);
+ vals[i].decimal_value.intg= dres->intg;
+ vals[i].decimal_value.frac= dres->frac;
+ vals[i].decimal_value.sign= dres->sign();
+ memcpy(vals[i].decimal_buffer, dres->buf,
+ sizeof(vals[i].decimal_buffer));
+ }
+ else
+ {
+ dynamic_column_prepare_decimal(&vals[i]); // just to be safe
+ DBUG_ASSERT(args[valpos]->null_value);
+ }
+ break;
+ case DYN_COL_DATETIME:
+ args[valpos]->get_date(&vals[i].time_value, TIME_FUZZY_DATE);
+ break;
+ case DYN_COL_DATE:
+ args[valpos]->get_date(&vals[i].time_value, TIME_FUZZY_DATE);
+ break;
+ case DYN_COL_TIME:
+ args[valpos]->get_time(&vals[i].time_value);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ vals[i].type= DYN_COL_NULL;
+ }
+ if (vals[i].type != DYN_COL_NULL && args[valpos]->null_value)
+ {
+ if (vals[i].type == DYN_COL_STRING)
+ my_free(vals[i].string_value.str, MYF(MY_ALLOW_ZERO_PTR));
+ vals[i].type= DYN_COL_NULL;
+ }
+ }
+}
+
+void Item_func_dyncol_create::cleanup_arguments()
+{
+ uint column_count= (arg_count / 2);
+ uint i;
+
+ for (i= 0; i < column_count; i++)
+ {
+ if (vals[i].type == DYN_COL_STRING)
+ my_free(vals[i].string_value.str, MYF(MY_ALLOW_ZERO_PTR));
+ }
+}
+
+String *Item_func_dyncol_create::val_str(String *str)
+{
+ DYNAMIC_COLUMN col;
+ String *res;
+ uint column_count= (arg_count / 2);
+ int rc;
+ DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments
+
+ prepare_arguments();
+
+ if ((rc= dynamic_column_create_many(&col, column_count, nums, vals)))
+ {
+ dynamic_column_error_message(rc);
+ res= NULL;
+ null_value= TRUE;
+ }
+ else
+ {
+ res= str;
+ str->copy(col.str, col.length, &my_charset_bin);
+ }
+
+ /* cleanup */
+ dynamic_column_column_free(&col);
+ cleanup_arguments();
+
+ return res;
+}
+
+void Item_func_dyncol_create::print_arguments(String *str,
+ enum_query_type query_type)
+{
+ uint i;
+ uint column_count= (arg_count / 2);
+ for (i= 0; i < column_count; i++)
+ {
+ args[i*2]->print(str, query_type);
+ str->append(',');
+ args[i*2 + 1]->print(str, query_type);
+ switch (defs[i].type) {
+ case DYN_COL_NULL: // automatic type => write nothing
+ break;
+ case DYN_COL_INT:
+ str->append(STRING_WITH_LEN(" AS int"));
+ break;
+ case DYN_COL_UINT:
+ str->append(STRING_WITH_LEN(" AS unsigned int"));
+ break;
+ case DYN_COL_DOUBLE:
+ str->append(STRING_WITH_LEN(" AS double"));
+ break;
+ case DYN_COL_STRING:
+ str->append(STRING_WITH_LEN(" AS char"));
+ if (defs[i].cs)
+ {
+ str->append(STRING_WITH_LEN(" charset "));
+ str->append(defs[i].cs->csname);
+ str->append(' ');
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ str->append(STRING_WITH_LEN(" AS decimal"));
+ break;
+ case DYN_COL_DATETIME:
+ str->append(STRING_WITH_LEN(" AS datetime"));
+ break;
+ case DYN_COL_DATE:
+ str->append(STRING_WITH_LEN(" AS date"));
+ break;
+ case DYN_COL_TIME:
+ str->append(STRING_WITH_LEN(" AS time"));
+ break;
+ }
+ if (i < column_count - 1)
+ str->append(',');
+ }
+}
+
+
+void Item_func_dyncol_create::print(String *str,
+ enum_query_type query_type)
+{
+ DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments
+ str->append(STRING_WITH_LEN("column_create("));
+ print_arguments(str, query_type);
+ str->append(')');
+}
+
+
+String *Item_func_dyncol_add::val_str(String *str)
+{
+ DYNAMIC_COLUMN col;
+ String *res;
+ uint column_count= (arg_count / 2);
+ int rc;
+ DBUG_ASSERT((arg_count & 0x1) == 1); // odd number of arguments
+
+ prepare_arguments();
+
+ res= args[arg_count - 1]->val_str(str);
+ if (args[arg_count - 1]->null_value)
+ goto null;
+ init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE,
+ STRING_BUFFER_USUAL_SIZE);
+ col.length= res->length();
+ memcpy(col.str, res->ptr(), col.length);
+ if ((rc= dynamic_column_update_many(&col, column_count, nums, vals)))
+ {
+ dynamic_column_error_message(rc);
+ goto null;
+ }
+
+ str->copy(col.str, col.length, &my_charset_bin);
+
+ /* cleanup */
+ dynamic_column_column_free(&col);
+ cleanup_arguments();
+
+ return str;
+
+null:
+ null_value= TRUE;
+ return NULL;
+}
+
+
+void Item_func_dyncol_add::print(String *str,
+ enum_query_type query_type)
+{
+ DBUG_ASSERT((arg_count & 0x1) == 1); // odd number of arguments
+ str->append(STRING_WITH_LEN("column_create("));
+ args[arg_count - 1]->print(str, query_type);
+ str->append(',');
+ print_arguments(str, query_type);
+ str->append(')');
+}
+
+bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp)
+{
+ DYNAMIC_COLUMN dyn_str;
+ String *res;
+ longlong num;
+ int rc;
+
+ num= args[1]->val_int();
+ if (args[1]->null_value || num < 0 || num > INT_MAX)
+ {
+ null_value= 1;
+ return 1;
+ }
+
+ res= args[0]->val_str(tmp);
+ if (args[0]->null_value)
+ {
+ null_value= 1;
+ return 1;
+ }
+
+ dyn_str.str= (char*) res->ptr();
+ dyn_str.length= res->length();
+ if ((rc= dynamic_column_get(&dyn_str, (uint) num, val)))
+ {
+ dynamic_column_error_message(rc);
+ null_value= 1;
+ return 1;
+ }
+
+ null_value= 0;
+ return 0; // ok
+}
+
+
+String *Item_dyncol_get::val_str(String *str_result)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return NULL;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_INT:
+ case DYN_COL_UINT:
+ str_result->set_int(val.long_value, test(val.type == DYN_COL_UINT),
+ &my_charset_latin1);
+ break;
+ case DYN_COL_DOUBLE:
+ str_result->set_real(val.double_value, NOT_FIXED_DEC, &my_charset_latin1);
+ break;
+ case DYN_COL_STRING:
+ if ((char*) tmp.ptr() <= val.string_value.str &&
+ (char*) tmp.ptr() + tmp.length() >= val.string_value.str)
+ {
+ /* value is allocated in tmp buffer; We have to make a copy */
+ str_result->copy(val.string_value.str, val.string_value.length,
+ val.charset);
+ }
+ else
+ {
+ /*
+ It's safe to use the current value because it's either pointing
+ into a field or in a buffer for another item and this buffer
+ is not going to be deleted during expression evulation
+ */
+ str_result->set(val.string_value.str, val.string_value.length,
+ val.charset);
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ {
+ int res;
+ int length=
+ my_decimal_string_length((const my_decimal*)&val.decimal_value);
+ if (str_result->alloc(length))
+ goto null;
+ if ((res= decimal2string(&val.decimal_value, (char*) str_result->ptr(),
+ &length, 0, 0, ' ')) != E_DEC_OK)
+ {
+ char buff[40];
+ int len= sizeof(buff);
+ DBUG_ASSERT(length < (int)sizeof(buff[40]));
+ decimal2string(&val.decimal_value, buff, &len, 0, 0, ' ');
+ decimal_operation_results(res, buff, "CHAR");
+ }
+ str_result->set_charset(&my_charset_latin1);
+ str_result->length(length);
+ break;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ {
+ int length;
+ if (str_result->alloc(MAX_DATE_STRING_REP_LENGTH) ||
+ !(length= my_TIME_to_str(&val.time_value, (char*) str_result->ptr())))
+ goto null;
+ str_result->set_charset(&my_charset_latin1);
+ str_result->length(length);
+ break;
+ }
+ }
+ return str_result;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+longlong Item_dyncol_get::val_int()
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return 0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ unsigned_flag= 1; // Make it possible for caller to detect sign
+ return val.long_value;
+ case DYN_COL_INT:
+ unsigned_flag= 0; // Make it possible for caller to detect sign
+ return val.long_value;
+ case DYN_COL_DOUBLE:
+ {
+ bool error;
+ longlong num;
+
+ num= double_to_longlong(val.double_value, unsigned_flag, &error);
+ if (error)
+ {
+ char buff[30];
+ sprintf(buff, "%lg", val.double_value);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_DATA_OVERFLOW,
+ ER(ER_DATA_OVERFLOW),
+ buff,
+ unsigned_flag ? "UNSIGNED INT" : "INT");
+ }
+ return num;
+ }
+ case DYN_COL_STRING:
+ {
+ int error;
+ longlong num;
+ char *end= val.string_value.str + val.string_value.length, *org_end= end;
+
+ num= my_strtoll10(val.string_value.str, &end, &error);
+ if (end != org_end || error > 0)
+ {
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff,
+ unsigned_flag ? "UNSIGNED INT" : "INT");
+ }
+ unsigned_flag= error >= 0;
+ return num;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ longlong num;
+ my_decimal2int(E_DEC_FATAL_ERROR, &val.decimal_value, unsigned_flag,
+ &num);
+ return num;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ unsigned_flag= 1;
+ return TIME_to_ulonglong(&val.time_value);
+ }
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+double Item_dyncol_get::val_real()
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return 0.0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ return ulonglong2double(val.ulong_value);
+ case DYN_COL_INT:
+ return (double) val.long_value;
+ case DYN_COL_DOUBLE:
+ return (double) val.double_value;
+ case DYN_COL_STRING:
+ {
+ int error;
+ char *end;
+ double res= my_strntod(val.charset, (char*) val.string_value.str,
+ val.string_value.length, &end, &error);
+
+ if (end != (char*) val.string_value.str + val.string_value.length ||
+ error)
+ {
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff, "DOUBLE");
+ }
+ return res;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ double res;
+ /* This will always succed */
+ decimal2double(&val.decimal_value, &res);
+ return res;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ return (ulonglong2double(TIME_to_ulonglong(&val.time_value)) +
+ val.time_value.second_part / (double) TIME_SUBSECOND_RANGE);
+ }
+
+null:
+ null_value= TRUE;
+ return 0.0;
+}
+
+
+my_decimal *Item_dyncol_get::val_decimal(my_decimal *decimal_value)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return NULL;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ int2my_decimal(E_DEC_FATAL_ERROR, val.long_value, TRUE, decimal_value);
+ break;
+ case DYN_COL_INT:
+ int2my_decimal(E_DEC_FATAL_ERROR, val.long_value, FALSE, decimal_value);
+ break;
+ case DYN_COL_DOUBLE:
+ double2my_decimal(E_DEC_FATAL_ERROR, val.double_value, decimal_value);
+ break;
+ case DYN_COL_STRING:
+ {
+ int rc;
+ rc= str2my_decimal(0, val.string_value.str, val.string_value.length,
+ val.charset, decimal_value);
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ if (rc != E_DEC_OK)
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff, "DECIMAL");
+ }
+ break;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ int length= STRING_BUFFER_USUAL_SIZE;
+ decimal2string(&val.decimal_value, buff, &length, 0,0, 0);
+ decimal2my_decimal(&val.decimal_value, decimal_value);
+
+ break;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ {
+ double tmp= (ulonglong2double(TIME_to_ulonglong(&val.time_value)) +
+ val.time_value.second_part / (double) TIME_SUBSECOND_RANGE);
+ /* This can't overflow as time is always in the range of decimal */
+ double2my_decimal(E_DEC_FATAL_ERROR, tmp, decimal_value);
+ break;
+ }
+ }
+ return decimal_value;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+ bool signed_value= 0;
+
+ if (get_dyn_value(&val, &tmp))
+ return 0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_INT:
+ signed_value= 1; // For error message
+ /* fall_trough */
+ case DYN_COL_UINT:
+ {
+ ulonglong num;
+ int error;
+
+ num= val.ulong_value;
+ number_to_datetime(num, ltime, fuzzy_date, &error);
+ if (error)
+ {
+ char buff[65];
+ int errnum= error == 2 ? ER_DATA_OVERFLOW : ER_BAD_DATA;
+ longlong2str(num, buff, signed_value ? -10 : 10, 1);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ errnum,
+ ER(errnum),
+ buff, "DATE or DATETIME");
+ goto null;
+ }
+ return 0;
+ }
+ case DYN_COL_DOUBLE:
+ {
+ if (double_to_datetime_with_warn(val.double_value, ltime, fuzzy_date))
+ goto null;
+ return 0;
+ }
+ case DYN_COL_DECIMAL:
+ if (decimal_to_datetime_with_warn(&val.decimal_value, ltime, fuzzy_date))
+ goto null;
+ return 0;
+ case DYN_COL_STRING:
+ {
+ if (str_to_datetime_with_warn(val.string_value.str,
+ val.string_value.length,
+ ltime, fuzzy_date) <= MYSQL_TIMESTAMP_ERROR)
+ goto null;
+ return 0;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ *ltime= val.time_value;
+ return 0;
+ }
+
+null:
+ null_value= TRUE;
+ return 1;
+}
+
+void Item_dyncol_get::print(String *str, enum_query_type query_type)
+{
+ str->append(STRING_WITH_LEN("column_get("));
+ args[0]->print(str, query_type);
+ str->append(',');
+ args[1]->print(str, query_type);
+ str->append(')');
+}
+
+String *Item_func_dyncol_list::val_str(String *str)
+{
+ DYNAMIC_ARRAY arr;
+ DYNAMIC_COLUMN col;
+ String *res= args[0]->val_str(str);
+ uint i;
+ int rc;
+
+ if (args[0]->null_value)
+ goto null;
+ col.length= res->length();
+ /* We do not change the string, so could do this trick */
+ col.str= (char *)res->ptr();
+ if ((rc= dynamic_column_list(&col, &arr)))
+ {
+ dynamic_column_error_message(rc);
+ delete_dynamic(&arr);
+ goto null;
+ }
+
+ str->length(0);
+ for (i= 0; i < arr.elements; i++)
+ {
+ str->qs_append(*dynamic_element(&arr, i, uint*));
+ if (i < arr.elements - 1)
+ str->append(',');
+ }
+
+ delete_dynamic(&arr);
+ return str;
+null:
+ null_value= TRUE;
+ return NULL;
+}
=== modified file 'sql/item_strfunc.h'
--- sql/item_strfunc.h 2010-06-01 19:52:20 +0000
+++ sql/item_strfunc.h 2011-04-29 09:52:28 +0000
@@ -871,3 +871,71 @@
}
};
+
+class Item_func_dyncol_create: public Item_str_func
+{
+protected:
+ DYNCALL_CREATE_DEF *defs;
+ DYNAMIC_COLUMN_VALUE *vals;
+ uint *nums;
+ void prepare_arguments();
+ void cleanup_arguments();
+ void print_arguments(String *str, enum_query_type query_type);
+public:
+ Item_func_dyncol_create(List<Item> &args, DYNCALL_CREATE_DEF *dfs);
+ bool fix_fields(THD *thd, Item **ref);
+ void fix_length_and_dec();
+ const char *func_name() const{ return "column_create"; }
+ String *val_str(String *);
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_dyncol_add: public Item_func_dyncol_create
+{
+public:
+ Item_func_dyncol_add(List<Item> &args, DYNCALL_CREATE_DEF *dfs)
+ :Item_func_dyncol_create(args, dfs)
+ {}
+ const char *func_name() const{ return "column_add"; }
+ String *val_str(String *);
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+/*
+ The following functions is always called from an Item_cast function
+*/
+
+class Item_dyncol_get: public Item_str_func
+{
+public:
+ Item_dyncol_get(Item *str, Item *num)
+ :Item_str_func(str, num)
+ {
+ max_length= MAX_FIELD_BLOBLENGTH;
+ }
+ void fix_length_and_dec()
+ { maybe_null= 1; }
+ /* Mark that collation can change between calls */
+ bool dynamic_result() { return 1; }
+
+ const char *func_name() const { return "column_get"; }
+ String *val_str(String *);
+ longlong val_int();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ bool get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp);
+ bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_dyncol_list: public Item_str_func
+{
+public:
+ Item_func_dyncol_list(Item *str) :Item_str_func(str) {};
+ void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
+ const char *func_name() const{ return "column_list"; }
+ String *val_str(String *);
+};
=== modified file 'sql/lex.h'
--- sql/lex.h 2011-04-28 16:56:10 +0000
+++ sql/lex.h 2011-04-29 09:52:28 +0000
@@ -116,6 +116,12 @@
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
{ "COLUMNS", SYM(COLUMNS)},
+ { "COLUMN_ADD", SYM(COLUMN_ADD_SYM)},
+ { "COLUMN_CREATE", SYM(COLUMN_CREATE_SYM)},
+ { "COLUMN_DELETE", SYM(COLUMN_DELETE_SYM)},
+ { "COLUMN_EXISTS", SYM(COLUMN_EXISTS_SYM)},
+ { "COLUMN_GET", SYM(COLUMN_GET_SYM)},
+ { "COLUMN_LIST", SYM(COLUMN_LIST_SYM)},
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
{ "COMMITTED", SYM(COMMITTED_SYM)},
=== modified file 'sql/my_decimal.cc'
--- sql/my_decimal.cc 2011-02-20 16:51:43 +0000
+++ sql/my_decimal.cc 2011-04-29 09:52:28 +0000
@@ -30,21 +30,20 @@
result
*/
-int decimal_operation_results(int result)
+int decimal_operation_results(int result, const char *value, const char *type)
{
switch (result) {
case E_DEC_OK:
break;
case E_DEC_TRUNCATED:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
- "", (ulong) 0);
+ ER_DATA_TRUNCATED, ER(ER_DATA_TRUNCATED),
+ value, type);
break;
case E_DEC_OVERFLOW:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE),
- "DECIMAL", "");
+ ER_DATA_OVERFLOW, ER(ER_DATA_OVERFLOW),
+ value, type);
break;
case E_DEC_DIV_ZERO:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
@@ -52,9 +51,8 @@
break;
case E_DEC_BAD_NUM:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
- ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
- "decimal", "", "", (ulong) 0);
+ ER_BAD_DATA, ER(ER_BAD_DATA),
+ value, type);
break;
case E_DEC_OOM:
my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -283,6 +281,35 @@
return buff;
}
+
+/*
+ Convert a decimal to an ulong with a descreptive error message
+*/
+
+int my_decimal2int(uint mask, const decimal_t *d, my_bool unsigned_flag,
+ longlong *l)
+{
+ int res;
+ my_decimal rounded;
+ /* decimal_round can return only E_DEC_TRUNCATED */
+ decimal_round(d, &rounded, 0, HALF_UP);
+ res= (unsigned_flag ?
+ decimal2ulonglong(&rounded, (ulonglong *) l) :
+ decimal2longlong(&rounded, l));
+ if (res & mask)
+ {
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ int length= sizeof(buff);
+ decimal2string(d, buff, &length, 0, 0, 0);
+
+ decimal_operation_results(res, buff,
+ unsigned_flag ? "UNSIGNED INT" :
+ "INT");
+ }
+ return res;
+}
+
+
#endif /*DBUG_OFF*/
=== modified file 'sql/my_decimal.h'
--- sql/my_decimal.h 2010-11-24 22:57:34 +0000
+++ sql/my_decimal.h 2011-04-29 09:52:28 +0000
@@ -32,32 +32,7 @@
#include <decimal.h>
C_MODE_END
-#define DECIMAL_LONGLONG_DIGITS 22
-#define DECIMAL_LONG_DIGITS 10
-#define DECIMAL_LONG3_DIGITS 8
-
-/** maximum length of buffer in our big digits (uint32). */
-#define DECIMAL_BUFF_LENGTH 9
-
-/* the number of digits that my_decimal can possibly contain */
-#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
-
-
-/**
- maximum guaranteed precision of number in decimal digits (number of our
- digits * number of decimal digits in one our big digit - number of decimal
- digits in one our big digit decreased by 1 (because we always put decimal
- point on the border of our big digits))
-*/
-#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
-#define DECIMAL_MAX_SCALE 30
-#define DECIMAL_NOT_SPECIFIED 31
-
-/**
- maximum length of string representation (number of maximum decimal
- digits + 1 position for sign + 1 position for decimal point)
-*/
-#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
+#include <my_decimal_limits.h>
/**
maximum size of packet length.
@@ -134,9 +109,10 @@
#endif
#ifndef MYSQL_CLIENT
-int decimal_operation_results(int result);
+int decimal_operation_results(int result, const char *value, const char *type);
#else
-inline int decimal_operation_results(int result)
+inline int decimal_operation_results(int result, const char *value,
+ const char *type)
{
return result;
}
@@ -158,7 +134,7 @@
inline int check_result(uint mask, int result)
{
if (result & mask)
- decimal_operation_results(result);
+ decimal_operation_results(result, "", "DECIMAL");
return result;
}
@@ -294,24 +270,14 @@
uint fixed_dec, char filler, String *str);
#endif
-inline
-int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
- longlong *l)
-{
- my_decimal rounded;
- /* decimal_round can return only E_DEC_TRUNCATED */
- decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
- return check_result(mask, (unsigned_flag ?
- decimal2ulonglong(&rounded, (ulonglong *)l) :
- decimal2longlong(&rounded, l)));
-}
-
-
-inline
-int my_decimal2double(uint, const my_decimal *d, double *result)
+int my_decimal2int(uint mask, const decimal_t *d, my_bool unsigned_flag,
+ longlong *l);
+
+inline
+int my_decimal2double(uint, const decimal_t *d, double *result)
{
/* No need to call check_result as this will always succeed */
- return decimal2double((decimal_t*) d, result);
+ return decimal2double(d, result);
}
@@ -354,6 +320,18 @@
longlong2decimal(i, d)));
}
+inline
+void decimal2my_decimal(decimal_t *from, my_decimal *to)
+{
+ DBUG_ASSERT(to->len >= from->len);
+ to->intg= from->intg;
+ to->frac= from->frac;
+ to->sign(from->sign);
+ memcpy(to->buf, from->buf, to->len*sizeof(decimal_digit_t));
+}
+
+
+
inline
void my_decimal_neg(decimal_t *arg)
=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h 2011-04-28 16:56:10 +0000
+++ sql/mysql_priv.h 2011-04-29 09:52:28 +0000
@@ -1412,6 +1412,7 @@
Field *
find_field_in_table_sef(TABLE *table, const char *name);
int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE);
+int dynamic_column_error_message(int rc);
#endif /* MYSQL_SERVER */
@@ -2322,16 +2323,22 @@
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *not_exist);
-bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time);
+bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time,
+ ulong fuzzydate);
timestamp_type str_to_datetime_with_warn(const char *str, uint length,
- MYSQL_TIME *l_time, uint flags);
+ MYSQL_TIME *l_time, ulong flags);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
-void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+void make_truncated_value_warning(THD *thd,
+ MYSQL_ERROR::enum_warning_level level,
const char *str_val,
uint str_length, timestamp_type time_type,
const char *field_name);
+bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime,
+ ulong fuzzy_date);
+bool decimal_to_datetime_with_warn(decimal_t *value, MYSQL_TIME *ltime,
+ ulong fuzzy_date);
bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL interval);
bool calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign,
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2011-04-28 16:56:10 +0000
+++ sql/share/errmsg.txt 2011-04-29 09:55:41 +0000
@@ -5321,7 +5321,7 @@
ER_DIVISION_BY_ZERO 22012
eng "Division by 0"
ger "Division durch 0"
-ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
+ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 22007
eng "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %lu"
ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.192s' in Zeile %lu"
ER_ILLEGAL_VALUE_FOR_TYPE 22007
@@ -6251,4 +6251,15 @@
eng "Incorrect value '%-.64s' for option '%-.64s'"
ER_CANT_DO_ONLINE
eng "Can't execute the given '%s' command as online"
-
+ER_DATA_OVERFLOW 22003
+ eng "Got overflow when converting '%-.128s' to %-.32s. Value truncated."
+ER_DATA_TRUNCATED 22003
+ eng "Truncated value '%-.128s' when converting to %-.32s"
+ER_BAD_DATA 22007
+ eng "Encountered illegal value '%-.128s' when converting to %-.32s"
+ER_DYN_COL_WRONG_FORMAT
+ eng "Encountered illegal format of dynamic column string"
+ER_DYN_COL_IMPLEMENTATION_LIMIT
+ eng "Dynamic column implementation limit reached"
+ER_DYN_COL_DATA 22007
+ eng "Illegal value used as argument of dynamic column function"
=== modified file 'sql/sql_base.cc'
--- sql/sql_base.cc 2011-03-31 15:35:57 +0000
+++ sql/sql_base.cc 2011-04-29 09:52:28 +0000
@@ -9406,6 +9406,39 @@
thd->restore_backup_open_tables_state(backup);
}
+
+/**
+ Check result of dynamic column function and issue error if it is needed
+
+ @param rc The result code of dynamic column function
+
+ @return the result code which was get as an argument\
+*/
+
+int dynamic_column_error_message(int rc)
+{
+ switch (rc) {
+ case ER_DYNCOL_YES:
+ case ER_DYNCOL_OK:
+ break; // it is not an error
+ case ER_DYNCOL_FORMAT:
+ my_error(ER_DYN_COL_WRONG_FORMAT, MYF(0));
+ break;
+ case ER_DYNCOL_LIMIT:
+ my_error(ER_DYN_COL_IMPLEMENTATION_LIMIT, MYF(0));
+ break;
+ case ER_DYNCOL_RESOURCE:
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ break;
+ case ER_DYNCOL_DATA:
+ my_error(ER_DYN_COL_DATA, MYF(0));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ return rc;
+}
+
/**
@} (end of group Data_Dictionary)
*/
=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy 2011-04-28 16:56:10 +0000
+++ sql/sql_yacc.yy 2011-04-29 09:56:51 +0000
@@ -34,6 +34,7 @@
#define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */
#define Lex (YYTHD->lex)
+
#define Select Lex->current_select
#include "mysql_priv.h"
#include "slave.h"
@@ -671,6 +672,8 @@
sp_head *sphead;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
+ DYNCALL_CREATE_DEF *dyncol_def;
+ List<DYNCALL_CREATE_DEF> *dyncol_def_list;
}
%{
@@ -770,6 +773,12 @@
%token COLLATE_SYM /* SQL-2003-R */
%token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS
+%token COLUMN_ADD_SYM
+%token COLUMN_CREATE_SYM
+%token COLUMN_DELETE_SYM
+%token COLUMN_EXISTS_SYM
+%token COLUMN_GET_SYM
+%token COLUMN_LIST_SYM
%token COLUMN_SYM /* SQL-2003-R */
%token COMMENT_SYM
%token COMMITTED_SYM /* SQL-2003-N */
@@ -1338,7 +1347,7 @@
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
- optional_flush_tables_arguments
+ optional_flush_tables_arguments opt_dyncol_type dyncol_type
%type <ulong_num>
ulong_num real_ulong_num merge_insert_types
@@ -1438,6 +1447,10 @@
%type <boolfunc2creator> comp_op
+%type <dyncol_def> dyncall_create_element
+
+%type <dyncol_def_list> dyncall_create_list
+
%type <NONE>
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
@@ -7506,6 +7519,131 @@
| ANY_SYM { $$ = 0; }
;
+opt_dyncol_type:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_NULL; /* automatic type */
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | AS dyncol_type { $$= $2; }
+ ;
+
+dyncol_type:
+ INT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_INT;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | UNSIGNED INT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_UINT;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DOUBLE_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | REAL
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | FLOAT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DECIMAL_SYM float_options
+ {
+ $$= DYN_COL_DECIMAL;
+ Lex->charset= NULL;
+ }
+ | char opt_binary
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_STRING;
+ lex->length= lex->dec= 0;
+ }
+ | nchar
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_STRING;
+ lex->charset= national_charset_info;
+ lex->length= lex->dec= 0;
+ }
+ | DATE_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DATE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | TIME_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_TIME;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DATETIME
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DATETIME;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ ;
+
+dyncall_create_element:
+ expr ',' expr opt_dyncol_type
+ {
+ LEX *lex= Lex;
+ $$= (DYNCALL_CREATE_DEF *)
+ alloc_root(YYTHD->mem_root, sizeof(DYNCALL_CREATE_DEF));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->num= $1;
+ $$->value= $3;
+ $$->type= (DYNAMIC_COLUMN_TYPE)$4;
+ $$->cs= lex->charset;
+ if (lex->length)
+ $$->len= strtoul(lex->length, NULL, 10);
+ else
+ $$->len= 0;
+ if (lex->dec)
+ $$->frac= strtoul(lex->dec, NULL, 10);
+ else
+ $$->len= 0;
+ }
+
+dyncall_create_list:
+ dyncall_create_element
+ {
+ $$= new (YYTHD->mem_root) List<DYNCALL_CREATE_DEF>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1);
+ }
+ | dyncall_create_list ',' dyncall_create_element
+ {
+ $1->push_back($3);
+ $$= $1;
+ }
+ ;
+
simple_expr:
simple_ident
| function_call_keyword
@@ -8040,6 +8178,51 @@
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
+ |
+ COLUMN_ADD_SYM '(' expr ',' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_add(YYTHD, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_DELETE_SYM '(' expr ',' expr_list ')'
+ {
+ $$= create_func_dyncol_delete(YYTHD, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_EXISTS_SYM '(' expr ',' expr ')'
+ {
+ $$= new (YYTHD->mem_root) Item_func_dyncol_exists($3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_LIST_SYM '(' expr ')'
+ {
+ $$= new (YYTHD->mem_root) Item_func_dyncol_list($3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_CREATE_SYM '(' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_create(YYTHD, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
+ {
+ LEX *lex= Lex;
+ $$= create_func_dyncol_get(YYTHD, $3, $5, $7,
+ lex->length, lex->dec,
+ lex->charset);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
;
/*
@@ -8641,6 +8824,8 @@
{ $$=ITEM_CAST_CHAR; Lex->dec= 0; }
| NCHAR_SYM opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
+ | INT_SYM
+ { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| SIGNED_SYM
{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| SIGNED_SYM INT_SYM
@@ -8657,7 +8842,10 @@
{ $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| DECIMAL_SYM float_options
{ $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; }
- ;
+ | DOUBLE_SYM
+ { Lex->charset= NULL; Lex->length= Lex->dec= 0;}
+ opt_precision
+ { $$=ITEM_CAST_DOUBLE; }
opt_expr_list:
/* empty */ { $$= NULL; }
@@ -11887,6 +12075,12 @@
| CHECKSUM_SYM {}
| CHECKPOINT_SYM {}
| CLOSE_SYM {}
+ | COLUMN_ADD_SYM {}
+ | COLUMN_CREATE_SYM {}
+ | COLUMN_DELETE_SYM {}
+ | COLUMN_EXISTS_SYM {}
+ | COLUMN_GET_SYM {}
+ | COLUMN_LIST_SYM {}
| COMMENT_SYM {}
| COMMIT_SYM {}
| CONTAINS_SYM {}
=== added file 'unittest/mysys/ma_dyncol-t.c'
--- unittest/mysys/ma_dyncol-t.c 1970-01-01 00:00:00 +0000
+++ unittest/mysys/ma_dyncol-t.c 2011-04-29 09:52:28 +0000
@@ -0,0 +1,767 @@
+#include <my_global.h>
+#include <ma_dyncol.h>
+#include <tap.h>
+
+
+
+void test_value_single_null()
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_NULL;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_NULL);
+err:
+ ok(rc, "%s", "NULL");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_uint(ulonglong num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_UINT;
+ val.ulong_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_UINT) && (res.ulong_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %llu", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_sint(longlong num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_INT;
+ val.long_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_INT) && (res.long_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %lld", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_single_double(double num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DOUBLE;
+ val.double_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_DOUBLE) && (res.double_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %lf", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_decimal(const char *num)
+{
+ char *end= (((char*)num) + strlen(num));
+ char buff[80];
+ int rc= FALSE;
+ int length= 80;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+
+ /* init values */
+ dynamic_column_prepare_decimal(&val); // special procedure for decimal!!!
+ if (string2decimal(num, &val.decimal_value, &end) != E_DEC_OK)
+ goto err;
+ dynamic_column_value_init(&res);
+
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DECIMAL) &&
+ (decimal_cmp(&res.decimal_value, &val.decimal_value) == 0));
+ decimal2string(&res.decimal_value, buff, &length, 0, 0, ' ');
+err:
+ ok(rc, "%s - %s", num, buff);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+static CHARSET_INFO *charset_list[]=
+{
+#ifdef HAVE_CHARSET_big5
+ &my_charset_big5_chinese_ci,
+ &my_charset_big5_bin,
+#endif
+#ifdef HAVE_CHARSET_euckr
+ &my_charset_euckr_korean_ci,
+ &my_charset_euckr_bin,
+#endif
+#ifdef HAVE_CHARSET_gb2312
+ &my_charset_gb2312_chinese_ci,
+ &my_charset_gb2312_bin,
+#endif
+#ifdef HAVE_CHARSET_gbk
+ &my_charset_gbk_chinese_ci,
+ &my_charset_gbk_bin,
+#endif
+#ifdef HAVE_CHARSET_latin1
+ &my_charset_latin1,
+ &my_charset_latin1_bin,
+#endif
+#ifdef HAVE_CHARSET_sjis
+ &my_charset_sjis_japanese_ci,
+ &my_charset_sjis_bin,
+#endif
+#ifdef HAVE_CHARSET_tis620
+ &my_charset_tis620_thai_ci,
+ &my_charset_tis620_bin,
+#endif
+#ifdef HAVE_CHARSET_ujis
+ &my_charset_ujis_japanese_ci,
+ &my_charset_ujis_bin,
+#endif
+#ifdef HAVE_CHARSET_utf8
+ &my_charset_utf8_general_ci,
+#ifdef HAVE_HAVE_UCA_COLLATIONS
+ &my_charset_utf8_unicode_ci,
+#endif
+ &my_charset_utf8_bin,
+#endif
+};
+
+
+void test_value_single_string(const char *string, size_t len,
+ CHARSET_INFO *cs)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+
+ /* init values */
+ val.type= DYN_COL_STRING;
+ val.string_value.str= (char*)string;
+ val.string_value.length= len;
+ val.charset= cs;
+ dynamic_column_value_init(&res);
+
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_STRING) &&
+ (res.string_value.length == len) &&
+ (memcmp(res.string_value.str, string, len) == 0) &&
+ (res.charset->number == cs->number));
+err:
+ ok(rc, "'%s' - '%s' %u %u-%s", string,
+ res.string_value.str, (uint)res.string_value.length,
+ (uint)res.charset->number, res.charset->name);
+ /* cleanup */
+ val.string_value.str= NULL; // we did not allocated it
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_date(uint year, uint month, uint day, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DATE;
+ val.time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ val.time_value.year= year;
+ val.time_value.month= month;
+ val.time_value.day= day;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DATE) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
+ (res.time_value.year == year) &&
+ (res.time_value.month == month) &&
+ (res.time_value.day == day));
+err:
+ ok(rc, "%s - %04u-%02u-%02u", name, year, month, day);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_time(uint neg, uint hour, uint minute, uint second,
+ uint mic, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_TIME;
+ val.time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ val.time_value.neg= neg;
+ val.time_value.hour= hour;
+ val.time_value.minute= minute;
+ val.time_value.second= second;
+ val.time_value.second_part= mic;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_TIME) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
+ (res.time_value.neg == (int)neg) &&
+ (res.time_value.hour == hour) &&
+ (res.time_value.minute == minute) &&
+ (res.time_value.second == second) &&
+ (res.time_value.second_part == mic));
+err:
+ ok(rc, "%s - %c%02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
+ hour, minute, second, mic);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_single_datetime(uint neg, uint year, uint month, uint day,
+ uint hour, uint minute, uint second,
+ uint mic, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DATETIME;
+ val.time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ val.time_value.neg= neg;
+ val.time_value.year= year;
+ val.time_value.month= month;
+ val.time_value.day= day;
+ val.time_value.hour= hour;
+ val.time_value.minute= minute;
+ val.time_value.second= second;
+ val.time_value.second_part= mic;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DATETIME) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
+ (res.time_value.neg == (int)neg) &&
+ (res.time_value.year == year) &&
+ (res.time_value.month == month) &&
+ (res.time_value.day == day) &&
+ (res.time_value.hour == hour) &&
+ (res.time_value.minute == minute) &&
+ (res.time_value.second == second) &&
+ (res.time_value.second_part == mic));
+err:
+ ok(rc, "%s - %c %04u-%02u-%02u %02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
+ year, month, day, hour, minute, second, mic);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_multi(ulonglong num0,
+ longlong num1,
+ double num2,
+ const char *num3,
+ const char *string4, size_t len4, CHARSET_INFO *cs4,
+ uint year5, uint month5, uint day5,
+ uint neg6, uint hour6, uint minute6,
+ uint second6, uint mic6,
+ uint neg7, uint year7, uint month7, uint day7,
+ uint hour7, uint minute7, uint second7,
+ uint mic7,
+ uint *column_numbers,
+ const char *name)
+{
+ char *end3= (((char*)num3) + strlen(num3));
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN_VALUE val[9], res[9];
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val[0].type= DYN_COL_UINT;
+ val[0].ulong_value= num0;
+ val[1].type= DYN_COL_INT;
+ val[1].long_value= num1;
+ val[2].type= DYN_COL_DOUBLE;
+ val[2].double_value= num2;
+ dynamic_column_prepare_decimal(val + 3); // special procedure for decimal!!!
+ if (string2decimal(num3, &val[3].decimal_value, &end3) != E_DEC_OK)
+ goto err;
+ val[4].type= DYN_COL_STRING;
+ val[4].string_value.str= (char*)string4;
+ val[4].string_value.length= len4;
+ val[4].charset= cs4;
+ val[5].type= DYN_COL_DATE;
+ val[5].time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ val[5].time_value.year= year5;
+ val[5].time_value.month= month5;
+ val[5].time_value.day= day5;
+ val[6].type= DYN_COL_TIME;
+ val[6].time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ val[6].time_value.neg= neg6;
+ val[6].time_value.hour= hour6;
+ val[6].time_value.minute= minute6;
+ val[6].time_value.second= second6;
+ val[6].time_value.second_part= mic6;
+ val[7].type= DYN_COL_DATETIME;
+ val[7].time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ val[7].time_value.neg= neg7;
+ val[7].time_value.year= year7;
+ val[7].time_value.month= month7;
+ val[7].time_value.day= day7;
+ val[7].time_value.hour= hour7;
+ val[7].time_value.minute= minute7;
+ val[7].time_value.second= second7;
+ val[7].time_value.second_part= mic7;
+ val[8].type= DYN_COL_NULL;
+ for (i= 0; i < 9; i++)
+ dynamic_column_value_init(res + i);
+ /* create column */
+ if (dynamic_column_create_many(&str, 9, column_numbers, val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ for (i= 0; i < 9; i++)
+ if (dynamic_column_get(&str, column_numbers[i], res + i))
+ goto err;
+ rc= ((res[0].type == DYN_COL_UINT) &&
+ (res[0].ulong_value == num0) &&
+ (res[1].type == DYN_COL_INT) &&
+ (res[1].long_value == num1) &&
+ (res[2].type == DYN_COL_DOUBLE) &&
+ (res[2].double_value == num2) &&
+ (res[3].type == DYN_COL_DECIMAL) &&
+ (decimal_cmp(&res[3].decimal_value, &val[3].decimal_value) == 0) &&
+ (res[4].type == DYN_COL_STRING) &&
+ (res[4].string_value.length == len4) &&
+ (memcmp(res[4].string_value.str, string4, len4) == 0) &&
+ (res[4].charset->number == cs4->number) &&
+ (res[5].type == DYN_COL_DATE) &&
+ (res[5].time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
+ (res[5].time_value.year == year5) &&
+ (res[5].time_value.month == month5) &&
+ (res[5].time_value.day == day5) &&
+ (res[6].type == DYN_COL_TIME) &&
+ (res[6].time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
+ (res[6].time_value.neg == (int)neg6) &&
+ (res[6].time_value.hour == hour6) &&
+ (res[6].time_value.minute == minute6) &&
+ (res[6].time_value.second == second6) &&
+ (res[6].time_value.second_part == mic6) &&
+ (res[7].type == DYN_COL_DATETIME) &&
+ (res[7].time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
+ (res[7].time_value.neg == (int)neg7) &&
+ (res[7].time_value.year == year7) &&
+ (res[7].time_value.month == month7) &&
+ (res[7].time_value.day == day7) &&
+ (res[7].time_value.hour == hour7) &&
+ (res[7].time_value.minute == minute7) &&
+ (res[7].time_value.second == second7) &&
+ (res[7].time_value.second_part == mic7) &&
+ (res[8].type == DYN_COL_NULL));
+err:
+ ok(rc, "%s", name);
+ /* cleanup */
+ val[4].string_value.str= NULL; // we did not allocated it
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_multi_same_num()
+{
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN_VALUE val[5];
+ uint column_numbers[]= {3,4,5,3,6}; // same column numbers
+ DYNAMIC_COLUMN str;
+ /* init values */
+ for (i= 0; i < 5; i++)
+ val[i].type= DYN_COL_NULL;
+ /* create column */
+ if (!dynamic_column_create_many(&str, 5, column_numbers, val))
+ goto err;
+ rc= TRUE;
+err:
+ ok(rc, "%s", "same column numbers check");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_update_multi(uint *column_numbers, uint *column_values,
+ my_bool *null_values, int only_add, int all)
+{
+ int rc= FALSE;
+ int i, j;
+ DYNAMIC_COLUMN str;
+ DYNAMIC_COLUMN_VALUE val;
+
+ val.type= DYN_COL_UINT;
+ val.ulong_value= column_values[0];
+ if (dynamic_column_create(&str, column_numbers[0], &val))
+ goto err;
+ for (i= 1; i < all; i++)
+ {
+ val.type= (null_values[i] ? DYN_COL_NULL : DYN_COL_UINT);
+ val.ulong_value= column_values[i];
+ if (dynamic_column_update(&str, column_numbers[i], &val))
+ goto err;
+
+ /* check value(s) */
+ for (j= i; j >= (i < only_add ? 0 : i); j--)
+ {
+ if (dynamic_column_get(&str, column_numbers[j], &val))
+ goto err;
+ if (null_values[j])
+ {
+ if (val.type != DYN_COL_NULL ||
+ dynamic_column_exists(&str, column_numbers[j]) == ER_DYNCOL_YES)
+ goto err;
+ }
+ else
+ {
+ if (val.type != DYN_COL_UINT ||
+ val.ulong_value != column_values[j] ||
+ dynamic_column_exists(&str, column_numbers[j]) == ER_DYNCOL_NO)
+ goto err;
+ }
+ }
+ if (i < only_add)
+ {
+ DYNAMIC_ARRAY num;
+ if (dynamic_column_list(&str, &num))
+ goto err;
+ /* cross check arrays */
+ if ((int)num.elements != i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ for(j= 0; j < i + 1; j++)
+ {
+ int k;
+ for(k= 0;
+ k < i + 1 && column_numbers[j] !=
+ *dynamic_element(&num, k, uint*);
+ k++);
+ if (k >= i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ for(k= 0;
+ k < i + 1 && column_numbers[k] !=
+ *dynamic_element(&num, j, uint*);
+ k++);
+ if (k >= i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ }
+ delete_dynamic(&num);
+ }
+ }
+
+ rc= TRUE;
+err:
+ ok(rc, "%s", "add/delete/update");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_empty_string()
+{
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ DYNAMIC_ARRAY array_of_uint;
+ int rc;
+ /* empty string */
+ bzero(&str, sizeof(str));
+
+ rc= dynamic_column_get(&str, 1, &res);
+ ok( (rc == ER_DYNCOL_OK) && (res.type == DYN_COL_NULL), "%s", "empty get");
+
+ rc= dynamic_column_delete(&str, 1);
+ ok( (rc == ER_DYNCOL_OK), "%s", "empty delete");
+
+ rc= dynamic_column_exists(&str, 1);
+ ok( (rc == ER_DYNCOL_NO), "%s", "empty exists");
+
+ rc= dynamic_column_list(&str, &array_of_uint);
+ ok( (rc == ER_DYNCOL_OK) && (array_of_uint.elements == 0),
+ "%s", "empty list");
+
+ val.type= DYN_COL_UINT;
+ val.ulong_value= 1212;
+ rc= dynamic_column_update(&str, 1, &val);
+ if (rc == ER_DYNCOL_OK)
+ rc= dynamic_column_get(&str, 1, &res);
+ ok( (rc == ER_DYNCOL_OK) &&
+ (res.type == DYN_COL_UINT) && (res.ulong_value == val.ulong_value),
+ "%s", "empty update");
+}
+
+
+void test_update_many(uint *column_numbers, uint *column_values,
+ uint column_count,
+ uint *update_numbers, uint *update_values,
+ my_bool *update_nulls, uint update_count,
+ uint *result_numbers, uint *result_values,
+ uint result_count)
+{
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN str1;
+ DYNAMIC_COLUMN str2;
+ DYNAMIC_COLUMN_VALUE *val, *upd, *res;
+
+ val= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ column_count);
+ upd= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ update_count);
+ res= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ result_count);
+
+
+ for (i= 0; i < column_count; i++)
+ {
+ val[i].type= DYN_COL_UINT;
+ val[i].ulong_value= column_values[i];
+ }
+ for (i= 0; i < update_count; i++)
+ {
+ if (update_nulls[i])
+ upd[i].type= DYN_COL_NULL;
+ else
+ {
+ upd[i].type= DYN_COL_UINT;
+ upd[i].ulong_value= update_values[i];
+ }
+ }
+ for (i= 0; i < result_count; i++)
+ {
+ res[i].type= DYN_COL_UINT;
+ res[i].ulong_value= result_values[i];
+ }
+ if (dynamic_column_create_many(&str1, column_count, column_numbers, val))
+ goto err;
+ if (dynamic_column_update_many(&str1, update_count, update_numbers, upd))
+ goto err;
+ if (dynamic_column_create_many(&str2, result_count, result_numbers, res))
+ goto err;
+ if (str1.length == str2.length &&
+ memcmp(str1.str, str2.str, str1.length) ==0)
+ rc= TRUE;
+
+err:
+ ok(rc, "%s", "update_many");
+ /* cleanup */
+ dynamic_column_column_free(&str1);
+ dynamic_column_column_free(&str2);
+}
+
+int main(int argc __attribute__((unused)), char **argv)
+{
+ uint i;
+ char *big_string= (char *)malloc(1024*1024);
+
+ MY_INIT(argv[0]);
+ plan(59);
+
+ if (!big_string)
+ exit(1);
+ for (i= 0; i < 1024*1024; i++)
+ big_string[i]= ('0' + (i % 10));
+ test_value_single_null();
+ test_value_single_uint(0, "0");
+ test_value_single_uint(0xffffffffffffffff, "0xffffffffffffffff");
+ test_value_single_uint(0xaaaaaaaaaaaaaaaa, "0xaaaaaaaaaaaaaaaa");
+ test_value_single_uint(0x5555555555555555, "0x5555555555555555");
+ test_value_single_uint(27652, "27652");
+ test_value_single_sint(0, "0");
+ test_value_single_sint(1, "1");
+ test_value_single_sint(-1, "-1");
+ test_value_single_sint((longlong)0x7fffffffffffffff,
+ "0x7fffffffffffffff");
+ test_value_single_sint((longlong)0xaaaaaaaaaaaaaaaa,
+ "0xaaaaaaaaaaaaaaaa");
+ test_value_single_sint((longlong)0x5555555555555555,
+ "0x5555555555555555");
+ test_value_single_sint((longlong)0x8000000000000000,
+ "0x8000000000000000");
+ test_value_single_double(0.0, "0.0");
+ test_value_single_double(1.0, "1.0");
+ test_value_single_double(-1.0, "-1.0");
+ test_value_single_double(1.0e100, "1.0e100");
+ test_value_single_double(1.0e-100, "1.0e-100");
+ test_value_single_double(9999999999999999999999999999999999999.0,
+ "9999999999999999999999999999999999999.0");
+ test_value_single_double(-9999999999999999999999999999999999999.0,
+ "-9999999999999999999999999999999999999.0");
+ test_value_single_decimal("0");
+ test_value_single_decimal("1");
+ test_value_single_decimal("-1");
+ test_value_single_decimal("9999999999999999999999999999999");
+ test_value_single_decimal("-9999999999999999999999999999999");
+ test_value_single_decimal("0.9999999999999999999999999999999");
+ test_value_single_decimal("-0.9999999999999999999999999999999");
+ test_value_single_string("", 0, charset_list[0]);
+ test_value_single_string("", 1, charset_list[0]);
+ test_value_single_string("1234567890", 11, charset_list[0]);
+ test_value_single_string("nulls\0\0\0\0\0", 10, charset_list[0]);
+ sprintf(big_string, "%x", 0x7a);
+ test_value_single_string(big_string, 0x7a, charset_list[0]);
+ sprintf(big_string, "%x", 0x80);
+ test_value_single_string(big_string, 0x80, charset_list[0]);
+ sprintf(big_string, "%x", 0x7ffa);
+ test_value_single_string(big_string, 0x7ffa, charset_list[0]);
+ sprintf(big_string, "%x", 0x8000);
+ test_value_single_string(big_string, 0x8000, charset_list[0]);
+ sprintf(big_string, "%x", 1024*1024);
+ test_value_single_string(big_string, 1024*1024, charset_list[0]);
+ free(big_string);
+ test_value_single_date(0, 0, 0, "zero date");
+ test_value_single_date(9999, 12, 31, "max date");
+ test_value_single_date(2011, 3, 26, "some date");
+ test_value_single_time(0, 0, 0, 0, 0, "zero time");
+ test_value_single_time(1, 23, 59, 59, 999999, "min time");
+ test_value_single_time(0, 23, 59, 59, 999999, "max time");
+ test_value_single_time(0, 21, 36, 20, 28, "some time");
+ test_value_single_datetime(0, 0, 0, 0, 0, 0, 0, 0, "zero datetime");
+ test_value_single_datetime(1, 9999, 12, 31, 23, 59, 59, 999999,
+ "min datetime");
+ test_value_single_datetime(0, 9999, 12, 31, 23, 59, 59, 999999,
+ "max datetime");
+ test_value_single_datetime(0, 2011, 3, 26, 21, 53, 12, 3445,
+ "some datetime");
+ {
+ uint column_numbers[]= {100,1,2,3,4,5,6,7,8};
+ test_value_multi(0, 0, 0.0, "0",
+ "", 0, charset_list[0],
+ 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ column_numbers,
+ "zero data");
+ }
+ {
+ uint column_numbers[]= {10,1,12,37,4,57,6,76,87};
+ test_value_multi(0xffffffffffffffff, 0x7fffffffffffffff,
+ 99999999.999e120, "9999999999999999999999999999999",
+ big_string, 1024*1024, charset_list[0],
+ 9999, 12, 31,
+ 0, 23, 59, 59, 999999,
+ 0, 9999, 12, 31, 23, 59, 59, 999999,
+ column_numbers,
+ "much data");
+ }
+ {
+ uint column_numbers[]= {101,12,122,37,24,572,16,726,77};
+ test_value_multi(37878, -3344,
+ 2873.3874, "92743.238984789898",
+ "string", 6, charset_list[0],
+ 2011, 3, 26,
+ 1, 23, 23, 20, 333,
+ 0, 2011, 3, 26, 23, 23, 53, 334,
+ column_numbers,
+ "zero data");
+ }
+ test_value_multi_same_num();
+ {
+ uint column_numbers[]= {1,2,3,4,5,6,7,2, 3, 4};
+ uint column_values[]= {1,2,3,4,5,6,7,0,30,40};
+ my_bool null_values[]= {0,0,0,0,0,0,0,1, 0, 0};
+
+ test_update_multi(column_numbers, column_values, null_values, 7, 10);
+ }
+ {
+ uint column_numbers[]= {4,3,2,1, 1,2,3,4};
+ uint column_values[]= {4,3,2,1, 0,0,0,0};
+ my_bool null_values[]= {0,0,0,0, 1,1,1,1};
+
+ test_update_multi(column_numbers, column_values, null_values, 4, 8);
+ }
+ {
+ uint column_numbers[]= {4,3,2,1, 4,3,2,1};
+ uint column_values[]= {4,3,2,1, 0,0,0,0};
+ my_bool null_values[]= {0,0,0,0, 1,1,1,1};
+
+ test_update_multi(column_numbers, column_values, null_values, 4, 8);
+ }
+ test_empty_string();
+ {
+ uint column_numbers[]= {1, 2, 3};
+ uint column_values[]= {1, 2, 3};
+ uint update_numbers[]= {4, 3, 2, 1};
+ uint update_values[]= {40,30, 0,10};
+ my_bool update_nulls[]={0, 0, 1, 0};
+ uint result_numbers[]= {1, 3, 4};
+ uint result_values[]= {10,30,40};
+ test_update_many(column_numbers, column_values, 3,
+ update_numbers, update_values, update_nulls, 4,
+ result_numbers, result_values, 3);
+ }
+ return 0;
+}
=== modified file 'include/decimal.h'
--- include/decimal.h 2007-05-24 10:24:36 +0000
+++ include/decimal.h 2011-04-29 09:52:28 +0000
@@ -29,17 +29,17 @@
int internal_str2dec(const char *from, decimal_t *to, char **end,
my_bool fixed);
-int decimal2string(decimal_t *from, char *to, int *to_len,
+int decimal2string(const decimal_t *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler);
-int decimal2ulonglong(decimal_t *from, ulonglong *to);
-int ulonglong2decimal(ulonglong from, decimal_t *to);
-int decimal2longlong(decimal_t *from, longlong *to);
+int decimal2ulonglong(const decimal_t *from, ulonglong *to);
+int ulonglong2decimal(const ulonglong from, decimal_t *to);
+int decimal2longlong(const decimal_t *from, longlong *to);
int longlong2decimal(longlong from, decimal_t *to);
-int decimal2double(decimal_t *from, double *to);
+int decimal2double(const decimal_t *from, double *to);
int double2decimal(double from, decimal_t *to);
int decimal_actual_fraction(decimal_t *from);
-int decimal2bin(decimal_t *from, uchar *to, int precision, int scale);
+int decimal2bin(const decimal_t *from, uchar *to, int precision, int scale);
int bin2decimal(const uchar *from, decimal_t *to, int precision, int scale);
int decimal_size(int precision, int scale);
@@ -55,7 +55,7 @@
int decimal_div(decimal_t *from1, decimal_t *from2, decimal_t *to,
int scale_incr);
int decimal_mod(decimal_t *from1, decimal_t *from2, decimal_t *to);
-int decimal_round(decimal_t *from, decimal_t *to, int new_scale,
+int decimal_round(const decimal_t *from, decimal_t *to, int new_scale,
decimal_round_mode mode);
int decimal_is_zero(decimal_t *from);
void max_decimal(int precision, int frac, decimal_t *to);
=== added file 'include/ma_dyncol.h'
--- include/ma_dyncol.h 1970-01-01 00:00:00 +0000
+++ include/ma_dyncol.h 2011-04-29 09:52:28 +0000
@@ -0,0 +1,101 @@
+#ifndef ma_dyncol_h
+#define ma_dyncol_h
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.h>
+#include <decimal.h>
+#include <my_decimal_limits.h>
+#include <mysql_time.h>
+
+#define ER_DYNCOL_YES 1
+/* NO and OK is the same used just to show semantics */
+#define ER_DYNCOL_NO 0
+#define ER_DYNCOL_OK 0
+/* Wrong format of the string with encoded columns */
+#define ER_DYNCOL_FORMAT -1
+/* Some limit reached */
+#define ER_DYNCOL_LIMIT -2
+/* Out of resourses */
+#define ER_DYNCOL_RESOURCE -3
+/* Incorrect input data */
+#define ER_DYNCOL_DATA -4
+
+typedef DYNAMIC_STRING DYNAMIC_COLUMN;
+
+enum enum_dynamic_column_type
+{
+ DYN_COL_NULL= 0,
+ DYN_COL_INT,
+ DYN_COL_UINT,
+ DYN_COL_DOUBLE,
+ DYN_COL_STRING,
+ DYN_COL_DECIMAL,
+ DYN_COL_DATETIME,
+ DYN_COL_DATE,
+ DYN_COL_TIME
+};
+
+typedef enum enum_dynamic_column_type DYNAMIC_COLUMN_TYPE;
+
+struct st_dynamic_column_value
+{
+ DYNAMIC_COLUMN_TYPE type;
+ union
+ {
+ long long long_value;
+ unsigned long long ulong_value;
+ double double_value;
+ struct {
+ LEX_STRING string_value;
+ CHARSET_INFO *charset;
+ };
+ struct {
+ decimal_digit_t decimal_buffer[DECIMAL_BUFF_LENGTH];
+ decimal_t decimal_value;
+ };
+ MYSQL_TIME time_value;
+ };
+};
+
+typedef struct st_dynamic_column_value DYNAMIC_COLUMN_VALUE;
+
+int dynamic_column_create(DYNAMIC_COLUMN *str,
+ uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value);
+
+int dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+
+int dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value);
+int dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values);
+
+int dynamic_column_delete(DYNAMIC_COLUMN *org, uint column_nr);
+
+int dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
+
+/* List of not NULL columns */
+int dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
+
+/*
+ if the column do not exists it is NULL
+*/
+int dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here);
+
+#define dynamic_column_column_free(V) dynstr_free(V)
+
+#define dynamic_column_value_init(V) (V)->type= DYN_COL_NULL
+
+/*
+ Prepare value for using as decimal
+*/
+void dynamic_column_prepare_decimal(DYNAMIC_COLUMN_VALUE *value);
+
+#endif
=== added file 'include/my_decimal_limits.h'
--- include/my_decimal_limits.h 1970-01-01 00:00:00 +0000
+++ include/my_decimal_limits.h 2011-04-29 09:52:28 +0000
@@ -0,0 +1,31 @@
+#ifndef my_decimal_limits_h
+#define my_decimal_limits_h
+
+#define DECIMAL_LONGLONG_DIGITS 22
+#define DECIMAL_LONG_DIGITS 10
+#define DECIMAL_LONG3_DIGITS 8
+
+/** maximum length of buffer in our big digits (uint32). */
+#define DECIMAL_BUFF_LENGTH 9
+
+/* the number of digits that my_decimal can possibly contain */
+#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
+
+
+/**
+ maximum guaranteed precision of number in decimal digits (number of our
+ digits * number of decimal digits in one our big digit - number of decimal
+ digits in one our big digit decreased by 1 (because we always put decimal
+ point on the border of our big digits))
+*/
+#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
+#define DECIMAL_MAX_SCALE 30
+#define DECIMAL_NOT_SPECIFIED 31
+
+/**
+ maximum length of string representation (number of maximum decimal
+ digits + 1 position for sign + 1 position for decimal point)
+*/
+#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
+
+#endif
=== modified file 'include/my_time.h'
--- include/my_time.h 2008-04-03 17:14:57 +0000
+++ include/my_time.h 2011-04-29 09:52:28 +0000
@@ -72,6 +72,7 @@
TIME_MAX_SECOND)
#define TIME_MAX_VALUE_SECONDS (TIME_MAX_HOUR * 3600L + \
TIME_MAX_MINUTE * 60L + TIME_MAX_SECOND)
+#define TIME_SUBSECOND_RANGE 1000000
my_bool check_date(const MYSQL_TIME *ltime, my_bool not_zero_date,
ulong flags, int *was_cut);
@@ -80,6 +81,8 @@
uint flags, int *was_cut);
longlong number_to_datetime(longlong nr, MYSQL_TIME *time_res,
uint flags, int *was_cut);
+my_bool double_to_datetime(double nr, MYSQL_TIME *time_res,
+ uint flags);
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *);
ulonglong TIME_to_ulonglong_date(const MYSQL_TIME *);
ulonglong TIME_to_ulonglong_time(const MYSQL_TIME *);
@@ -87,7 +90,7 @@
my_bool str_to_time(const char *str,uint length, MYSQL_TIME *l_time,
- int *warning);
+ ulong flag,int *warning);
int check_time_range(struct st_mysql_time *, int *warning);
=== modified file 'libmysql/libmysql.c'
--- libmysql/libmysql.c 2011-02-28 17:39:30 +0000
+++ libmysql/libmysql.c 2011-04-29 09:52:28 +0000
@@ -3549,7 +3549,7 @@
case MYSQL_TYPE_TIME:
{
MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
- str_to_time(value, length, tm, &err);
+ str_to_time(value, length, tm, TIME_FUZZY_DATE, &err);
*param->error= test(err);
break;
}
=== modified file 'mysql-test/r/bigint.result'
--- mysql-test/r/bigint.result 2010-02-25 19:13:11 +0000
+++ mysql-test/r/bigint.result 2011-04-29 10:51:42 +0000
@@ -362,12 +362,12 @@
cast(19999999999999999999 as signed)
9223372036854775807
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '19999999999999999999' to INT. Value truncated.
select cast(-19999999999999999999 as signed);
cast(-19999999999999999999 as signed)
-9223372036854775808
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-19999999999999999999' to INT. Value truncated.
select -9223372036854775808;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def -9223372036854775808 8 20 20 N 32897 0 63
=== modified file 'mysql-test/r/cast.result'
--- mysql-test/r/cast.result 2009-05-21 08:06:43 +0000
+++ mysql-test/r/cast.result 2011-04-29 09:52:28 +0000
@@ -1,9 +1,13 @@
select CAST(1-2 AS UNSIGNED);
CAST(1-2 AS UNSIGNED)
18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER);
CAST(CAST(1-2 AS UNSIGNED) AS SIGNED INTEGER)
-1
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select CAST('10 ' as unsigned integer);
CAST('10 ' as unsigned integer)
10
@@ -12,9 +16,15 @@
select cast(-5 as unsigned) | 1, cast(-5 as unsigned) & -1;
cast(-5 as unsigned) | 1 cast(-5 as unsigned) & -1
18446744073709551611 18446744073709551611
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select cast(-5 as unsigned) -1, cast(-5 as unsigned) + 1;
cast(-5 as unsigned) -1 cast(-5 as unsigned) + 1
18446744073709551610 18446744073709551612
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select ~5, cast(~5 as signed);
~5 cast(~5 as signed)
18446744073709551610 -6
@@ -29,6 +39,51 @@
select cast(NULL as signed), cast(1/0 as signed);
cast(NULL as signed) cast(1/0 as signed)
NULL NULL
+select cast(1 as double(5,2));
+cast(1 as double(5,2))
+1.00
+select cast("5.2222" as double(5,2));
+cast("5.2222" as double(5,2))
+5.22
+select cast(12.444 as double(5,2));
+cast(12.444 as double(5,2))
+12.44
+select cast(cast(12.444 as decimal(10,3)) as double(5,2));
+cast(cast(12.444 as decimal(10,3)) as double(5,2))
+12.44
+select cast(null as double(5,2));
+cast(null as double(5,2))
+NULL
+select cast(12.444 as double);
+cast(12.444 as double)
+12.444
+select cast(cast("20:01:01" as time) as datetime);
+cast(cast("20:01:01" as time) as datetime)
+0000-00-00 20:01:01
+select cast(cast("8:46:06.23434" AS time) as decimal(32,10));
+cast(cast("8:46:06.23434" AS time) as decimal(32,10))
+84606.2343400000
+select cast(cast(20010203101112.121314 as double) as datetime);
+cast(cast(20010203101112.121314 as double) as datetime)
+2001-02-03 10:11:12.125000
+select cast(cast(010203101112.12 as double) as datetime);
+cast(cast(010203101112.12 as double) as datetime)
+2001-02-03 10:11:12.120000
+select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime);
+cast(cast(20010203101112.121314 as decimal(32,6)) as datetime)
+2001-02-03 10:11:12.121314
+select cast(20010203101112.121314 as datetime);
+cast(20010203101112.121314 as datetime)
+2001-02-03 10:11:12.121314
+select cast(110203101112.121314 as datetime);
+cast(110203101112.121314 as datetime)
+2011-02-03 10:11:12.121314
+select cast(cast(010203101112.12 as double) as datetime);
+cast(cast(010203101112.12 as double) as datetime)
+2001-02-03 10:11:12.120000
+select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as time);
+cast(cast("2011-04-05 8:46:06.23434" AS datetime) as time)
+08:46:06.234340
select cast(NULL as unsigned), cast(1/0 as unsigned);
cast(NULL as unsigned) cast(1/0 as unsigned)
NULL NULL
@@ -111,6 +166,115 @@
10
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'a'
+select cast("a" as double(5,2));
+cast("a" as double(5,2))
+0.00
+Warnings:
+Warning 1292 Truncated incorrect DOUBLE value: 'a'
+select cast(1000 as decimal(5,2));
+cast(1000 as decimal(5,2))
+999.99
+Warnings:
+Error 1264 Out of range value for column 'cast(1000 as decimal(5,2))' at row 1
+select cast(-1000 as decimal(5,2));
+cast(-1000 as decimal(5,2))
+-999.99
+Warnings:
+Error 1264 Out of range value for column 'cast(-1000 as decimal(5,2))' at row 1
+select cast(1000 as double(5,2));
+cast(1000 as double(5,2))
+999.99
+Warnings:
+Warning 1264 Out of range value for column 'cast(1000 as double(5,2))' at row 1
+select cast(-1000 as double(5,2));
+cast(-1000 as double(5,2))
+-999.99
+Warnings:
+Warning 1264 Out of range value for column 'cast(-1000 as double(5,2))' at row 1
+select cast(010203101112.121314 as datetime);
+cast(010203101112.121314 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '10203101112.121314'
+select cast(120010203101112.121314 as datetime);
+cast(120010203101112.121314 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '120010203101112.121314'
+select cast(cast(1.1 as decimal) as datetime);
+cast(cast(1.1 as decimal) as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '1'
+select cast(cast(-1.1 as decimal) as datetime);
+cast(cast(-1.1 as decimal) as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '-1'
+select cast('0' as date);
+cast('0' as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '0'
+select cast('' as date);
+cast('' as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: ''
+select cast('0' as datetime);
+cast('0' as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '0'
+select cast('' as datetime);
+cast('' as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: ''
+select cast('0' as time);
+cast('0' as time)
+00:00:00
+select cast('' as time);
+cast('' as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: ''
+select cast(NULL as DATE);
+cast(NULL as DATE)
+NULL
+select cast(NULL as DATETIME);
+cast(NULL as DATETIME)
+NULL
+select cast(NULL as TIME);
+cast(NULL as TIME)
+NULL
+select cast(NULL as BINARY);
+cast(NULL as BINARY)
+NULL
+select cast(cast(120010203101112.121314 as double) as datetime);
+cast(cast(120010203101112.121314 as double) as datetime)
+NULL
+select cast(cast(1.1 as double) as datetime);
+cast(cast(1.1 as double) as datetime)
+NULL
+select cast(cast(-1.1 as double) as datetime);
+cast(cast(-1.1 as double) as datetime)
+NULL
+explain extended select cast(10 as double(5,2));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(10 as double(5,2)) AS `cast(10 as double(5,2))`
+explain extended select cast(10 as double);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(10 as double) AS `cast(10 as double)`
+explain extended select cast(10 as decimal(5,2));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(10 as decimal(5,2)) AS `cast(10 as decimal(5,2))`
select cast('18446744073709551616' as unsigned);
cast('18446744073709551616' as unsigned)
18446744073709551615
@@ -146,6 +310,18 @@
0
Warnings:
Warning 1292 Truncated incorrect INTEGER value: ''
+select cast(1 as double(5,6));
+ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '').
+select cast(1 as decimal(5,6));
+ERROR 42000: For float(M,D), double(M,D) or decimal(M,D), M must be >= D (column '').
+select cast(1 as double(66,6));
+ERROR 42000: Too big precision 66 specified for column '1'. Maximum is 65.
+select cast(1 as decimal(66,6));
+ERROR 42000: Too big precision 66 specified for column '1'. Maximum is 65.
+select cast(1 as decimal(64,63));
+ERROR 42000: Too big scale 63 specified for column '1'. Maximum is 30.
+select cast(1 as double(64,63));
+ERROR 42000: Too big scale 63 specified for column '1'. Maximum is 30.
set names binary;
select cast(_latin1'test' as char character set latin2);
cast(_latin1'test' as char character set latin2)
@@ -255,12 +431,6 @@
select cast("1:2:3" as TIME) = "1:02:03";
cast("1:2:3" as TIME) = "1:02:03"
0
-select cast(NULL as DATE);
-cast(NULL as DATE)
-NULL
-select cast(NULL as BINARY);
-cast(NULL as BINARY)
-NULL
CREATE TABLE t1 (a enum ('aac','aab','aaa') not null);
INSERT INTO t1 VALUES ('aaa'),('aab'),('aac');
SELECT a, CAST(a AS CHAR) FROM t1 ORDER BY CAST(a AS UNSIGNED) ;
@@ -337,6 +507,21 @@
select cast(1.0e+300 as signed int);
cast(1.0e+300 as signed int)
9223372036854775807
+create table t1 select cast(1 as unsigned), cast(1 as signed), cast(1 as double(5,2)), cast(1 as decimal(5,3)), cast("A" as binary), cast("A" as char(100)), cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME), cast("1:2:3" as TIME);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `cast(1 as unsigned)` int(1) unsigned NOT NULL DEFAULT '0',
+ `cast(1 as signed)` int(1) NOT NULL DEFAULT '0',
+ `cast(1 as double(5,2))` double(5,2) DEFAULT NULL,
+ `cast(1 as decimal(5,3))` decimal(5,3) NOT NULL DEFAULT '0.000',
+ `cast("A" as binary)` varbinary(1) NOT NULL DEFAULT '',
+ `cast("A" as char(100))` varbinary(100) NOT NULL DEFAULT '',
+ `cast("2001-1-1" as DATE)` date DEFAULT NULL,
+ `cast("2001-1-1" as DATETIME)` datetime DEFAULT NULL,
+ `cast("1:2:3" as TIME)` time DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
CREATE TABLE t1 (f1 double);
INSERT INTO t1 SET f1 = -1.0e+30 ;
INSERT INTO t1 SET f1 = +1.0e+30 ;
=== added file 'mysql-test/r/dyncol.result'
--- mysql-test/r/dyncol.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/dyncol.result 2011-04-29 11:07:51 +0000
@@ -0,0 +1,1012 @@
+#
+# column create
+#
+select hex(COLUMN_CREATE(1, NULL AS char character set utf8));
+hex(COLUMN_CREATE(1, NULL AS char character set utf8))
+000000
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8));
+hex(COLUMN_CREATE(1, "afaf" AS char character set utf8))
+0001000100030861666166
+select hex(COLUMN_CREATE(1, 1212 AS char character set utf8));
+hex(COLUMN_CREATE(1, 1212 AS char character set utf8))
+0001000100033F31323132
+select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8));
+hex(COLUMN_CREATE(1, 12.12 AS char character set utf8))
+0001000100033F31322E3132
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8));
+hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8))
+0001000100033F3939393939393939393939393939393939393939393939393939393939
+select hex(COLUMN_CREATE(1, NULL AS unsigned int));
+hex(COLUMN_CREATE(1, NULL AS unsigned int))
+000000
+select hex(COLUMN_CREATE(1, 1212 AS unsigned int));
+hex(COLUMN_CREATE(1, 1212 AS unsigned int))
+000100010001BC04
+select hex(COLUMN_CREATE(1, 7 AS unsigned int));
+hex(COLUMN_CREATE(1, 7 AS unsigned int))
+00010001000107
+select hex(COLUMN_CREATE(1, 8 AS unsigned int));
+hex(COLUMN_CREATE(1, 8 AS unsigned int))
+00010001000108
+select hex(COLUMN_CREATE(1, 127 AS unsigned int));
+hex(COLUMN_CREATE(1, 127 AS unsigned int))
+0001000100017F
+select hex(COLUMN_CREATE(1, 128 AS unsigned int));
+hex(COLUMN_CREATE(1, 128 AS unsigned int))
+00010001000180
+select hex(COLUMN_CREATE(1, 12.12 AS unsigned int));
+hex(COLUMN_CREATE(1, 12.12 AS unsigned int))
+0001000100010C
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int));
+hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int))
+000100010001FFFFFFFFFFFFFF7F
+Warnings:
+Error 1655 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated.
+select hex(COLUMN_CREATE(1, NULL AS int));
+hex(COLUMN_CREATE(1, NULL AS int))
+000000
+select hex(COLUMN_CREATE(1, 1212 AS int));
+hex(COLUMN_CREATE(1, 1212 AS int))
+0001000100007809
+select hex(COLUMN_CREATE(1, 7 AS int));
+hex(COLUMN_CREATE(1, 7 AS int))
+0001000100000E
+select hex(COLUMN_CREATE(1, 8 AS int));
+hex(COLUMN_CREATE(1, 8 AS int))
+00010001000010
+select hex(COLUMN_CREATE(1, 127 AS int));
+hex(COLUMN_CREATE(1, 127 AS int))
+000100010000FE
+select hex(COLUMN_CREATE(1, 128 AS int));
+hex(COLUMN_CREATE(1, 128 AS int))
+0001000100000001
+select hex(COLUMN_CREATE(1, 12.12 AS int));
+hex(COLUMN_CREATE(1, 12.12 AS int))
+00010001000018
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int));
+hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int))
+000100010000FEFFFFFFFFFFFFFF
+Warnings:
+Error 1655 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated.
+select hex(COLUMN_CREATE(1, NULL AS double));
+hex(COLUMN_CREATE(1, NULL AS double))
+000000
+select hex(COLUMN_CREATE(1, 1212 AS double));
+hex(COLUMN_CREATE(1, 1212 AS double))
+0001000100020000000000F09240
+select hex(COLUMN_CREATE(1, 12.12 AS double));
+hex(COLUMN_CREATE(1, 12.12 AS double))
+0001000100023D0AD7A3703D2840
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double));
+hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double))
+00010001000221D7E6FAE031F445
+select hex(COLUMN_CREATE(1, NULL AS decimal));
+hex(COLUMN_CREATE(1, NULL AS decimal))
+000000
+select hex(COLUMN_CREATE(1, 1212 AS decimal));
+hex(COLUMN_CREATE(1, 1212 AS decimal))
+0001000100040900800004BC
+select hex(COLUMN_CREATE(1, 7 AS decimal));
+hex(COLUMN_CREATE(1, 7 AS decimal))
+000100010004090080000007
+select hex(COLUMN_CREATE(1, 8 AS decimal));
+hex(COLUMN_CREATE(1, 8 AS decimal))
+000100010004090080000008
+select hex(COLUMN_CREATE(1, 127 AS decimal));
+hex(COLUMN_CREATE(1, 127 AS decimal))
+00010001000409008000007F
+select hex(COLUMN_CREATE(1, 128 AS decimal));
+hex(COLUMN_CREATE(1, 128 AS decimal))
+000100010004090080000080
+select hex(COLUMN_CREATE(1, 12.12 AS decimal));
+hex(COLUMN_CREATE(1, 12.12 AS decimal))
+00010001000402028C0C
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal));
+hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal))
+0001000100041D00E33B9AC9FF3B9AC9FF3B9AC9FF
+select hex(COLUMN_CREATE(1, NULL AS date));
+hex(COLUMN_CREATE(1, NULL AS date))
+000000
+select hex(COLUMN_CREATE(1, "2011-04-05" AS date));
+hex(COLUMN_CREATE(1, "2011-04-05" AS date))
+00010001000685B60F
+select hex(COLUMN_CREATE(1, NULL AS time));
+hex(COLUMN_CREATE(1, NULL AS time))
+000000
+select hex(COLUMN_CREATE(1, "0:45:49.000001" AS time));
+hex(COLUMN_CREATE(1, "0:45:49.000001" AS time))
+000100010007010010B70000
+select hex(COLUMN_CREATE(1, NULL AS datetime));
+hex(COLUMN_CREATE(1, NULL AS datetime))
+000000
+select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime));
+hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime))
+00010001000585B60F010010B70000
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+2, 1212 AS unsigned int,
+3, 1212 AS int,
+4, 12.12 AS double,
+4+1, 12.12 AS decimal,
+6, "2011-04-05" AS date,
+7, "- 0:45:49.000001" AS time,
+8, "2011-04-05 0:45:49.000001" AS datetime));
+hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+2, 1212 AS unsigned int,
+3, 1212 AS int,
+4, 12.12 AS double,
+4+1, 12.12 AS decimal,
+6, "2011-04-05" AS date,
+7, "- 0:45:49.000001" AS time,
+8, "2011-04-05 0:45:49.000001" AS datetime))
+01080001000300020029000300380004004A0005008C000600AE000700C7000800F5000861666166BC0478093D0AD7A3703D284002028C0C85B60F010010B7000485B60F010010B70000
+explain extended
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+2, 1212 AS unsigned int,
+3, 1212 AS int,
+4, 12.12 AS double,
+4+1, 12.12 AS decimal,
+6, "2011-04-05" AS date,
+7, "- 0:45:49.000001" AS time,
+8, "2011-04-05 0:45:49.000001" AS datetime));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select hex(column_create(1,'afaf' AS char charset utf8 ,2,1212 AS unsigned int,3,1212 AS int,4,12.12 AS double,(4 + 1),12.12 AS decimal,6,'2011-04-05' AS date,7,'- 0:45:49.000001' AS time,8,'2011-04-05 0:45:49.000001' AS datetime)) AS `hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+2, 1212 AS unsigned int,
+3, 1212 AS int,
+4, 12.12 AS double,
+4+1, 12.12 AS decimal,
+6, "2011-04-05" AS date,
+7, "- 0:45:49.000001" AS time,
+8, "2011-04-05 0:45:49.000001" AS datetime))`
+#
+# column get uint
+#
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int);
+column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int)
+1212
+explain extended
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212 AS unsigned int),1) as unsigned) AS `column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int)`
+explain extended
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212 AS unsigned int),1) as unsigned) AS `column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned)`
+select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int);
+column_get(column_create(1, 1212 AS decimal), 1 as unsigned int)
+1212
+select column_get(column_create(1, 1212 AS double), 1 as unsigned int);
+column_get(column_create(1, 1212 AS double), 1 as unsigned int)
+1212
+select column_get(column_create(1, 1212 AS int), 1 as unsigned int);
+column_get(column_create(1, 1212 AS int), 1 as unsigned int)
+1212
+select column_get(column_create(1, "1212" AS char), 1 as unsigned int);
+column_get(column_create(1, "1212" AS char), 1 as unsigned int)
+1212
+select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int);
+column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int)
+20110405
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int);
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int)
+84606
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int)
+20110405084606
+select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int);
+column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int)
+NULL
+# column geint truncation & warnings
+select column_get(column_create(1, -1212 AS int), 1 as unsigned int);
+column_get(column_create(1, -1212 AS int), 1 as unsigned int)
+18446744073709550404
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int)
+18446744073709551615
+Warnings:
+Error 1655 Got overflow when converting '99999999999999999999999999999' to UNSIGNED INT. Value truncated.
+select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int);
+column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int)
+1000
+select column_get(column_create(1, -1 AS decimal), 1 as unsigned int);
+column_get(column_create(1, -1 AS decimal), 1 as unsigned int)
+0
+Warnings:
+Error 1655 Got overflow when converting '-1' to UNSIGNED INT. Value truncated.
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int);
+column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int)
+18446744073709551615
+Warnings:
+Warning 1655 Got overflow when converting '1e+29' to UNSIGNED INT. Value truncated.
+select column_get(column_create(1, 999.9 AS double), 1 as unsigned int);
+column_get(column_create(1, 999.9 AS double), 1 as unsigned int)
+1000
+select column_get(column_create(1, -1 AS double), 1 as unsigned int);
+column_get(column_create(1, -1 AS double), 1 as unsigned int)
+0
+Warnings:
+Warning 1655 Got overflow when converting '-1' to UNSIGNED INT. Value truncated.
+select column_get(column_create(1, "1212III" AS char), 1 as unsigned int);
+column_get(column_create(1, "1212III" AS char), 1 as unsigned int)
+1212
+Warnings:
+Warning 1657 Encountered illegal value '1212III' when converting to UNSIGNED INT
+#
+# column get int
+#
+select column_get(column_create(1, 1212 AS int), 1 as int);
+column_get(column_create(1, 1212 AS int), 1 as int)
+1212
+explain extended
+select column_get(column_create(1, 1212 AS int), 1 as int);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212 AS int),1) as signed) AS `column_get(column_create(1, 1212 AS int), 1 as int)`
+explain extended
+select column_get(column_create(1, 1212 AS int), 1 as signed int);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212 AS int),1) as signed) AS `column_get(column_create(1, 1212 AS int), 1 as signed int)`
+select column_get(column_create(1, -1212 AS int), 1 as int);
+column_get(column_create(1, -1212 AS int), 1 as int)
+-1212
+select column_get(column_create(1, 1212 AS decimal), 1 as int);
+column_get(column_create(1, 1212 AS decimal), 1 as int)
+1212
+select column_get(column_create(1, 1212 AS double), 1 as int);
+column_get(column_create(1, 1212 AS double), 1 as int)
+1212
+select column_get(column_create(1, 1212 AS unsigned int), 1 as int);
+column_get(column_create(1, 1212 AS unsigned int), 1 as int)
+1212
+select column_get(column_create(1, "1212" AS char), 1 as int);
+column_get(column_create(1, "1212" AS char), 1 as int)
+1212
+select column_get(column_create(1, "-1212" AS char), 1 as int);
+column_get(column_create(1, "-1212" AS char), 1 as int)
+-1212
+select column_get(column_create(1, "2011-04-05" AS date), 1 as int);
+column_get(column_create(1, "2011-04-05" AS date), 1 as int)
+20110405
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int);
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as int)
+84606
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as int);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as int)
+20110405084606
+select column_get(column_create(1, NULL AS int), 1 as int);
+column_get(column_create(1, NULL AS int), 1 as int)
+NULL
+#column gett truncation & warnings
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int)
+-1
+Warnings:
+Warning 1105 Cast to signed converted positive out-of-range integer to it's negative complement
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int)
+9223372036854775807
+Warnings:
+Error 1655 Got overflow when converting '99999999999999999999999999999' to INT. Value truncated.
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int);
+column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int)
+-9223372036854775808
+Warnings:
+Error 1655 Got overflow when converting '-99999999999999999999999999999' to INT. Value truncated.
+select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int);
+column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int)
+1000
+select column_get(column_create(1, 999.9 AS double), 1 as int);
+column_get(column_create(1, 999.9 AS double), 1 as int)
+1000
+select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int);
+column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int)
+-9223372036854775808
+Warnings:
+Warning 1655 Got overflow when converting '-1e+29' to INT. Value truncated.
+select column_get(column_create(1, "-1212III" AS char), 1 as int);
+column_get(column_create(1, "-1212III" AS char), 1 as int)
+-1212
+Warnings:
+Warning 1657 Encountered illegal value '-1212III' when converting to INT
+select column_get(column_create(1, "1212III" AS char), 1 as int);
+column_get(column_create(1, "1212III" AS char), 1 as int)
+1212
+Warnings:
+Warning 1657 Encountered illegal value '1212III' when converting to INT
+#
+#column get char
+#
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8);
+column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8)
+1212
+explain extended
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,'1212' AS char charset utf8 ),1) as char charset utf8) AS `column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8)`
+select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8);
+column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8)
+1212
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8)
+18446744073709551615
+select column_get(column_create(1, 1212 AS int), 1 as char charset utf8);
+column_get(column_create(1, 1212 AS int), 1 as char charset utf8)
+1212
+select column_get(column_create(1, -1212 AS int), 1 as char charset utf8);
+column_get(column_create(1, -1212 AS int), 1 as char charset utf8)
+-1212
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8)
+9223372036854775807
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8)
+-9223372036854775808
+select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8);
+column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8)
+1212.12
+select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8);
+column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8)
+1212.12
+select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8);
+column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8)
+2011-04-05
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8);
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8)
+08:46:06.234340
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8)
+2011-04-05 08:46:06.234340
+select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8);
+column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8)
+NULL
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary);
+column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary)
+1212
+explain extended
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,'1212' AS char charset utf8 ),1) as char charset binary) AS `column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary)`
+#
+# column get real
+#
+select column_get(column_create(1, 1212.12 AS double), 1 as double);
+column_get(column_create(1, 1212.12 AS double), 1 as double)
+1212.12
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as double);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212.12 AS double),1) as double) AS `column_get(column_create(1, 1212.12 AS double), 1 as double)`
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212.12 AS double),1) as double(6,2)) AS `column_get(column_create(1, 1212.12 AS double), 1 as double(6,2))`
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double)
+1.84467440737096e+19
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as double);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as double)
+9.22337203685478e+18
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as double);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as double)
+-9.22337203685478e+18
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double)
+1e+29
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double);
+column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double)
+-1e+29
+select column_get(column_create(1, "2011-04-05" AS date), 1 as double);
+column_get(column_create(1, "2011-04-05" AS date), 1 as double)
+20110405
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double);
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as double)
+84606.23434
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double)
+20110405084606.2
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6));
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6))
+20110405084606.234375
+select column_get(column_create(1, NULL AS double), 1 as double);
+column_get(column_create(1, NULL AS double), 1 as double)
+NULL
+# column get real truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as double);
+column_get(column_create(1, "1223.5aa" AS char), 1 as double)
+1223.5
+Warnings:
+Warning 1657 Encountered illegal value '1223.5aa' when converting to DOUBLE
+select column_get(column_create(1, "aa" AS char), 1 as double);
+column_get(column_create(1, "aa" AS char), 1 as double)
+0
+Warnings:
+Warning 1657 Encountered illegal value 'aa' when converting to DOUBLE
+select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2));
+column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))
+999.99
+Warnings:
+Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2))' at row 1
+select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2));
+column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))
+9.99
+Warnings:
+Warning 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2))' at row 1
+#
+# column get decimal
+#
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal);
+column_get(column_create(1, 1212.12 AS double), 1 as decimal)
+1212
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2));
+column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2))
+1212.12
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal);
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212.12 AS double),1) as decimal(10,0)) AS `column_get(column_create(1, 1212.12 AS double), 1 as decimal)`
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used
+Warnings:
+Note 1003 select cast(column_get(column_create(1,1212.12 AS double),1) as decimal(6,2)) AS `column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2))`
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0));
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0))
+18446744073709551615
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0));
+column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0))
+9223372036854775807
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0));
+column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0))
+-9223372036854775808
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10));
+column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10))
+-99999999999999999999999999999.0000000000
+select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6));
+column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6))
+20110405.000000
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6));
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6))
+84606.234340
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal(32,6));
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal(32,6))
+20110405084606.230000
+select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10));
+column_get(column_create(1, NULL as decimal), 1 as decimal(32,10))
+NULL
+select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2));
+column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2))
+1223.56
+# column get decimal truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10));
+column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10))
+1223.5000000000
+Warnings:
+Warning 1657 Encountered illegal value '1223.5aa' when converting to DECIMAL
+select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10));
+column_get(column_create(1, "aa" AS char), 1 as decimal(32,10))
+0.0000000000
+Warnings:
+Warning 1657 Encountered illegal value 'aa' when converting to DECIMAL
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal)
+9999999999
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal)' at row 1
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal)
+9999999999
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal)' at row 1
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal)
+-9999999999
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal)' at row 1
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal)
+9999999999
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal)' at row 1
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal)
+9999999999
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal)' at row 1
+select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2));
+column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2))
+999.99
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2))' at row 1
+select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2));
+column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2))
+-999.99
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2))' at row 1
+select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2));
+column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2))
+9.99
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2))' at row 1
+select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2));
+column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2))
+9.99
+Warnings:
+Error 1264 Out of range value for column 'column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2))' at row 1
+#
+# column get datetime
+#
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime);
+column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime)
+2001-02-03 10:11:12.125000
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime);
+column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime)
+2001-02-03 10:11:12.121314
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime);
+column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime)
+2001-02-03 10:11:12
+select column_get(column_create(1, 20010203101112 as int), 1 as datetime);
+column_get(column_create(1, 20010203101112 as int), 1 as datetime)
+2001-02-03 10:11:12
+select column_get(column_create(1, "20010203101112" as char), 1 as datetime);
+column_get(column_create(1, "20010203101112" as char), 1 as datetime)
+2001-02-03 10:11:12
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime);
+column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime)
+2001-02-03 10:11:12
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime);
+column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime)
+2001-02-03 10:11:12.121314
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime);
+column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime)
+2001-02-03 10:11:12.121314
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime)
+2011-04-05 08:46:06.234340
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime)
+2011-00-00 08:46:06.234340
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime)
+2011-00-01 08:46:06.234340
+select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime);
+column_get(column_create(1, 20010203 as unsigned int), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, 20010203 as int), 1 as datetime);
+column_get(column_create(1, 20010203 as int), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, 20010203), 1 as datetime);
+column_get(column_create(1, 20010203), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, 20010203.0), 1 as datetime);
+column_get(column_create(1, 20010203.0), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, 20010203.0 as double), 1 as datetime);
+column_get(column_create(1, 20010203.0 as double), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, "2001-02-03"), 1 as datetime);
+column_get(column_create(1, "2001-02-03"), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, "20010203"), 1 as datetime);
+column_get(column_create(1, "20010203"), 1 as datetime)
+2001-02-03 00:00:00
+select column_get(column_create(1, 0), 1 as datetime);
+column_get(column_create(1, 0), 1 as datetime)
+0000-00-00 00:00:00
+select column_get(column_create(1, "2001021"), 1 as datetime);
+column_get(column_create(1, "2001021"), 1 as datetime)
+2020-01-02 01:00:00
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime);
+column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime)
+0000-00-00 08:46:06.234340
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime)
+2011-02-30 18:46:06.234340
+select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime);
+column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime)
+0000-00-00 00:00:00
+select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime)
+2001-00-02 00:00:00
+set @@sql_mode="";
+# column get datetime truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime);
+column_get(column_create(1, "1223.5aa" AS char), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '1223.5aa'
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '18446744073709551615' when converting to DATE or DATETIME
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '9223372036854775807' when converting to DATE or DATETIME
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '-9223372036854775808' when converting to DATE or DATETIME
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '99999999999999999999999999999'
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime);
+column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '9.99999999999999914332e+28 '
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434'
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-13-01 8:46:06.23434'
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime);
+column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-02-30 8:46:06.23434'
+select column_get(column_create(1, "20010231"), 1 as datetime);
+column_get(column_create(1, "20010231"), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '20010231'
+select column_get(column_create(1, "0" AS CHAR), 1 as datetime);
+column_get(column_create(1, "0" AS CHAR), 1 as datetime)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '0'
+#
+# column get date
+#
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as date);
+column_get(column_create(1, 20010203101112.121314 as double), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date);
+column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date);
+column_get(column_create(1, 20010203101112 as unsigned int), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203101112 as int), 1 as date);
+column_get(column_create(1, 20010203101112 as int), 1 as date)
+2001-02-03
+select column_get(column_create(1, "20010203101112" as char), 1 as date);
+column_get(column_create(1, "20010203101112" as char), 1 as date)
+2001-02-03
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date);
+column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date)
+2001-02-03
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date);
+column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date)
+2001-02-03
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date);
+column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date)
+2001-02-03
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date)
+2011-04-05
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date)
+2011-00-00
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date)
+2011-00-01
+select column_get(column_create(1, 20010203 as unsigned int), 1 as date);
+column_get(column_create(1, 20010203 as unsigned int), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203 as int), 1 as date);
+column_get(column_create(1, 20010203 as int), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203), 1 as date);
+column_get(column_create(1, 20010203), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203.0), 1 as date);
+column_get(column_create(1, 20010203.0), 1 as date)
+2001-02-03
+select column_get(column_create(1, 20010203.0 as double), 1 as date);
+column_get(column_create(1, 20010203.0 as double), 1 as date)
+2001-02-03
+select column_get(column_create(1, "2001-02-03"), 1 as date);
+column_get(column_create(1, "2001-02-03"), 1 as date)
+2001-02-03
+select column_get(column_create(1, "20010203"), 1 as date);
+column_get(column_create(1, "20010203"), 1 as date)
+2001-02-03
+select column_get(column_create(1, 0), 1 as date);
+column_get(column_create(1, 0), 1 as date)
+0000-00-00
+select column_get(column_create(1, "2001021"), 1 as date);
+column_get(column_create(1, "2001021"), 1 as date)
+2020-01-02
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date)
+2011-02-30
+select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date);
+column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date)
+0000-00-00
+select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date);
+column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date)
+2001-00-02
+set @@sql_mode="";
+# column get date truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as date);
+column_get(column_create(1, "1223.5aa" AS char), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '1223.5aa'
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '18446744073709551615' when converting to DATE or DATETIME
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as date);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as date)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '9223372036854775807' when converting to DATE or DATETIME
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as date);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as date)
+NULL
+Warnings:
+Warning 1657 Encountered illegal value '-9223372036854775808' when converting to DATE or DATETIME
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '99999999999999999999999999999'
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date);
+column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect datetime value: '9.99999999999999914332e+28 '
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-02-32 8:46:06.23434'
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-13-01 8:46:06.23434'
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date);
+column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '2011-02-30 8:46:06.23434'
+select column_get(column_create(1, "20010231"), 1 as date);
+column_get(column_create(1, "20010231"), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '20010231'
+select column_get(column_create(1, "0" AS CHAR), 1 as date);
+column_get(column_create(1, "0" AS CHAR), 1 as date)
+NULL
+Warnings:
+Warning 1292 Incorrect datetime value: '0'
+#
+# column get time
+#
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as time);
+column_get(column_create(1, 20010203101112.121314 as double), 1 as time)
+10:11:12.100000
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time);
+column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time)
+10:11:12.121314
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time);
+column_get(column_create(1, 20010203101112 as unsigned int), 1 as time)
+10:11:12
+select column_get(column_create(1, 20010203101112 as int), 1 as time);
+column_get(column_create(1, 20010203101112 as int), 1 as time)
+10:11:12
+select column_get(column_create(1, "20010203101112" as char), 1 as time);
+column_get(column_create(1, "20010203101112" as char), 1 as time)
+10:11:12
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time);
+column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time)
+10:11:12
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time);
+column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time)
+10:11:12.121314
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time);
+column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time)
+10:11:12.121314
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time);
+column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time)
+08:46:06.234340
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time)
+08:46:06.234340
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time)
+08:46:06.234340
+select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time)
+830:46:06.234340
+select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time)
+-830:46:06.234340
+select column_get(column_create(1, "0" AS CHAR), 1 as time);
+column_get(column_create(1, "0" AS CHAR), 1 as time)
+00:00:00
+select column_get(column_create(1, "6" AS CHAR), 1 as time);
+column_get(column_create(1, "6" AS CHAR), 1 as time)
+00:00:06
+select column_get(column_create(1, "1:6" AS CHAR), 1 as time);
+column_get(column_create(1, "1:6" AS CHAR), 1 as time)
+01:06:00
+select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time);
+column_get(column_create(1, "2:1:6" AS CHAR), 1 as time)
+02:01:06
+select column_get(column_create(1, 0), 1 as time);
+column_get(column_create(1, 0), 1 as time)
+00:00:00
+select column_get(column_create(1, "2001021"), 1 as time);
+column_get(column_create(1, "2001021"), 1 as time)
+200:10:21
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time)
+18:46:06.234340
+set @@sql_mode="";
+# column get date truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as time);
+column_get(column_create(1, "1223.5aa" AS char), 1 as time)
+00:12:23.500000
+Warnings:
+Warning 1292 Truncated incorrect time value: '1223.5aa'
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time);
+column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '18446744073709551615'
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as time);
+column_get(column_create(1, 9223372036854775807 AS int), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '9223372036854775807'
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as time);
+column_get(column_create(1, -9223372036854775808 AS int), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '-9223372036854775808'
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time);
+column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '99999999999999999999999999999'
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time);
+column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '1e+29'
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '2011-02-32 8:46:06.23434'
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '2011-13-01 8:46:06.23434'
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time);
+column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time)
+NULL
+Warnings:
+Warning 1292 Truncated incorrect time value: '2011-02-30 8:46:06.23434'
+select column_get(column_create(1, "2001-02-03"), 1 as time);
+column_get(column_create(1, "2001-02-03"), 1 as time)
+00:20:01
+Warnings:
+Warning 1292 Truncated incorrect time value: '2001-02-03'
+select column_get(column_create(1, "20010203"), 1 as time);
+column_get(column_create(1, "20010203"), 1 as time)
+838:59:59
+Warnings:
+Warning 1292 Truncated incorrect time value: '20010203'
+# column add
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer))
+00020001000002001078097809
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer))
+0001000100007809
+select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer))
+000000
+select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer))
+0001000100007809
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer))
+000200010000020008167809
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer);
+column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer)
+11
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer);
+column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer)
+1212
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer))
+000200010000020010780916
+select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer));
+hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer))
+000200010000020010780916
+select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer));
+hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer))
+000200010000020008167809
+# column delete
+select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1));
+hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1))
+0001000200007809
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2))
+0002000100000300080206
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3))
+0002000100000200080204
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4))
+000300010000020008030010020406
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1))
+00010003000006
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3))
+00010001000002
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3))
+000000
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10));
+hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10))
+000000
+# column exists
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1);
+column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1)
+1
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4);
+column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4)
+0
+# column list
+select column_list(column_create(1, 1212 as integer, 2, 1212 as integer));
+column_list(column_create(1, 1212 as integer, 2, 1212 as integer))
+1,2
+select column_list(column_create(1, 1212 as integer));
+column_list(column_create(1, 1212 as integer))
+1
+select column_list(column_create(1, NULL as integer));
+column_list(column_create(1, NULL as integer))
+
=== modified file 'mysql-test/r/func_math.result'
--- mysql-test/r/func_math.result 2010-12-24 11:05:04 +0000
+++ mysql-test/r/func_math.result 2011-04-29 10:51:37 +0000
@@ -285,33 +285,55 @@
select cast(-2 as unsigned), 18446744073709551614, -2;
cast(-2 as unsigned) 18446744073709551614 -2
18446744073709551614 18446744073709551614 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select abs(cast(-2 as unsigned)), abs(18446744073709551614), abs(-2);
abs(cast(-2 as unsigned)) abs(18446744073709551614) abs(-2)
18446744073709551614 18446744073709551614 2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select ceiling(cast(-2 as unsigned)), ceiling(18446744073709551614), ceiling(-2);
ceiling(cast(-2 as unsigned)) ceiling(18446744073709551614) ceiling(-2)
18446744073709551614 18446744073709551614 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select floor(cast(-2 as unsigned)), floor(18446744073709551614), floor(-2);
floor(cast(-2 as unsigned)) floor(18446744073709551614) floor(-2)
18446744073709551614 18446744073709551614 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select format(cast(-2 as unsigned), 2), format(18446744073709551614, 2), format(-2, 2);
format(cast(-2 as unsigned), 2) format(18446744073709551614, 2) format(-2, 2)
18,446,744,073,709,551,614.00 18,446,744,073,709,551,614.00 -2.00
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select sqrt(cast(-2 as unsigned)), sqrt(18446744073709551614), sqrt(-2);
sqrt(cast(-2 as unsigned)) sqrt(18446744073709551614) sqrt(-2)
4294967296 4294967296 NULL
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select round(cast(-2 as unsigned), 1), round(18446744073709551614, 1), round(-2, 1);
round(cast(-2 as unsigned), 1) round(18446744073709551614, 1) round(-2, 1)
18446744073709551614 18446744073709551614 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select round(4, cast(-2 as unsigned)), round(4, 18446744073709551614), round(4, -2);
round(4, cast(-2 as unsigned)) round(4, 18446744073709551614) round(4, -2)
4 4 0
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select truncate(cast(-2 as unsigned), 1), truncate(18446744073709551614, 1), truncate(-2, 1);
truncate(cast(-2 as unsigned), 1) truncate(18446744073709551614, 1) truncate(-2, 1)
18446744073709551614 18446744073709551614 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select truncate(4, cast(-2 as unsigned)), truncate(4, 18446744073709551614), truncate(4, -2);
truncate(4, cast(-2 as unsigned)) truncate(4, 18446744073709551614) truncate(4, -2)
4 4 0
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select round(10000000000000000000, -19), truncate(10000000000000000000, -19);
round(10000000000000000000, -19) truncate(10000000000000000000, -19)
10000000000000000000 10000000000000000000
@@ -363,12 +385,18 @@
select mod(cast(-2 as unsigned), 3), mod(18446744073709551614, 3), mod(-2, 3);
mod(cast(-2 as unsigned), 3) mod(18446744073709551614, 3) mod(-2, 3)
2 2 -2
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select mod(5, cast(-2 as unsigned)), mod(5, 18446744073709551614), mod(5, -2);
mod(5, cast(-2 as unsigned)) mod(5, 18446744073709551614) mod(5, -2)
5 5 1
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select pow(cast(-2 as unsigned), 5), pow(18446744073709551614, 5), pow(-2, 5);
pow(cast(-2 as unsigned), 5) pow(18446744073709551614, 5) pow(-2, 5)
2.13598703592091e+96 2.13598703592091e+96 -32
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
CREATE TABLE t1 (a timestamp, b varchar(20), c bit(1));
INSERT INTO t1 VALUES('1998-09-23', 'str1', 1), ('2003-03-25', 'str2', 0);
SELECT a DIV 900 y FROM t1 GROUP BY y;
@@ -488,7 +516,7 @@
-9999999999999999991 DIV -1
-9223372036854775808
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-9999999999999999991' to INT. Value truncated.
SELECT -9223372036854775808 DIV -1;
-9223372036854775808 DIV -1
-9223372036854775808
=== modified file 'mysql-test/r/func_str.result'
--- mysql-test/r/func_str.result 2011-03-09 13:47:59 +0000
+++ mysql-test/r/func_str.result 2011-04-29 11:17:50 +0000
@@ -1533,7 +1533,7 @@
locate('lo','hello',-18446744073709551615)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select locate('lo','hello',18446744073709551615);
locate('lo','hello',18446744073709551615)
0
@@ -1541,22 +1541,22 @@
locate('lo','hello',-18446744073709551616)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select locate('lo','hello',18446744073709551616);
locate('lo','hello',18446744073709551616)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select locate('lo','hello',-18446744073709551617);
locate('lo','hello',-18446744073709551617)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select locate('lo','hello',18446744073709551617);
locate('lo','hello',18446744073709551617)
0
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select left('hello', 10);
left('hello', 10)
hello
@@ -1588,8 +1588,8 @@
left('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select left('hello', 18446744073709551615);
left('hello', 18446744073709551615)
hello
@@ -1597,26 +1597,26 @@
left('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select left('hello', 18446744073709551616);
left('hello', 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select left('hello', -18446744073709551617);
left('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select left('hello', 18446744073709551617);
left('hello', 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select right('hello', 10);
right('hello', 10)
hello
@@ -1648,8 +1648,8 @@
right('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select right('hello', 18446744073709551615);
right('hello', 18446744073709551615)
hello
@@ -1657,26 +1657,26 @@
right('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select right('hello', 18446744073709551616);
right('hello', 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select right('hello', -18446744073709551617);
right('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select right('hello', 18446744073709551617);
right('hello', 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select substring('hello', 2, -1);
substring('hello', 2, -1)
@@ -1708,8 +1708,8 @@
substring('hello', -18446744073709551615, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select substring('hello', 18446744073709551615, 1);
substring('hello', 18446744073709551615, 1)
@@ -1717,26 +1717,26 @@
substring('hello', -18446744073709551616, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select substring('hello', 18446744073709551616, 1);
substring('hello', 18446744073709551616, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select substring('hello', -18446744073709551617, 1);
substring('hello', -18446744073709551617, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select substring('hello', 18446744073709551617, 1);
substring('hello', 18446744073709551617, 1)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select substring('hello', 1, -1);
substring('hello', 1, -1)
@@ -1762,8 +1762,8 @@
substring('hello', 1, -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select substring('hello', 1, 18446744073709551615);
substring('hello', 1, 18446744073709551615)
hello
@@ -1771,26 +1771,26 @@
substring('hello', 1, -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select substring('hello', 1, 18446744073709551616);
substring('hello', 1, 18446744073709551616)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select substring('hello', 1, -18446744073709551617);
substring('hello', 1, -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select substring('hello', 1, 18446744073709551617);
substring('hello', 1, 18446744073709551617)
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select substring('hello', -1, -1);
substring('hello', -1, -1)
@@ -1816,10 +1816,10 @@
substring('hello', -18446744073709551615, -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select substring('hello', 18446744073709551615, 18446744073709551615);
substring('hello', 18446744073709551615, 18446744073709551615)
@@ -1827,34 +1827,34 @@
substring('hello', -18446744073709551616, -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select substring('hello', 18446744073709551616, 18446744073709551616);
substring('hello', 18446744073709551616, 18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select substring('hello', -18446744073709551617, -18446744073709551617);
substring('hello', -18446744073709551617, -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select substring('hello', 18446744073709551617, 18446744073709551617);
substring('hello', 18446744073709551617, 18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select insert('hello', -1, 1, 'hi');
insert('hello', -1, 1, 'hi')
hello
@@ -1880,7 +1880,7 @@
insert('hello', -18446744073709551615, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select insert('hello', 18446744073709551615, 1, 'hi');
insert('hello', 18446744073709551615, 1, 'hi')
hello
@@ -1888,22 +1888,22 @@
insert('hello', -18446744073709551616, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select insert('hello', 18446744073709551616, 1, 'hi');
insert('hello', 18446744073709551616, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select insert('hello', -18446744073709551617, 1, 'hi');
insert('hello', -18446744073709551617, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select insert('hello', 18446744073709551617, 1, 'hi');
insert('hello', 18446744073709551617, 1, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select insert('hello', 1, -1, 'hi');
insert('hello', 1, -1, 'hi')
hi
@@ -1929,7 +1929,7 @@
insert('hello', 1, -18446744073709551615, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select insert('hello', 1, 18446744073709551615, 'hi');
insert('hello', 1, 18446744073709551615, 'hi')
hi
@@ -1937,22 +1937,22 @@
insert('hello', 1, -18446744073709551616, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select insert('hello', 1, 18446744073709551616, 'hi');
insert('hello', 1, 18446744073709551616, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select insert('hello', 1, -18446744073709551617, 'hi');
insert('hello', 1, -18446744073709551617, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select insert('hello', 1, 18446744073709551617, 'hi');
insert('hello', 1, 18446744073709551617, 'hi')
hi
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select insert('hello', -1, -1, 'hi');
insert('hello', -1, -1, 'hi')
hello
@@ -1978,8 +1978,8 @@
insert('hello', -18446744073709551615, -18446744073709551615, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select insert('hello', 18446744073709551615, 18446744073709551615, 'hi');
insert('hello', 18446744073709551615, 18446744073709551615, 'hi')
hello
@@ -1987,26 +1987,26 @@
insert('hello', -18446744073709551616, -18446744073709551616, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select insert('hello', 18446744073709551616, 18446744073709551616, 'hi');
insert('hello', 18446744073709551616, 18446744073709551616, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
select insert('hello', -18446744073709551617, -18446744073709551617, 'hi');
insert('hello', -18446744073709551617, -18446744073709551617, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select insert('hello', 18446744073709551617, 18446744073709551617, 'hi');
insert('hello', 18446744073709551617, 18446744073709551617, 'hi')
hello
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
select repeat('hello', -1);
repeat('hello', -1)
@@ -2038,8 +2038,8 @@
repeat('hello', -18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select repeat('hello', 18446744073709551615);
repeat('hello', 18446744073709551615)
NULL
@@ -2049,27 +2049,27 @@
repeat('hello', -18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select repeat('hello', 18446744073709551616);
repeat('hello', 18446744073709551616)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select repeat('hello', -18446744073709551617);
repeat('hello', -18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select repeat('hello', 18446744073709551617);
repeat('hello', 18446744073709551617)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select space(-1);
space(-1)
@@ -2102,8 +2102,8 @@
space(-18446744073709551615)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select space(18446744073709551615);
space(18446744073709551615)
NULL
@@ -2113,27 +2113,27 @@
space(-18446744073709551616)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select space(18446744073709551616);
space(18446744073709551616)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select space(-18446744073709551617);
space(-18446744073709551617)
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select space(18446744073709551617);
space(18446744073709551617)
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
Warning 1301 Result of repeat() was larger than max_allowed_packet (1048576) - truncated
select rpad('hello', -1, '1');
rpad('hello', -1, '1')
@@ -2166,8 +2166,8 @@
rpad('hello', -18446744073709551615, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select rpad('hello', 18446744073709551615, '1');
rpad('hello', 18446744073709551615, '1')
NULL
@@ -2177,27 +2177,27 @@
rpad('hello', -18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select rpad('hello', 18446744073709551616, '1');
rpad('hello', 18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
select rpad('hello', -18446744073709551617, '1');
rpad('hello', -18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select rpad('hello', 18446744073709551617, '1');
rpad('hello', 18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
Warning 1301 Result of rpad() was larger than max_allowed_packet (1048576) - truncated
select lpad('hello', -1, '1');
lpad('hello', -1, '1')
@@ -2230,8 +2230,8 @@
lpad('hello', -18446744073709551615, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551615' to INT. Value truncated.
select lpad('hello', 18446744073709551615, '1');
lpad('hello', 18446744073709551615, '1')
NULL
@@ -2241,27 +2241,27 @@
lpad('hello', -18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551616' to INT. Value truncated.
select lpad('hello', 18446744073709551616, '1');
lpad('hello', 18446744073709551616, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551616' to INT. Value truncated.
Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
select lpad('hello', -18446744073709551617, '1');
lpad('hello', -18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '-18446744073709551617' to INT. Value truncated.
select lpad('hello', 18446744073709551617, '1');
lpad('hello', 18446744073709551617, '1')
NULL
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
+Error 1655 Got overflow when converting '18446744073709551617' to INT. Value truncated.
Warning 1301 Result of lpad() was larger than max_allowed_packet (1048576) - truncated
SET @orig_sql_mode = @@SQL_MODE;
SET SQL_MODE=traditional;
=== modified file 'mysql-test/r/func_time.result'
--- mysql-test/r/func_time.result 2011-02-20 16:51:43 +0000
+++ mysql-test/r/func_time.result 2011-04-29 09:52:28 +0000
@@ -1014,6 +1014,7 @@
MAKETIME(CAST(-1 AS UNSIGNED), 0, 0)
838:59:59
Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
Warning 1292 Truncated incorrect time value: '18446744073709551615:00:00'
SELECT EXTRACT(HOUR FROM '100000:02:03');
EXTRACT(HOUR FROM '100000:02:03')
@@ -1033,6 +1034,7 @@
SEC_TO_TIME(CAST(-1 AS UNSIGNED))
838:59:59
Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
Warning 1292 Truncated incorrect time value: '18446744073709551615'
SET NAMES latin1;
SET character_set_results = NULL;
=== modified file 'mysql-test/r/sp-vars.result'
--- mysql-test/r/sp-vars.result 2007-05-18 12:29:24 +0000
+++ mysql-test/r/sp-vars.result 2011-04-29 09:52:28 +0000
@@ -380,7 +380,7 @@
SELECT sp_vars_check_ret2();
ERROR 22003: Out of range value for column 'sp_vars_check_ret2()' at row 1
SELECT sp_vars_check_ret3();
-ERROR HY000: Incorrect integer value: 'Hello, world' for column 'sp_vars_check_ret3()' at row 1
+ERROR 22007: Incorrect integer value: 'Hello, world' for column 'sp_vars_check_ret3()' at row 1
SELECT sp_vars_check_ret4();
sp_vars_check_ret4()
154.12
=== modified file 'mysql-test/r/strict.result'
--- mysql-test/r/strict.result 2009-06-11 16:21:32 +0000
+++ mysql-test/r/strict.result 2011-04-29 09:52:28 +0000
@@ -260,24 +260,24 @@
INSERT INTO t1 (col3) VALUES (CAST('2004-10-15 10:15' AS DATETIME));
INSERT INTO t1 (col1) VALUES(CAST('0000-10-31' AS DATE));
INSERT INTO t1 (col1) VALUES(CAST('2004-10-0' AS DATE));
-ERROR 22007: Incorrect date value: '2004-10-00' for column 'col1' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0'
INSERT INTO t1 (col1) VALUES(CAST('2004-0-10' AS DATE));
-ERROR 22007: Incorrect date value: '2004-00-10' for column 'col1' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10'
INSERT INTO t1 (col1) VALUES(CAST('0000-00-00' AS DATE));
ERROR 22007: Incorrect datetime value: '0000-00-00'
INSERT INTO t1 (col2) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
INSERT INTO t1 (col2) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col2' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30'
INSERT INTO t1 (col2) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col2' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10 15:30'
INSERT INTO t1 (col2) VALUES(CAST('0000-00-00' AS DATETIME));
ERROR 22007: Incorrect datetime value: '0000-00-00'
INSERT INTO t1 (col3) VALUES(CAST('0000-10-31 15:30' AS DATETIME));
ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col3' at row 1
INSERT INTO t1 (col3) VALUES(CAST('2004-10-0 15:30' AS DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col3' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30'
INSERT INTO t1 (col3) VALUES(CAST('2004-0-10 15:30' AS DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col3' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10 15:30'
INSERT INTO t1 (col3) VALUES(CAST('0000-00-00' AS DATETIME));
ERROR 22007: Incorrect datetime value: '0000-00-00'
drop table t1;
@@ -287,24 +287,26 @@
INSERT INTO t1 (col3) VALUES (CONVERT('2004-10-15 10:15',DATETIME));
INSERT INTO t1 (col1) VALUES(CONVERT('0000-10-31' , DATE));
INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-0' , DATE));
-ERROR 22007: Incorrect date value: '2004-10-00' for column 'col1' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0'
INSERT INTO t1 (col1) VALUES(CONVERT('2004-0-10' , DATE));
-ERROR 22007: Incorrect date value: '2004-00-10' for column 'col1' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10'
+INSERT INTO t1 (col1) VALUES('2004-0-10');
+ERROR 22007: Incorrect date value: '2004-0-10' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES(CONVERT('0000-00-00',DATE));
ERROR 22007: Incorrect datetime value: '0000-00-00'
INSERT INTO t1 (col2) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
INSERT INTO t1 (col2) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col2' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30'
INSERT INTO t1 (col2) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col2' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10 15:30'
INSERT INTO t1 (col2) VALUES(CONVERT('0000-00-00',DATETIME));
ERROR 22007: Incorrect datetime value: '0000-00-00'
INSERT INTO t1 (col3) VALUES(CONVERT('0000-10-31 15:30',DATETIME));
ERROR 22007: Incorrect datetime value: '0000-10-31 15:30:00' for column 'col3' at row 1
INSERT INTO t1 (col3) VALUES(CONVERT('2004-10-0 15:30',DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-10-00 15:30:00' for column 'col3' at row 1
+ERROR 22007: Incorrect datetime value: '2004-10-0 15:30'
INSERT INTO t1 (col3) VALUES(CONVERT('2004-0-10 15:30',DATETIME));
-ERROR 22007: Incorrect datetime value: '2004-00-10 15:30:00' for column 'col3' at row 1
+ERROR 22007: Incorrect datetime value: '2004-0-10 15:30'
INSERT INTO t1 (col3) VALUES(CONVERT('0000-00-00',DATETIME));
ERROR 22007: Incorrect datetime value: '0000-00-00'
drop table t1;
@@ -364,9 +366,9 @@
Error 1365 Division by 0
Error 1365 Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
@@ -447,9 +449,9 @@
UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
ERROR 22012: Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
@@ -531,9 +533,9 @@
UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
ERROR 22012: Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
@@ -615,9 +617,9 @@
UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
ERROR 22012: Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
@@ -697,9 +699,9 @@
UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
ERROR 22012: Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect integer value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect integer value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
@@ -776,7 +778,7 @@
INSERT INTO t1 VALUES ('-100E+1');
ERROR 22003: Out of range value for column 'col1' at row 1
INSERT INTO t1 VALUES ('-100E');
-ERROR HY000: Incorrect decimal value: '-100E' for column 'col1' at row 1
+ERROR 22007: Incorrect decimal value: '-100E' for column 'col1' at row 1
UPDATE t1 SET col1 =col1 * 50000 WHERE col1 =11;
ERROR 22003: Out of range value for column 'col1' at row 6
UPDATE t1 SET col1 =col1 / 0 WHERE col1 > 0;
@@ -784,11 +786,11 @@
UPDATE t1 SET col1= MOD(col1,0) WHERE col1 > 0;
ERROR 22012: Division by 0
INSERT INTO t1 (col1) VALUES ('');
-ERROR HY000: Incorrect decimal value: '' for column 'col1' at row 1
+ERROR 22007: Incorrect decimal value: '' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('a59b');
-ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect decimal value: 'a59b' for column 'col1' at row 1
INSERT INTO t1 (col1) VALUES ('1a');
-ERROR HY000: Incorrect decimal value: '1a' for column 'col1' at row 1
+ERROR 22007: Incorrect decimal value: '1a' for column 'col1' at row 1
INSERT IGNORE INTO t1 (col1) VALUES ('2a');
Warnings:
Note 1265 Data truncated for column 'col1' at row 1
@@ -1361,34 +1363,34 @@
col7 int, col8 int unsigned,
col9 bigint, col10 bigint unsigned);
insert into t1(col1) values('-');
-ERROR HY000: Incorrect integer value: '-' for column 'col1' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'col1' at row 1
insert into t1(col2) values('+');
-ERROR HY000: Incorrect integer value: '+' for column 'col2' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'col2' at row 1
insert into t1(col3) values('-');
-ERROR HY000: Incorrect integer value: '-' for column 'col3' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'col3' at row 1
insert into t1(col4) values('+');
-ERROR HY000: Incorrect integer value: '+' for column 'col4' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'col4' at row 1
insert into t1(col5) values('-');
-ERROR HY000: Incorrect integer value: '-' for column 'col5' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'col5' at row 1
insert into t1(col6) values('+');
-ERROR HY000: Incorrect integer value: '+' for column 'col6' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'col6' at row 1
insert into t1(col7) values('-');
-ERROR HY000: Incorrect integer value: '-' for column 'col7' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'col7' at row 1
insert into t1(col8) values('+');
-ERROR HY000: Incorrect integer value: '+' for column 'col8' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'col8' at row 1
insert into t1(col9) values('-');
-ERROR HY000: Incorrect integer value: '-' for column 'col9' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'col9' at row 1
insert into t1(col10) values('+');
-ERROR HY000: Incorrect integer value: '+' for column 'col10' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'col10' at row 1
drop table t1;
set sql_mode='traditional';
create table t1(a year);
insert into t1 values ('-');
-ERROR HY000: Incorrect integer value: '-' for column 'a' at row 1
+ERROR 22007: Incorrect integer value: '-' for column 'a' at row 1
insert into t1 values ('+');
-ERROR HY000: Incorrect integer value: '+' for column 'a' at row 1
+ERROR 22007: Incorrect integer value: '+' for column 'a' at row 1
insert into t1 values ('');
-ERROR HY000: Incorrect integer value: '' for column 'a' at row 1
+ERROR 22007: Incorrect integer value: '' for column 'a' at row 1
insert into t1 values ('2000a');
ERROR 01000: Data truncated for column 'a' at row 1
insert into t1 values ('2E3x');
=== modified file 'mysql-test/r/type_newdecimal.result'
--- mysql-test/r/type_newdecimal.result 2009-12-08 09:26:11 +0000
+++ mysql-test/r/type_newdecimal.result 2011-04-29 10:53:06 +0000
@@ -825,7 +825,7 @@
Error 1365 Division by 0
Error 1365 Division by 0
INSERT INTO Sow6_2f VALUES ('a59b');
-ERROR HY000: Incorrect decimal value: 'a59b' for column 'col1' at row 1
+ERROR 22007: Incorrect decimal value: 'a59b' for column 'col1' at row 1
drop table Sow6_2f;
select 10.3330000000000/12.34500000;
10.3330000000000/12.34500000
@@ -838,12 +838,12 @@
x
99999999999999999999999999999999999999999999999999999999999999999
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
select 9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 + 1 as x;
x
100000000000000000000000000000000000000000000000000000000000000000
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
select 0.190287977636363637 + 0.040372670 * 0 - 0;
0.190287977636363637 + 0.040372670 * 0 - 0
0.190287977636363637
@@ -1380,15 +1380,15 @@
insert into t1 values(
89000000000000000000000000000000000000000000000000000000000000000000000000000000000000000);
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
Warning 1264 Out of range value for column 'c1' at row 1
insert into t1 values(
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999 *
99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999);
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
Warning 1264 Out of range value for column 'c1' at row 1
insert into t1 values(1e100);
Warnings:
@@ -1432,7 +1432,7 @@
cast(19999999999999999999 as unsigned)
18446744073709551615
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '19999999999999999999' to UNSIGNED INT. Value truncated.
create table t1(a decimal(18));
insert into t1 values(123456789012345678);
alter table t1 modify column a decimal(19);
@@ -1674,7 +1674,7 @@
/* 82 */ 1000000000000000000000000000000000000000000000000000000000000000000000000000000001
AS c1;
Warnings:
-Error 1292 Truncated incorrect DECIMAL value: ''
+Error 1655 Got overflow when converting '' to DECIMAL. Value truncated.
DESC t1;
Field Type Null Key Default Extra
c1 decimal(65,0) NO 0
=== modified file 'mysql-test/r/warnings.result'
--- mysql-test/r/warnings.result 2010-04-28 12:52:24 +0000
+++ mysql-test/r/warnings.result 2011-04-29 10:50:43 +0000
@@ -324,7 +324,7 @@
CAST(a AS DECIMAL(13,5))
0.00000
Warnings:
-Error 1366 Incorrect decimal value: '' for column '' at row 0
+Error 1657 Encountered illegal value '' when converting to DECIMAL
Warning 1292 Truncated incorrect DECIMAL value: ''
create table t1 (a integer unsigned);
insert into t1 values (1),(-1),(0),(-2);
=== modified file 'mysql-test/suite/optimizer_unfixed_bugs/t/bug43448.test'
--- mysql-test/suite/optimizer_unfixed_bugs/t/bug43448.test 2009-12-15 07:16:46 +0000
+++ mysql-test/suite/optimizer_unfixed_bugs/t/bug43448.test 2011-04-29 09:52:28 +0000
@@ -26,6 +26,7 @@
disable_query_log;
+begin;
let $1 = 100;
while ($1)
{
@@ -44,6 +45,7 @@
}
dec $1;
}
+commit;
enable_query_log;
=== modified file 'mysql-test/suite/parts/inc/part_supported_sql_funcs_delete.inc'
--- mysql-test/suite/parts/inc/part_supported_sql_funcs_delete.inc 2008-07-01 18:38:15 +0000
+++ mysql-test/suite/parts/inc/part_supported_sql_funcs_delete.inc 2011-04-29 09:52:28 +0000
@@ -16,12 +16,14 @@
--echo --- Delete rows and partitions of tables with $sqlfunc
--echo -------------------------------------------------------------------------
+begin;
eval delete from $t1 where col1=$val2;
eval delete from $t2 where col1=$val2;
eval delete from $t3 where col1=$val2;
eval delete from $t4 where col1=$val2;
eval delete from $t5 where col1=$val2;
eval delete from $t6 where col1=$val2;
+commit;
eval select * from $t1 order by col1;
eval select * from $t2 order by col1;
@@ -29,12 +31,14 @@
eval select * from $t4 order by colint;
eval select * from $t5 order by colint;
+begin;
eval insert into $t1 values ($val2);
eval insert into $t2 values ($val2);
eval insert into $t3 values ($val2);
eval insert into $t4 values (60,$val2);
eval insert into $t5 values (60,$val2);
eval insert into $t6 values (60,$val2);
+commit;
eval select * from $t1 order by col1;
eval select * from $t2 order by col1;
=== modified file 'mysql-test/suite/parts/inc/partition_supported_sql_funcs.inc'
--- mysql-test/suite/parts/inc/partition_supported_sql_funcs.inc 2008-08-04 05:04:47 +0000
+++ mysql-test/suite/parts/inc/partition_supported_sql_funcs.inc 2011-04-29 09:52:28 +0000
@@ -113,6 +113,7 @@
--echo --- Access tables with $sqlfunc
--echo -------------------------------------------------------------------------
+begin;
eval insert into t1 values ($val1);
eval insert into t1 values ($val2);
@@ -123,6 +124,7 @@
eval insert into t3 values ($val1);
eval insert into t3 values ($val2);
eval insert into t3 values ($val3);
+commit;
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval load data infile '$MYSQLTEST_VARDIR/std_data/parts/$infile' into table t4;
@@ -142,12 +144,14 @@
if ($do_long_tests)
{
+ begin;
eval update t1 set col1=$val4 where col1=$val1;
eval update t2 set col1=$val4 where col1=$val1;
eval update t3 set col1=$val4 where col1=$val1;
eval update t4 set col1=$val4 where col1=$val1;
eval update t5 set col1=$val4 where col1=$val1;
eval update t6 set col1=$val4 where col1=$val1;
+ commit;
select * from t1 order by col1;
select * from t2 order by col1;
=== modified file 'mysql-test/suite/parts/r/part_supported_sql_func_innodb.result'
--- mysql-test/suite/parts/r/part_supported_sql_func_innodb.result 2010-12-22 09:50:36 +0000
+++ mysql-test/suite/parts/r/part_supported_sql_func_innodb.result 2011-04-29 09:52:28 +0000
@@ -47,6 +47,7 @@
-------------------------------------------------------------------------
--- Access tables with abs(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values (5 );
insert into t1 values (13 );
insert into t2 values (5 );
@@ -55,6 +56,7 @@
insert into t3 values (5 );
insert into t3 values (13 );
insert into t3 values (17 );
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t6;
@@ -217,12 +219,14 @@
50 56
51 34
55 123
+begin;
update t1 set col1=15 where col1=5 ;
update t2 set col1=15 where col1=5 ;
update t3 set col1=15 where col1=5 ;
update t4 set col1=15 where col1=5 ;
update t5 set col1=15 where col1=5 ;
update t6 set col1=15 where col1=5 ;
+commit;
select * from t1 order by col1;
col1
13
@@ -877,12 +881,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with abs(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1=13 ;
delete from t2 where col1=13 ;
delete from t3 where col1=13 ;
delete from t4 where col1=13 ;
delete from t5 where col1=13 ;
delete from t6 where col1=13 ;
+commit;
select * from t1 order by col1;
col1
15
@@ -986,12 +992,14 @@
50 56
51 34
55 123
+begin;
insert into t1 values (13 );
insert into t2 values (13 );
insert into t3 values (13 );
insert into t4 values (60,13 );
insert into t5 values (60,13 );
insert into t6 values (60,13 );
+commit;
select * from t1 order by col1;
col1
13
@@ -1274,12 +1282,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with abs(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1=13 ;
delete from t22 where col1=13 ;
delete from t33 where col1=13 ;
delete from t44 where col1=13 ;
delete from t55 where col1=13 ;
delete from t66 where col1=13 ;
+commit;
select * from t11 order by col1;
col1
15
@@ -1383,12 +1393,14 @@
50 56
51 34
55 123
+begin;
insert into t11 values (13 );
insert into t22 values (13 );
insert into t33 values (13 );
insert into t44 values (60,13 );
insert into t55 values (60,13 );
insert into t66 values (60,13 );
+commit;
select * from t11 order by col1;
col1
13
@@ -1732,6 +1744,7 @@
-------------------------------------------------------------------------
--- Access tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
insert into t1 values (5);
insert into t1 values (19);
insert into t2 values (5);
@@ -1740,6 +1753,7 @@
insert into t3 values (5);
insert into t3 values (19);
insert into t3 values (17);
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t6;
@@ -1902,12 +1916,14 @@
50 56
51 34
55 123
+begin;
update t1 set col1=15 where col1=5;
update t2 set col1=15 where col1=5;
update t3 set col1=15 where col1=5;
update t4 set col1=15 where col1=5;
update t5 set col1=15 where col1=5;
update t6 set col1=15 where col1=5;
+commit;
select * from t1 order by col1;
col1
15
@@ -2562,12 +2578,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1=19;
delete from t2 where col1=19;
delete from t3 where col1=19;
delete from t4 where col1=19;
delete from t5 where col1=19;
delete from t6 where col1=19;
+commit;
select * from t1 order by col1;
col1
15
@@ -2673,12 +2691,14 @@
50 56
51 34
55 123
+begin;
insert into t1 values (19);
insert into t2 values (19);
insert into t3 values (19);
insert into t4 values (60,19);
insert into t5 values (60,19);
insert into t6 values (60,19);
+commit;
select * from t1 order by col1;
col1
15
@@ -2970,12 +2990,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1=19;
delete from t22 where col1=19;
delete from t33 where col1=19;
delete from t44 where col1=19;
delete from t55 where col1=19;
delete from t66 where col1=19;
+commit;
select * from t11 order by col1;
col1
15
@@ -3081,12 +3103,14 @@
50 56
51 34
55 123
+begin;
insert into t11 values (19);
insert into t22 values (19);
insert into t33 values (19);
insert into t44 values (60,19);
insert into t55 values (60,19);
insert into t66 values (60,19);
+commit;
select * from t11 order by col1;
col1
15
@@ -3439,6 +3463,7 @@
-------------------------------------------------------------------------
--- Access tables with day(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-02-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-02-03');
@@ -3447,6 +3472,7 @@
insert into t3 values ('2006-02-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -3486,12 +3512,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-02-03';
update t2 set col1='2006-02-05' where col1='2006-02-03';
update t3 set col1='2006-02-05' where col1='2006-02-03';
update t4 set col1='2006-02-05' where col1='2006-02-03';
update t5 set col1='2006-02-05' where col1='2006-02-03';
update t6 set col1='2006-02-05' where col1='2006-02-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -3695,12 +3723,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with day(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -3722,12 +3752,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -3789,12 +3821,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with day(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -3816,12 +3850,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -3944,6 +3980,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-02-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-02-03');
@@ -3952,6 +3989,7 @@
insert into t3 values ('2006-02-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -3991,12 +4029,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-02-03';
update t2 set col1='2006-02-05' where col1='2006-02-03';
update t3 set col1='2006-02-05' where col1='2006-02-03';
update t4 set col1='2006-02-05' where col1='2006-02-03';
update t5 set col1='2006-02-05' where col1='2006-02-03';
update t6 set col1='2006-02-05' where col1='2006-02-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -4200,12 +4240,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4227,12 +4269,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -4294,12 +4338,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4321,12 +4367,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -4449,6 +4497,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-01-03');
@@ -4457,6 +4506,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-02-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -4496,12 +4546,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4705,12 +4757,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-02-17';
delete from t2 where col1='2006-02-17';
delete from t3 where col1='2006-02-17';
delete from t4 where col1='2006-02-17';
delete from t5 where col1='2006-02-17';
delete from t6 where col1='2006-02-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4734,12 +4788,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-02-17');
insert into t3 values ('2006-02-17');
insert into t4 values (60,'2006-02-17');
insert into t5 values (60,'2006-02-17');
insert into t6 values (60,'2006-02-17');
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4805,12 +4861,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-02-17';
delete from t22 where col1='2006-02-17';
delete from t33 where col1='2006-02-17';
delete from t44 where col1='2006-02-17';
delete from t55 where col1='2006-02-17';
delete from t66 where col1='2006-02-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4834,12 +4892,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-02-17');
insert into t22 values ('2006-02-17');
insert into t33 values ('2006-02-17');
insert into t44 values (60,'2006-02-17');
insert into t55 values (60,'2006-02-17');
insert into t66 values (60,'2006-02-17');
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4966,6 +5026,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-03');
@@ -4974,6 +5035,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-02-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -5013,12 +5075,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -5222,12 +5286,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5249,12 +5315,14 @@
1 2006-02-03
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -5317,12 +5385,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5344,12 +5414,14 @@
1 2006-02-03
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -5473,6 +5545,7 @@
-------------------------------------------------------------------------
--- Access tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-01-03');
@@ -5481,6 +5554,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-02-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -5520,12 +5594,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5729,12 +5805,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-02-17';
delete from t2 where col1='2006-02-17';
delete from t3 where col1='2006-02-17';
delete from t4 where col1='2006-02-17';
delete from t5 where col1='2006-02-17';
delete from t6 where col1='2006-02-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5758,12 +5836,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-02-17');
insert into t3 values ('2006-02-17');
insert into t4 values (60,'2006-02-17');
insert into t5 values (60,'2006-02-17');
insert into t6 values (60,'2006-02-17');
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5824,12 +5904,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-02-17';
delete from t22 where col1='2006-02-17';
delete from t33 where col1='2006-02-17';
delete from t44 where col1='2006-02-17';
delete from t55 where col1='2006-02-17';
delete from t66 where col1='2006-02-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5853,12 +5935,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-02-17');
insert into t22 values ('2006-02-17');
insert into t33 values ('2006-02-17');
insert into t44 values (60,'2006-02-17');
insert into t55 values (60,'2006-02-17');
insert into t66 values (60,'2006-02-17');
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5980,6 +6064,7 @@
-------------------------------------------------------------------------
--- Access tables with hour(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09');
insert into t1 values ('14:30');
insert into t2 values ('09:09');
@@ -5988,6 +6073,7 @@
insert into t3 values ('09:09');
insert into t3 values ('14:30');
insert into t3 values ('21:59');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -6027,12 +6113,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:30' where col1='09:09';
update t2 set col1='10:30' where col1='09:09';
update t3 set col1='10:30' where col1='09:09';
update t4 set col1='10:30' where col1='09:09';
update t5 set col1='10:30' where col1='09:09';
update t6 set col1='10:30' where col1='09:09';
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6236,12 +6324,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with hour(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30';
delete from t2 where col1='14:30';
delete from t3 where col1='14:30';
delete from t4 where col1='14:30';
delete from t5 where col1='14:30';
delete from t6 where col1='14:30';
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6265,12 +6355,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30');
insert into t2 values ('14:30');
insert into t3 values ('14:30');
insert into t4 values (60,'14:30');
insert into t5 values (60,'14:30');
insert into t6 values (60,'14:30');
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6334,12 +6426,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with hour(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30';
delete from t22 where col1='14:30';
delete from t33 where col1='14:30';
delete from t44 where col1='14:30';
delete from t55 where col1='14:30';
delete from t66 where col1='14:30';
+commit;
select * from t11 order by col1;
col1
10:30:00
@@ -6363,12 +6457,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30');
insert into t22 values ('14:30');
insert into t33 values ('14:30');
insert into t44 values (60,'14:30');
insert into t55 values (60,'14:30');
insert into t66 values (60,'14:30');
+commit;
select * from t11 order by col1;
col1
10:30:00
@@ -6493,6 +6589,7 @@
-------------------------------------------------------------------------
--- Access tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15.000002');
insert into t1 values ('04:30:01.000018');
insert into t2 values ('09:09:15.000002');
@@ -6501,6 +6598,7 @@
insert into t3 values ('09:09:15.000002');
insert into t3 values ('04:30:01.000018');
insert into t3 values ('00:59:22.000024');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -6540,12 +6638,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t2 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t3 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t4 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t5 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t6 set col1='05:30:34.000037' where col1='09:09:15.000002';
+commit;
select * from t1 order by col1;
col1
04:30:01
@@ -6749,12 +6849,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='04:30:01.000018';
delete from t2 where col1='04:30:01.000018';
delete from t3 where col1='04:30:01.000018';
delete from t4 where col1='04:30:01.000018';
delete from t5 where col1='04:30:01.000018';
delete from t6 where col1='04:30:01.000018';
+commit;
select * from t1 order by col1;
col1
05:30:34
@@ -6776,12 +6878,14 @@
1 05:30:34
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('04:30:01.000018');
insert into t2 values ('04:30:01.000018');
insert into t3 values ('04:30:01.000018');
insert into t4 values (60,'04:30:01.000018');
insert into t5 values (60,'04:30:01.000018');
insert into t6 values (60,'04:30:01.000018');
+commit;
select * from t1 order by col1;
col1
04:30:01
@@ -6840,12 +6944,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='04:30:01.000018';
delete from t22 where col1='04:30:01.000018';
delete from t33 where col1='04:30:01.000018';
delete from t44 where col1='04:30:01.000018';
delete from t55 where col1='04:30:01.000018';
delete from t66 where col1='04:30:01.000018';
+commit;
select * from t11 order by col1;
col1
05:30:34
@@ -6867,12 +6973,14 @@
1 05:30:34
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('04:30:01.000018');
insert into t22 values ('04:30:01.000018');
insert into t33 values ('04:30:01.000018');
insert into t44 values (60,'04:30:01.000018');
insert into t55 values (60,'04:30:01.000018');
insert into t66 values (60,'04:30:01.000018');
+commit;
select * from t11 order by col1;
col1
04:30:01
@@ -6992,6 +7100,7 @@
-------------------------------------------------------------------------
--- Access tables with minute(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15');
insert into t1 values ('14:30:45');
insert into t2 values ('09:09:15');
@@ -7000,6 +7109,7 @@
insert into t3 values ('09:09:15');
insert into t3 values ('14:30:45');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -7039,12 +7149,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:24:23' where col1='09:09:15';
update t2 set col1='10:24:23' where col1='09:09:15';
update t3 set col1='10:24:23' where col1='09:09:15';
update t4 set col1='10:24:23' where col1='09:09:15';
update t5 set col1='10:24:23' where col1='09:09:15';
update t6 set col1='10:24:23' where col1='09:09:15';
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7248,12 +7360,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with minute(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:45';
delete from t2 where col1='14:30:45';
delete from t3 where col1='14:30:45';
delete from t4 where col1='14:30:45';
delete from t5 where col1='14:30:45';
delete from t6 where col1='14:30:45';
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7277,12 +7391,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:45');
insert into t2 values ('14:30:45');
insert into t3 values ('14:30:45');
insert into t4 values (60,'14:30:45');
insert into t5 values (60,'14:30:45');
insert into t6 values (60,'14:30:45');
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7349,12 +7465,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with minute(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:45';
delete from t22 where col1='14:30:45';
delete from t33 where col1='14:30:45';
delete from t44 where col1='14:30:45';
delete from t55 where col1='14:30:45';
delete from t66 where col1='14:30:45';
+commit;
select * from t11 order by col1;
col1
10:24:23
@@ -7378,12 +7496,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:45');
insert into t22 values ('14:30:45');
insert into t33 values ('14:30:45');
insert into t44 values (60,'14:30:45');
insert into t55 values (60,'14:30:45');
insert into t66 values (60,'14:30:45');
+commit;
select * from t11 order by col1;
col1
10:24:23
@@ -7511,6 +7631,7 @@
-------------------------------------------------------------------------
--- Access tables with second(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:09');
insert into t1 values ('14:30:20');
insert into t2 values ('09:09:09');
@@ -7519,6 +7640,7 @@
insert into t3 values ('09:09:09');
insert into t3 values ('14:30:20');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -7558,12 +7680,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:22:33' where col1='09:09:09';
update t2 set col1='10:22:33' where col1='09:09:09';
update t3 set col1='10:22:33' where col1='09:09:09';
update t4 set col1='10:22:33' where col1='09:09:09';
update t5 set col1='10:22:33' where col1='09:09:09';
update t6 set col1='10:22:33' where col1='09:09:09';
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7767,12 +7891,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with second(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:20';
delete from t2 where col1='14:30:20';
delete from t3 where col1='14:30:20';
delete from t4 where col1='14:30:20';
delete from t5 where col1='14:30:20';
delete from t6 where col1='14:30:20';
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7796,12 +7922,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:20');
insert into t2 values ('14:30:20');
insert into t3 values ('14:30:20');
insert into t4 values (60,'14:30:20');
insert into t5 values (60,'14:30:20');
insert into t6 values (60,'14:30:20');
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7868,12 +7996,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with second(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:20';
delete from t22 where col1='14:30:20';
delete from t33 where col1='14:30:20';
delete from t44 where col1='14:30:20';
delete from t55 where col1='14:30:20';
delete from t66 where col1='14:30:20';
+commit;
select * from t11 order by col1;
col1
10:22:33
@@ -7897,12 +8027,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:20');
insert into t22 values ('14:30:20');
insert into t33 values ('14:30:20');
insert into t44 values (60,'14:30:20');
insert into t55 values (60,'14:30:20');
insert into t66 values (60,'14:30:20');
+commit;
select * from t11 order by col1;
col1
10:22:33
@@ -8030,6 +8162,7 @@
-------------------------------------------------------------------------
--- Access tables with month(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-01-03');
@@ -8038,6 +8171,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-12-17');
insert into t3 values ('2006-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -8077,12 +8211,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-11-06' where col1='2006-01-03';
update t2 set col1='2006-11-06' where col1='2006-01-03';
update t3 set col1='2006-11-06' where col1='2006-01-03';
update t4 set col1='2006-11-06' where col1='2006-01-03';
update t5 set col1='2006-11-06' where col1='2006-01-03';
update t6 set col1='2006-11-06' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8286,12 +8422,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with month(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-12-17';
delete from t2 where col1='2006-12-17';
delete from t3 where col1='2006-12-17';
delete from t4 where col1='2006-12-17';
delete from t5 where col1='2006-12-17';
delete from t6 where col1='2006-12-17';
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8315,12 +8453,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-12-17');
insert into t3 values ('2006-12-17');
insert into t4 values (60,'2006-12-17');
insert into t5 values (60,'2006-12-17');
insert into t6 values (60,'2006-12-17');
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8384,12 +8524,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with month(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-12-17';
delete from t22 where col1='2006-12-17';
delete from t33 where col1='2006-12-17';
delete from t44 where col1='2006-12-17';
delete from t55 where col1='2006-12-17';
delete from t66 where col1='2006-12-17';
+commit;
select * from t11 order by col1;
col1
2006-11-06
@@ -8413,12 +8555,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-12-17');
insert into t22 values ('2006-12-17');
insert into t33 values ('2006-12-17');
insert into t44 values (60,'2006-12-17');
insert into t55 values (60,'2006-12-17');
insert into t66 values (60,'2006-12-17');
+commit;
select * from t11 order by col1;
col1
2006-11-06
@@ -8543,6 +8687,7 @@
-------------------------------------------------------------------------
--- Access tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-01-03');
@@ -8551,6 +8696,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-12-17');
insert into t3 values ('2006-09-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -8590,12 +8736,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-07-30' where col1='2006-01-03';
update t2 set col1='2006-07-30' where col1='2006-01-03';
update t3 set col1='2006-07-30' where col1='2006-01-03';
update t4 set col1='2006-07-30' where col1='2006-01-03';
update t5 set col1='2006-07-30' where col1='2006-01-03';
update t6 set col1='2006-07-30' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8799,12 +8947,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-12-17';
delete from t2 where col1='2006-12-17';
delete from t3 where col1='2006-12-17';
delete from t4 where col1='2006-12-17';
delete from t5 where col1='2006-12-17';
delete from t6 where col1='2006-12-17';
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8828,12 +8978,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-12-17');
insert into t3 values ('2006-12-17');
insert into t4 values (60,'2006-12-17');
insert into t5 values (60,'2006-12-17');
insert into t6 values (60,'2006-12-17');
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8896,12 +9048,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-12-17';
delete from t22 where col1='2006-12-17';
delete from t33 where col1='2006-12-17';
delete from t44 where col1='2006-12-17';
delete from t55 where col1='2006-12-17';
delete from t66 where col1='2006-12-17';
+commit;
select * from t11 order by col1;
col1
2006-07-30
@@ -8925,12 +9079,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-12-17');
insert into t22 values ('2006-12-17');
insert into t33 values ('2006-12-17');
insert into t44 values (60,'2006-12-17');
insert into t55 values (60,'2006-12-17');
insert into t66 values (60,'2006-12-17');
+commit;
select * from t11 order by col1;
col1
2006-07-30
@@ -9054,6 +9210,7 @@
-------------------------------------------------------------------------
--- Access tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15');
insert into t1 values ('14:30:45');
insert into t2 values ('09:09:15');
@@ -9062,6 +9219,7 @@
insert into t3 values ('09:09:15');
insert into t3 values ('14:30:45');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -9101,12 +9259,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:33:11' where col1='09:09:15';
update t2 set col1='10:33:11' where col1='09:09:15';
update t3 set col1='10:33:11' where col1='09:09:15';
update t4 set col1='10:33:11' where col1='09:09:15';
update t5 set col1='10:33:11' where col1='09:09:15';
update t6 set col1='10:33:11' where col1='09:09:15';
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9310,12 +9470,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:45';
delete from t2 where col1='14:30:45';
delete from t3 where col1='14:30:45';
delete from t4 where col1='14:30:45';
delete from t5 where col1='14:30:45';
delete from t6 where col1='14:30:45';
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9339,12 +9501,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:45');
insert into t2 values ('14:30:45');
insert into t3 values ('14:30:45');
insert into t4 values (60,'14:30:45');
insert into t5 values (60,'14:30:45');
insert into t6 values (60,'14:30:45');
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9410,12 +9574,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:45';
delete from t22 where col1='14:30:45';
delete from t33 where col1='14:30:45';
delete from t44 where col1='14:30:45';
delete from t55 where col1='14:30:45';
delete from t66 where col1='14:30:45';
+commit;
select * from t11 order by col1;
col1
10:33:11
@@ -9439,12 +9605,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:45');
insert into t22 values ('14:30:45');
insert into t33 values ('14:30:45');
insert into t44 values (60,'14:30:45');
insert into t55 values (60,'14:30:45');
insert into t66 values (60,'14:30:45');
+commit;
select * from t11 order by col1;
col1
10:33:11
@@ -9571,6 +9739,7 @@
-------------------------------------------------------------------------
--- Access tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-12-03');
insert into t1 values ('2006-11-17');
insert into t2 values ('2006-12-03');
@@ -9579,6 +9748,7 @@
insert into t3 values ('2006-12-03');
insert into t3 values ('2006-11-17');
insert into t3 values ('2006-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -9618,12 +9788,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-06' where col1='2006-12-03';
update t2 set col1='2006-02-06' where col1='2006-12-03';
update t3 set col1='2006-02-06' where col1='2006-12-03';
update t4 set col1='2006-02-06' where col1='2006-12-03';
update t5 set col1='2006-02-06' where col1='2006-12-03';
update t6 set col1='2006-02-06' where col1='2006-12-03';
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9827,12 +9999,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-11-17';
delete from t2 where col1='2006-11-17';
delete from t3 where col1='2006-11-17';
delete from t4 where col1='2006-11-17';
delete from t5 where col1='2006-11-17';
delete from t6 where col1='2006-11-17';
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9856,12 +10030,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-11-17');
insert into t2 values ('2006-11-17');
insert into t3 values ('2006-11-17');
insert into t4 values (60,'2006-11-17');
insert into t5 values (60,'2006-11-17');
insert into t6 values (60,'2006-11-17');
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9923,12 +10099,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-11-17';
delete from t22 where col1='2006-11-17';
delete from t33 where col1='2006-11-17';
delete from t44 where col1='2006-11-17';
delete from t55 where col1='2006-11-17';
delete from t66 where col1='2006-11-17';
+commit;
select * from t11 order by col1;
col1
2006-02-06
@@ -9952,12 +10130,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-11-17');
insert into t22 values ('2006-11-17');
insert into t33 values ('2006-11-17');
insert into t44 values (60,'2006-11-17');
insert into t55 values (60,'2006-11-17');
insert into t66 values (60,'2006-11-17');
+commit;
select * from t11 order by col1;
col1
2006-02-06
@@ -10080,6 +10260,7 @@
-------------------------------------------------------------------------
--- Access tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
insert into t1 values ('1996-01-03');
insert into t1 values ('2000-02-17');
insert into t2 values ('1996-01-03');
@@ -10088,6 +10269,7 @@
insert into t3 values ('1996-01-03');
insert into t3 values ('2000-02-17');
insert into t3 values ('2004-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -10127,12 +10309,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2002-02-15' where col1='1996-01-03';
update t2 set col1='2002-02-15' where col1='1996-01-03';
update t3 set col1='2002-02-15' where col1='1996-01-03';
update t4 set col1='2002-02-15' where col1='1996-01-03';
update t5 set col1='2002-02-15' where col1='1996-01-03';
update t6 set col1='2002-02-15' where col1='1996-01-03';
+commit;
select * from t1 order by col1;
col1
2000-02-17
@@ -10336,12 +10520,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2000-02-17';
delete from t2 where col1='2000-02-17';
delete from t3 where col1='2000-02-17';
delete from t4 where col1='2000-02-17';
delete from t5 where col1='2000-02-17';
delete from t6 where col1='2000-02-17';
+commit;
select * from t1 order by col1;
col1
2002-02-15
@@ -10365,12 +10551,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2000-02-17');
insert into t2 values ('2000-02-17');
insert into t3 values ('2000-02-17');
insert into t4 values (60,'2000-02-17');
insert into t5 values (60,'2000-02-17');
insert into t6 values (60,'2000-02-17');
+commit;
select * from t1 order by col1;
col1
2000-02-17
@@ -10434,12 +10622,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2000-02-17';
delete from t22 where col1='2000-02-17';
delete from t33 where col1='2000-02-17';
delete from t44 where col1='2000-02-17';
delete from t55 where col1='2000-02-17';
delete from t66 where col1='2000-02-17';
+commit;
select * from t11 order by col1;
col1
2002-02-15
@@ -10463,12 +10653,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2000-02-17');
insert into t22 values ('2000-02-17');
insert into t33 values ('2000-02-17');
insert into t44 values (60,'2000-02-17');
insert into t55 values (60,'2000-02-17');
insert into t66 values (60,'2000-02-17');
+commit;
select * from t11 order by col1;
col1
2000-02-17
@@ -10593,6 +10785,7 @@
-------------------------------------------------------------------------
--- Access tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-08-17');
insert into t2 values ('2006-01-03');
@@ -10601,6 +10794,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-08-17');
insert into t3 values ('2006-03-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -10640,12 +10834,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-11-15' where col1='2006-01-03';
update t2 set col1='2006-11-15' where col1='2006-01-03';
update t3 set col1='2006-11-15' where col1='2006-01-03';
update t4 set col1='2006-11-15' where col1='2006-01-03';
update t5 set col1='2006-11-15' where col1='2006-01-03';
update t6 set col1='2006-11-15' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-08-17
@@ -10849,12 +11045,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-08-17';
delete from t2 where col1='2006-08-17';
delete from t3 where col1='2006-08-17';
delete from t4 where col1='2006-08-17';
delete from t5 where col1='2006-08-17';
delete from t6 where col1='2006-08-17';
+commit;
select * from t1 order by col1;
col1
2006-11-15
@@ -10878,12 +11076,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-08-17');
insert into t2 values ('2006-08-17');
insert into t3 values ('2006-08-17');
insert into t4 values (60,'2006-08-17');
insert into t5 values (60,'2006-08-17');
insert into t6 values (60,'2006-08-17');
+commit;
select * from t1 order by col1;
col1
2006-08-17
@@ -10950,12 +11150,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-08-17';
delete from t22 where col1='2006-08-17';
delete from t33 where col1='2006-08-17';
delete from t44 where col1='2006-08-17';
delete from t55 where col1='2006-08-17';
delete from t66 where col1='2006-08-17';
+commit;
select * from t11 order by col1;
col1
2006-11-15
@@ -10979,12 +11181,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-08-17');
insert into t22 values ('2006-08-17');
insert into t33 values ('2006-08-17');
insert into t44 values (60,'2006-08-17');
insert into t55 values (60,'2006-08-17');
insert into t66 values (60,'2006-08-17');
+commit;
select * from t11 order by col1;
col1
2006-08-17
=== modified file 'mysql-test/suite/parts/r/part_supported_sql_func_myisam.result'
--- mysql-test/suite/parts/r/part_supported_sql_func_myisam.result 2010-12-22 09:50:36 +0000
+++ mysql-test/suite/parts/r/part_supported_sql_func_myisam.result 2011-04-29 09:52:28 +0000
@@ -47,6 +47,7 @@
-------------------------------------------------------------------------
--- Access tables with abs(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values (5 );
insert into t1 values (13 );
insert into t2 values (5 );
@@ -55,6 +56,7 @@
insert into t3 values (5 );
insert into t3 values (13 );
insert into t3 values (17 );
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t6;
@@ -217,12 +219,14 @@
50 56
51 34
55 123
+begin;
update t1 set col1=15 where col1=5 ;
update t2 set col1=15 where col1=5 ;
update t3 set col1=15 where col1=5 ;
update t4 set col1=15 where col1=5 ;
update t5 set col1=15 where col1=5 ;
update t6 set col1=15 where col1=5 ;
+commit;
select * from t1 order by col1;
col1
13
@@ -877,12 +881,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with abs(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1=13 ;
delete from t2 where col1=13 ;
delete from t3 where col1=13 ;
delete from t4 where col1=13 ;
delete from t5 where col1=13 ;
delete from t6 where col1=13 ;
+commit;
select * from t1 order by col1;
col1
15
@@ -986,12 +992,14 @@
50 56
51 34
55 123
+begin;
insert into t1 values (13 );
insert into t2 values (13 );
insert into t3 values (13 );
insert into t4 values (60,13 );
insert into t5 values (60,13 );
insert into t6 values (60,13 );
+commit;
select * from t1 order by col1;
col1
13
@@ -1274,12 +1282,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with abs(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1=13 ;
delete from t22 where col1=13 ;
delete from t33 where col1=13 ;
delete from t44 where col1=13 ;
delete from t55 where col1=13 ;
delete from t66 where col1=13 ;
+commit;
select * from t11 order by col1;
col1
15
@@ -1383,12 +1393,14 @@
50 56
51 34
55 123
+begin;
insert into t11 values (13 );
insert into t22 values (13 );
insert into t33 values (13 );
insert into t44 values (60,13 );
insert into t55 values (60,13 );
insert into t66 values (60,13 );
+commit;
select * from t11 order by col1;
col1
13
@@ -1732,6 +1744,7 @@
-------------------------------------------------------------------------
--- Access tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
insert into t1 values (5);
insert into t1 values (19);
insert into t2 values (5);
@@ -1740,6 +1753,7 @@
insert into t3 values (5);
insert into t3 values (19);
insert into t3 values (17);
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_int.inc' into table t6;
@@ -1902,12 +1916,14 @@
50 56
51 34
55 123
+begin;
update t1 set col1=15 where col1=5;
update t2 set col1=15 where col1=5;
update t3 set col1=15 where col1=5;
update t4 set col1=15 where col1=5;
update t5 set col1=15 where col1=5;
update t6 set col1=15 where col1=5;
+commit;
select * from t1 order by col1;
col1
15
@@ -2562,12 +2578,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1=19;
delete from t2 where col1=19;
delete from t3 where col1=19;
delete from t4 where col1=19;
delete from t5 where col1=19;
delete from t6 where col1=19;
+commit;
select * from t1 order by col1;
col1
15
@@ -2673,12 +2691,14 @@
50 56
51 34
55 123
+begin;
insert into t1 values (19);
insert into t2 values (19);
insert into t3 values (19);
insert into t4 values (60,19);
insert into t5 values (60,19);
insert into t6 values (60,19);
+commit;
select * from t1 order by col1;
col1
15
@@ -2970,12 +2990,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with mod(col1,10)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1=19;
delete from t22 where col1=19;
delete from t33 where col1=19;
delete from t44 where col1=19;
delete from t55 where col1=19;
delete from t66 where col1=19;
+commit;
select * from t11 order by col1;
col1
15
@@ -3081,12 +3103,14 @@
50 56
51 34
55 123
+begin;
insert into t11 values (19);
insert into t22 values (19);
insert into t33 values (19);
insert into t44 values (60,19);
insert into t55 values (60,19);
insert into t66 values (60,19);
+commit;
select * from t11 order by col1;
col1
15
@@ -3439,6 +3463,7 @@
-------------------------------------------------------------------------
--- Access tables with day(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-02-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-02-03');
@@ -3447,6 +3472,7 @@
insert into t3 values ('2006-02-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -3486,12 +3512,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-02-03';
update t2 set col1='2006-02-05' where col1='2006-02-03';
update t3 set col1='2006-02-05' where col1='2006-02-03';
update t4 set col1='2006-02-05' where col1='2006-02-03';
update t5 set col1='2006-02-05' where col1='2006-02-03';
update t6 set col1='2006-02-05' where col1='2006-02-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -3695,12 +3723,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with day(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -3722,12 +3752,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -3789,12 +3821,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with day(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -3816,12 +3850,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -3944,6 +3980,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-02-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-02-03');
@@ -3952,6 +3989,7 @@
insert into t3 values ('2006-02-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -3991,12 +4029,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-02-03';
update t2 set col1='2006-02-05' where col1='2006-02-03';
update t3 set col1='2006-02-05' where col1='2006-02-03';
update t4 set col1='2006-02-05' where col1='2006-02-03';
update t5 set col1='2006-02-05' where col1='2006-02-03';
update t6 set col1='2006-02-05' where col1='2006-02-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -4200,12 +4240,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4227,12 +4269,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -4294,12 +4338,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofmonth(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4321,12 +4367,14 @@
1 2006-02-05
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -4449,6 +4497,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-01-03');
@@ -4457,6 +4506,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-02-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -4496,12 +4546,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4705,12 +4757,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-02-17';
delete from t2 where col1='2006-02-17';
delete from t3 where col1='2006-02-17';
delete from t4 where col1='2006-02-17';
delete from t5 where col1='2006-02-17';
delete from t6 where col1='2006-02-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4734,12 +4788,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-02-17');
insert into t3 values ('2006-02-17');
insert into t4 values (60,'2006-02-17');
insert into t5 values (60,'2006-02-17');
insert into t6 values (60,'2006-02-17');
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -4805,12 +4861,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofweek(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-02-17';
delete from t22 where col1='2006-02-17';
delete from t33 where col1='2006-02-17';
delete from t44 where col1='2006-02-17';
delete from t55 where col1='2006-02-17';
delete from t66 where col1='2006-02-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4834,12 +4892,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-02-17');
insert into t22 values ('2006-02-17');
insert into t33 values ('2006-02-17');
insert into t44 values (60,'2006-02-17');
insert into t55 values (60,'2006-02-17');
insert into t66 values (60,'2006-02-17');
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -4966,6 +5026,7 @@
-------------------------------------------------------------------------
--- Access tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-03');
@@ -4974,6 +5035,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-01-17');
insert into t3 values ('2006-02-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -5013,12 +5075,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -5222,12 +5286,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-01-17';
delete from t2 where col1='2006-01-17';
delete from t3 where col1='2006-01-17';
delete from t4 where col1='2006-01-17';
delete from t5 where col1='2006-01-17';
delete from t6 where col1='2006-01-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5249,12 +5315,14 @@
1 2006-02-03
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-01-17');
insert into t2 values ('2006-01-17');
insert into t3 values ('2006-01-17');
insert into t4 values (60,'2006-01-17');
insert into t5 values (60,'2006-01-17');
insert into t6 values (60,'2006-01-17');
+commit;
select * from t1 order by col1;
col1
2006-01-17
@@ -5317,12 +5385,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with dayofyear(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-01-17';
delete from t22 where col1='2006-01-17';
delete from t33 where col1='2006-01-17';
delete from t44 where col1='2006-01-17';
delete from t55 where col1='2006-01-17';
delete from t66 where col1='2006-01-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5344,12 +5414,14 @@
1 2006-02-03
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-01-17');
insert into t22 values ('2006-01-17');
insert into t33 values ('2006-01-17');
insert into t44 values (60,'2006-01-17');
insert into t55 values (60,'2006-01-17');
insert into t66 values (60,'2006-01-17');
+commit;
select * from t11 order by col1;
col1
2006-01-17
@@ -5473,6 +5545,7 @@
-------------------------------------------------------------------------
--- Access tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-01-03');
@@ -5481,6 +5554,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-02-17');
insert into t3 values ('2006-01-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -5520,12 +5594,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-05' where col1='2006-01-03';
update t2 set col1='2006-02-05' where col1='2006-01-03';
update t3 set col1='2006-02-05' where col1='2006-01-03';
update t4 set col1='2006-02-05' where col1='2006-01-03';
update t5 set col1='2006-02-05' where col1='2006-01-03';
update t6 set col1='2006-02-05' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5729,12 +5805,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-02-17';
delete from t2 where col1='2006-02-17';
delete from t3 where col1='2006-02-17';
delete from t4 where col1='2006-02-17';
delete from t5 where col1='2006-02-17';
delete from t6 where col1='2006-02-17';
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5758,12 +5836,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-02-17');
insert into t2 values ('2006-02-17');
insert into t3 values ('2006-02-17');
insert into t4 values (60,'2006-02-17');
insert into t5 values (60,'2006-02-17');
insert into t6 values (60,'2006-02-17');
+commit;
select * from t1 order by col1;
col1
2006-02-05
@@ -5824,12 +5904,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with extract(month from col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-02-17';
delete from t22 where col1='2006-02-17';
delete from t33 where col1='2006-02-17';
delete from t44 where col1='2006-02-17';
delete from t55 where col1='2006-02-17';
delete from t66 where col1='2006-02-17';
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5853,12 +5935,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-02-17');
insert into t22 values ('2006-02-17');
insert into t33 values ('2006-02-17');
insert into t44 values (60,'2006-02-17');
insert into t55 values (60,'2006-02-17');
insert into t66 values (60,'2006-02-17');
+commit;
select * from t11 order by col1;
col1
2006-02-05
@@ -5980,6 +6064,7 @@
-------------------------------------------------------------------------
--- Access tables with hour(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09');
insert into t1 values ('14:30');
insert into t2 values ('09:09');
@@ -5988,6 +6073,7 @@
insert into t3 values ('09:09');
insert into t3 values ('14:30');
insert into t3 values ('21:59');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -6027,12 +6113,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:30' where col1='09:09';
update t2 set col1='10:30' where col1='09:09';
update t3 set col1='10:30' where col1='09:09';
update t4 set col1='10:30' where col1='09:09';
update t5 set col1='10:30' where col1='09:09';
update t6 set col1='10:30' where col1='09:09';
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6236,12 +6324,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with hour(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30';
delete from t2 where col1='14:30';
delete from t3 where col1='14:30';
delete from t4 where col1='14:30';
delete from t5 where col1='14:30';
delete from t6 where col1='14:30';
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6265,12 +6355,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30');
insert into t2 values ('14:30');
insert into t3 values ('14:30');
insert into t4 values (60,'14:30');
insert into t5 values (60,'14:30');
insert into t6 values (60,'14:30');
+commit;
select * from t1 order by col1;
col1
10:30:00
@@ -6334,12 +6426,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with hour(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30';
delete from t22 where col1='14:30';
delete from t33 where col1='14:30';
delete from t44 where col1='14:30';
delete from t55 where col1='14:30';
delete from t66 where col1='14:30';
+commit;
select * from t11 order by col1;
col1
10:30:00
@@ -6363,12 +6457,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30');
insert into t22 values ('14:30');
insert into t33 values ('14:30');
insert into t44 values (60,'14:30');
insert into t55 values (60,'14:30');
insert into t66 values (60,'14:30');
+commit;
select * from t11 order by col1;
col1
10:30:00
@@ -6493,6 +6589,7 @@
-------------------------------------------------------------------------
--- Access tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15.000002');
insert into t1 values ('04:30:01.000018');
insert into t2 values ('09:09:15.000002');
@@ -6501,6 +6598,7 @@
insert into t3 values ('09:09:15.000002');
insert into t3 values ('04:30:01.000018');
insert into t3 values ('00:59:22.000024');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -6540,12 +6638,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t2 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t3 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t4 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t5 set col1='05:30:34.000037' where col1='09:09:15.000002';
update t6 set col1='05:30:34.000037' where col1='09:09:15.000002';
+commit;
select * from t1 order by col1;
col1
04:30:01
@@ -6749,12 +6849,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='04:30:01.000018';
delete from t2 where col1='04:30:01.000018';
delete from t3 where col1='04:30:01.000018';
delete from t4 where col1='04:30:01.000018';
delete from t5 where col1='04:30:01.000018';
delete from t6 where col1='04:30:01.000018';
+commit;
select * from t1 order by col1;
col1
05:30:34
@@ -6776,12 +6878,14 @@
1 05:30:34
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('04:30:01.000018');
insert into t2 values ('04:30:01.000018');
insert into t3 values ('04:30:01.000018');
insert into t4 values (60,'04:30:01.000018');
insert into t5 values (60,'04:30:01.000018');
insert into t6 values (60,'04:30:01.000018');
+commit;
select * from t1 order by col1;
col1
04:30:01
@@ -6840,12 +6944,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with microsecond(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='04:30:01.000018';
delete from t22 where col1='04:30:01.000018';
delete from t33 where col1='04:30:01.000018';
delete from t44 where col1='04:30:01.000018';
delete from t55 where col1='04:30:01.000018';
delete from t66 where col1='04:30:01.000018';
+commit;
select * from t11 order by col1;
col1
05:30:34
@@ -6867,12 +6973,14 @@
1 05:30:34
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('04:30:01.000018');
insert into t22 values ('04:30:01.000018');
insert into t33 values ('04:30:01.000018');
insert into t44 values (60,'04:30:01.000018');
insert into t55 values (60,'04:30:01.000018');
insert into t66 values (60,'04:30:01.000018');
+commit;
select * from t11 order by col1;
col1
04:30:01
@@ -6992,6 +7100,7 @@
-------------------------------------------------------------------------
--- Access tables with minute(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15');
insert into t1 values ('14:30:45');
insert into t2 values ('09:09:15');
@@ -7000,6 +7109,7 @@
insert into t3 values ('09:09:15');
insert into t3 values ('14:30:45');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -7039,12 +7149,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:24:23' where col1='09:09:15';
update t2 set col1='10:24:23' where col1='09:09:15';
update t3 set col1='10:24:23' where col1='09:09:15';
update t4 set col1='10:24:23' where col1='09:09:15';
update t5 set col1='10:24:23' where col1='09:09:15';
update t6 set col1='10:24:23' where col1='09:09:15';
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7248,12 +7360,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with minute(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:45';
delete from t2 where col1='14:30:45';
delete from t3 where col1='14:30:45';
delete from t4 where col1='14:30:45';
delete from t5 where col1='14:30:45';
delete from t6 where col1='14:30:45';
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7277,12 +7391,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:45');
insert into t2 values ('14:30:45');
insert into t3 values ('14:30:45');
insert into t4 values (60,'14:30:45');
insert into t5 values (60,'14:30:45');
insert into t6 values (60,'14:30:45');
+commit;
select * from t1 order by col1;
col1
10:24:23
@@ -7349,12 +7465,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with minute(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:45';
delete from t22 where col1='14:30:45';
delete from t33 where col1='14:30:45';
delete from t44 where col1='14:30:45';
delete from t55 where col1='14:30:45';
delete from t66 where col1='14:30:45';
+commit;
select * from t11 order by col1;
col1
10:24:23
@@ -7378,12 +7496,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:45');
insert into t22 values ('14:30:45');
insert into t33 values ('14:30:45');
insert into t44 values (60,'14:30:45');
insert into t55 values (60,'14:30:45');
insert into t66 values (60,'14:30:45');
+commit;
select * from t11 order by col1;
col1
10:24:23
@@ -7511,6 +7631,7 @@
-------------------------------------------------------------------------
--- Access tables with second(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:09');
insert into t1 values ('14:30:20');
insert into t2 values ('09:09:09');
@@ -7519,6 +7640,7 @@
insert into t3 values ('09:09:09');
insert into t3 values ('14:30:20');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -7558,12 +7680,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:22:33' where col1='09:09:09';
update t2 set col1='10:22:33' where col1='09:09:09';
update t3 set col1='10:22:33' where col1='09:09:09';
update t4 set col1='10:22:33' where col1='09:09:09';
update t5 set col1='10:22:33' where col1='09:09:09';
update t6 set col1='10:22:33' where col1='09:09:09';
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7767,12 +7891,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with second(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:20';
delete from t2 where col1='14:30:20';
delete from t3 where col1='14:30:20';
delete from t4 where col1='14:30:20';
delete from t5 where col1='14:30:20';
delete from t6 where col1='14:30:20';
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7796,12 +7922,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:20');
insert into t2 values ('14:30:20');
insert into t3 values ('14:30:20');
insert into t4 values (60,'14:30:20');
insert into t5 values (60,'14:30:20');
insert into t6 values (60,'14:30:20');
+commit;
select * from t1 order by col1;
col1
10:22:33
@@ -7868,12 +7996,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with second(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:20';
delete from t22 where col1='14:30:20';
delete from t33 where col1='14:30:20';
delete from t44 where col1='14:30:20';
delete from t55 where col1='14:30:20';
delete from t66 where col1='14:30:20';
+commit;
select * from t11 order by col1;
col1
10:22:33
@@ -7897,12 +8027,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:20');
insert into t22 values ('14:30:20');
insert into t33 values ('14:30:20');
insert into t44 values (60,'14:30:20');
insert into t55 values (60,'14:30:20');
insert into t66 values (60,'14:30:20');
+commit;
select * from t11 order by col1;
col1
10:22:33
@@ -8030,6 +8162,7 @@
-------------------------------------------------------------------------
--- Access tables with month(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-01-03');
@@ -8038,6 +8171,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-12-17');
insert into t3 values ('2006-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -8077,12 +8211,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-11-06' where col1='2006-01-03';
update t2 set col1='2006-11-06' where col1='2006-01-03';
update t3 set col1='2006-11-06' where col1='2006-01-03';
update t4 set col1='2006-11-06' where col1='2006-01-03';
update t5 set col1='2006-11-06' where col1='2006-01-03';
update t6 set col1='2006-11-06' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8286,12 +8422,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with month(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-12-17';
delete from t2 where col1='2006-12-17';
delete from t3 where col1='2006-12-17';
delete from t4 where col1='2006-12-17';
delete from t5 where col1='2006-12-17';
delete from t6 where col1='2006-12-17';
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8315,12 +8453,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-12-17');
insert into t3 values ('2006-12-17');
insert into t4 values (60,'2006-12-17');
insert into t5 values (60,'2006-12-17');
insert into t6 values (60,'2006-12-17');
+commit;
select * from t1 order by col1;
col1
2006-11-06
@@ -8384,12 +8524,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with month(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-12-17';
delete from t22 where col1='2006-12-17';
delete from t33 where col1='2006-12-17';
delete from t44 where col1='2006-12-17';
delete from t55 where col1='2006-12-17';
delete from t66 where col1='2006-12-17';
+commit;
select * from t11 order by col1;
col1
2006-11-06
@@ -8413,12 +8555,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-12-17');
insert into t22 values ('2006-12-17');
insert into t33 values ('2006-12-17');
insert into t44 values (60,'2006-12-17');
insert into t55 values (60,'2006-12-17');
insert into t66 values (60,'2006-12-17');
+commit;
select * from t11 order by col1;
col1
2006-11-06
@@ -8543,6 +8687,7 @@
-------------------------------------------------------------------------
--- Access tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-01-03');
@@ -8551,6 +8696,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-12-17');
insert into t3 values ('2006-09-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -8590,12 +8736,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-07-30' where col1='2006-01-03';
update t2 set col1='2006-07-30' where col1='2006-01-03';
update t3 set col1='2006-07-30' where col1='2006-01-03';
update t4 set col1='2006-07-30' where col1='2006-01-03';
update t5 set col1='2006-07-30' where col1='2006-01-03';
update t6 set col1='2006-07-30' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8799,12 +8947,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-12-17';
delete from t2 where col1='2006-12-17';
delete from t3 where col1='2006-12-17';
delete from t4 where col1='2006-12-17';
delete from t5 where col1='2006-12-17';
delete from t6 where col1='2006-12-17';
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8828,12 +8978,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-12-17');
insert into t2 values ('2006-12-17');
insert into t3 values ('2006-12-17');
insert into t4 values (60,'2006-12-17');
insert into t5 values (60,'2006-12-17');
insert into t6 values (60,'2006-12-17');
+commit;
select * from t1 order by col1;
col1
2006-07-30
@@ -8896,12 +9048,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with quarter(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-12-17';
delete from t22 where col1='2006-12-17';
delete from t33 where col1='2006-12-17';
delete from t44 where col1='2006-12-17';
delete from t55 where col1='2006-12-17';
delete from t66 where col1='2006-12-17';
+commit;
select * from t11 order by col1;
col1
2006-07-30
@@ -8925,12 +9079,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-12-17');
insert into t22 values ('2006-12-17');
insert into t33 values ('2006-12-17');
insert into t44 values (60,'2006-12-17');
insert into t55 values (60,'2006-12-17');
insert into t66 values (60,'2006-12-17');
+commit;
select * from t11 order by col1;
col1
2006-07-30
@@ -9054,6 +9210,7 @@
-------------------------------------------------------------------------
--- Access tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('09:09:15');
insert into t1 values ('14:30:45');
insert into t2 values ('09:09:15');
@@ -9062,6 +9219,7 @@
insert into t3 values ('09:09:15');
insert into t3 values ('14:30:45');
insert into t3 values ('21:59:22');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_time.inc' into table t6;
@@ -9101,12 +9259,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
update t1 set col1='10:33:11' where col1='09:09:15';
update t2 set col1='10:33:11' where col1='09:09:15';
update t3 set col1='10:33:11' where col1='09:09:15';
update t4 set col1='10:33:11' where col1='09:09:15';
update t5 set col1='10:33:11' where col1='09:09:15';
update t6 set col1='10:33:11' where col1='09:09:15';
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9310,12 +9470,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='14:30:45';
delete from t2 where col1='14:30:45';
delete from t3 where col1='14:30:45';
delete from t4 where col1='14:30:45';
delete from t5 where col1='14:30:45';
delete from t6 where col1='14:30:45';
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9339,12 +9501,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t1 values ('14:30:45');
insert into t2 values ('14:30:45');
insert into t3 values ('14:30:45');
insert into t4 values (60,'14:30:45');
insert into t5 values (60,'14:30:45');
insert into t6 values (60,'14:30:45');
+commit;
select * from t1 order by col1;
col1
10:33:11
@@ -9410,12 +9574,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with time_to_sec(col1)-(time_to_sec(col1)-20)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='14:30:45';
delete from t22 where col1='14:30:45';
delete from t33 where col1='14:30:45';
delete from t44 where col1='14:30:45';
delete from t55 where col1='14:30:45';
delete from t66 where col1='14:30:45';
+commit;
select * from t11 order by col1;
col1
10:33:11
@@ -9439,12 +9605,14 @@
2 04:30:01
3 00:59:22
4 05:30:34
+begin;
insert into t11 values ('14:30:45');
insert into t22 values ('14:30:45');
insert into t33 values ('14:30:45');
insert into t44 values (60,'14:30:45');
insert into t55 values (60,'14:30:45');
insert into t66 values (60,'14:30:45');
+commit;
select * from t11 order by col1;
col1
10:33:11
@@ -9571,6 +9739,7 @@
-------------------------------------------------------------------------
--- Access tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-12-03');
insert into t1 values ('2006-11-17');
insert into t2 values ('2006-12-03');
@@ -9579,6 +9748,7 @@
insert into t3 values ('2006-12-03');
insert into t3 values ('2006-11-17');
insert into t3 values ('2006-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -9618,12 +9788,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-02-06' where col1='2006-12-03';
update t2 set col1='2006-02-06' where col1='2006-12-03';
update t3 set col1='2006-02-06' where col1='2006-12-03';
update t4 set col1='2006-02-06' where col1='2006-12-03';
update t5 set col1='2006-02-06' where col1='2006-12-03';
update t6 set col1='2006-02-06' where col1='2006-12-03';
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9827,12 +9999,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-11-17';
delete from t2 where col1='2006-11-17';
delete from t3 where col1='2006-11-17';
delete from t4 where col1='2006-11-17';
delete from t5 where col1='2006-11-17';
delete from t6 where col1='2006-11-17';
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9856,12 +10030,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-11-17');
insert into t2 values ('2006-11-17');
insert into t3 values ('2006-11-17');
insert into t4 values (60,'2006-11-17');
insert into t5 values (60,'2006-11-17');
insert into t6 values (60,'2006-11-17');
+commit;
select * from t1 order by col1;
col1
2006-02-06
@@ -9923,12 +10099,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with weekday(col1)
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-11-17';
delete from t22 where col1='2006-11-17';
delete from t33 where col1='2006-11-17';
delete from t44 where col1='2006-11-17';
delete from t55 where col1='2006-11-17';
delete from t66 where col1='2006-11-17';
+commit;
select * from t11 order by col1;
col1
2006-02-06
@@ -9952,12 +10130,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-11-17');
insert into t22 values ('2006-11-17');
insert into t33 values ('2006-11-17');
insert into t44 values (60,'2006-11-17');
insert into t55 values (60,'2006-11-17');
insert into t66 values (60,'2006-11-17');
+commit;
select * from t11 order by col1;
col1
2006-02-06
@@ -10080,6 +10260,7 @@
-------------------------------------------------------------------------
--- Access tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
insert into t1 values ('1996-01-03');
insert into t1 values ('2000-02-17');
insert into t2 values ('1996-01-03');
@@ -10088,6 +10269,7 @@
insert into t3 values ('1996-01-03');
insert into t3 values ('2000-02-17');
insert into t3 values ('2004-05-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -10127,12 +10309,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2002-02-15' where col1='1996-01-03';
update t2 set col1='2002-02-15' where col1='1996-01-03';
update t3 set col1='2002-02-15' where col1='1996-01-03';
update t4 set col1='2002-02-15' where col1='1996-01-03';
update t5 set col1='2002-02-15' where col1='1996-01-03';
update t6 set col1='2002-02-15' where col1='1996-01-03';
+commit;
select * from t1 order by col1;
col1
2000-02-17
@@ -10336,12 +10520,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2000-02-17';
delete from t2 where col1='2000-02-17';
delete from t3 where col1='2000-02-17';
delete from t4 where col1='2000-02-17';
delete from t5 where col1='2000-02-17';
delete from t6 where col1='2000-02-17';
+commit;
select * from t1 order by col1;
col1
2002-02-15
@@ -10365,12 +10551,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2000-02-17');
insert into t2 values ('2000-02-17');
insert into t3 values ('2000-02-17');
insert into t4 values (60,'2000-02-17');
insert into t5 values (60,'2000-02-17');
insert into t6 values (60,'2000-02-17');
+commit;
select * from t1 order by col1;
col1
2000-02-17
@@ -10434,12 +10622,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with year(col1)-1990
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2000-02-17';
delete from t22 where col1='2000-02-17';
delete from t33 where col1='2000-02-17';
delete from t44 where col1='2000-02-17';
delete from t55 where col1='2000-02-17';
delete from t66 where col1='2000-02-17';
+commit;
select * from t11 order by col1;
col1
2002-02-15
@@ -10463,12 +10653,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2000-02-17');
insert into t22 values ('2000-02-17');
insert into t33 values ('2000-02-17');
insert into t44 values (60,'2000-02-17');
insert into t55 values (60,'2000-02-17');
insert into t66 values (60,'2000-02-17');
+commit;
select * from t11 order by col1;
col1
2000-02-17
@@ -10593,6 +10785,7 @@
-------------------------------------------------------------------------
--- Access tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
insert into t1 values ('2006-01-03');
insert into t1 values ('2006-08-17');
insert into t2 values ('2006-01-03');
@@ -10601,6 +10794,7 @@
insert into t3 values ('2006-01-03');
insert into t3 values ('2006-08-17');
insert into t3 values ('2006-03-25');
+commit;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t4;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t5;
load data infile 'MYSQLTEST_VARDIR/std_data/parts/part_supported_sql_funcs_int_date.inc' into table t6;
@@ -10640,12 +10834,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
update t1 set col1='2006-11-15' where col1='2006-01-03';
update t2 set col1='2006-11-15' where col1='2006-01-03';
update t3 set col1='2006-11-15' where col1='2006-01-03';
update t4 set col1='2006-11-15' where col1='2006-01-03';
update t5 set col1='2006-11-15' where col1='2006-01-03';
update t6 set col1='2006-11-15' where col1='2006-01-03';
+commit;
select * from t1 order by col1;
col1
2006-08-17
@@ -10849,12 +11045,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
delete from t1 where col1='2006-08-17';
delete from t2 where col1='2006-08-17';
delete from t3 where col1='2006-08-17';
delete from t4 where col1='2006-08-17';
delete from t5 where col1='2006-08-17';
delete from t6 where col1='2006-08-17';
+commit;
select * from t1 order by col1;
col1
2006-11-15
@@ -10878,12 +11076,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t1 values ('2006-08-17');
insert into t2 values ('2006-08-17');
insert into t3 values ('2006-08-17');
insert into t4 values (60,'2006-08-17');
insert into t5 values (60,'2006-08-17');
insert into t6 values (60,'2006-08-17');
+commit;
select * from t1 order by col1;
col1
2006-08-17
@@ -10950,12 +11150,14 @@
-------------------------------------------------------------------------
--- Delete rows and partitions of tables with yearweek(col1)-200600
-------------------------------------------------------------------------
+begin;
delete from t11 where col1='2006-08-17';
delete from t22 where col1='2006-08-17';
delete from t33 where col1='2006-08-17';
delete from t44 where col1='2006-08-17';
delete from t55 where col1='2006-08-17';
delete from t66 where col1='2006-08-17';
+commit;
select * from t11 order by col1;
col1
2006-11-15
@@ -10979,12 +11181,14 @@
2 2006-01-17
3 2006-01-25
4 2006-02-05
+begin;
insert into t11 values ('2006-08-17');
insert into t22 values ('2006-08-17');
insert into t33 values ('2006-08-17');
insert into t44 values (60,'2006-08-17');
insert into t55 values (60,'2006-08-17');
insert into t66 values (60,'2006-08-17');
+commit;
select * from t11 order by col1;
col1
2006-08-17
=== modified file 'mysql-test/suite/parts/r/rpl_partition.result'
--- mysql-test/suite/parts/r/rpl_partition.result 2010-12-19 17:07:28 +0000
+++ mysql-test/suite/parts/r/rpl_partition.result 2011-04-29 09:52:28 +0000
@@ -96,13 +96,19 @@
SET del_count = del_count - 2;
END WHILE;
END|
+begin;
CALL p1();
+commit;
SELECT count(*) as "Master regular" FROM t1;
Master regular 500
+begin;
CALL p2();
+commit;
SELECT count(*) as "Master bykey" FROM t2;
Master bykey 500
+begin;
CALL p3();
+commit;
SELECT count(*) as "Master byrange" FROM t3;
Master byrange 500
show create table t3;
=== modified file 'mysql-test/suite/parts/t/part_supported_sql_func_innodb.test'
--- mysql-test/suite/parts/t/part_supported_sql_func_innodb.test 2011-02-20 16:51:43 +0000
+++ mysql-test/suite/parts/t/part_supported_sql_func_innodb.test 2011-04-29 09:52:28 +0000
@@ -26,13 +26,11 @@
let $do_long_tests= 1;
#
+# This test takes long time, so only run it with the --big mtr-flag.
--source include/big_test.inc
# The server must support partitioning.
--source include/have_partition.inc
-# This test takes long time, so only run it with the --big mtr-flag.
---source include/big_test.inc
-
#------------------------------------------------------------------------------#
# Engine specific settings and requirements
=== modified file 'mysql-test/suite/parts/t/rpl_partition.test'
--- mysql-test/suite/parts/t/rpl_partition.test 2011-02-20 16:51:43 +0000
+++ mysql-test/suite/parts/t/rpl_partition.test 2011-04-29 09:52:28 +0000
@@ -127,11 +127,17 @@
############ Test Section ###################
+begin;
CALL p1();
+commit;
SELECT count(*) as "Master regular" FROM t1;
+begin;
CALL p2();
+commit;
SELECT count(*) as "Master bykey" FROM t2;
+begin;
CALL p3();
+commit;
SELECT count(*) as "Master byrange" FROM t3;
--sync_slave_with_master
=== modified file 'mysql-test/suite/rpl/r/rpl_innodb_bug28430.result'
--- mysql-test/suite/rpl/r/rpl_innodb_bug28430.result 2010-12-19 17:07:28 +0000
+++ mysql-test/suite/rpl/r/rpl_innodb_bug28430.result 2011-04-29 09:52:28 +0000
@@ -90,13 +90,19 @@
SET del_count = del_count - 2;
END WHILE;
END|
+begin;
CALL test.proc_norm();
+commit;
SELECT count(*) as "Master regular" FROM test.regular_tbl;
Master regular 500
+begin;
CALL test.proc_bykey();
+commit;
SELECT count(*) as "Master bykey" FROM test.bykey_tbl;
Master bykey 500
+begin;
CALL test.proc_byrange();
+commit;
SELECT count(*) as "Master byrange" FROM test.byrange_tbl;
Master byrange 500
show create table test.byrange_tbl;
=== modified file 'mysql-test/suite/rpl/t/rpl_innodb_bug28430.test'
--- mysql-test/suite/rpl/t/rpl_innodb_bug28430.test 2011-02-20 16:51:43 +0000
+++ mysql-test/suite/rpl/t/rpl_innodb_bug28430.test 2011-04-29 09:52:28 +0000
@@ -127,11 +127,17 @@
############ Test Section ###################
+begin;
CALL test.proc_norm();
+commit;
SELECT count(*) as "Master regular" FROM test.regular_tbl;
+begin;
CALL test.proc_bykey();
+commit;
SELECT count(*) as "Master bykey" FROM test.bykey_tbl;
+begin;
CALL test.proc_byrange();
+commit;
SELECT count(*) as "Master byrange" FROM test.byrange_tbl;
--sync_slave_with_master
=== modified file 'mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result'
--- mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result 2010-10-30 17:54:38 +0000
+++ mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result 2011-04-29 09:52:28 +0000
@@ -2686,10 +2686,15 @@
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (1,default);
insert into t1 values (-1,default);
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select * from t1;
a b
1 1
-1 18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
drop table t1;
set sql_warnings = 0;
# Convert()
@@ -2703,10 +2708,15 @@
) ENGINE=InnoDB DEFAULT CHARSET=latin1
insert into t1 values (1,default);
insert into t1 values (-1,default);
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select * from t1;
a b
1 1
-1 18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
drop table t1;
set sql_warnings = 0;
#
=== modified file 'mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result'
--- mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result 2010-10-30 17:54:38 +0000
+++ mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result 2011-04-29 09:52:28 +0000
@@ -2686,10 +2686,15 @@
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values (1,default);
insert into t1 values (-1,default);
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select * from t1;
a b
1 1
-1 18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
drop table t1;
set sql_warnings = 0;
# Convert()
@@ -2703,10 +2708,15 @@
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert into t1 values (1,default);
insert into t1 values (-1,default);
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
select * from t1;
a b
1 1
-1 18446744073709551615
+Warnings:
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
+Warning 1105 Cast to unsigned converted negative integer to it's positive complement
drop table t1;
set sql_warnings = 0;
#
=== modified file 'mysql-test/t/cast.test'
--- mysql-test/t/cast.test 2009-05-21 08:06:43 +0000
+++ mysql-test/t/cast.test 2011-04-29 09:52:28 +0000
@@ -11,6 +11,21 @@
explain extended select ~5, cast(~5 as signed);
select cast(5 as unsigned) -6.0;
select cast(NULL as signed), cast(1/0 as signed);
+select cast(1 as double(5,2));
+select cast("5.2222" as double(5,2));
+select cast(12.444 as double(5,2));
+select cast(cast(12.444 as decimal(10,3)) as double(5,2));
+select cast(null as double(5,2));
+select cast(12.444 as double);
+select cast(cast("20:01:01" as time) as datetime);
+select cast(cast("8:46:06.23434" AS time) as decimal(32,10));
+select cast(cast(20010203101112.121314 as double) as datetime);
+select cast(cast(010203101112.12 as double) as datetime);
+select cast(cast(20010203101112.121314 as decimal(32,6)) as datetime);
+select cast(20010203101112.121314 as datetime);
+select cast(110203101112.121314 as datetime);
+select cast(cast(010203101112.12 as double) as datetime);
+select cast(cast("2011-04-05 8:46:06.23434" AS datetime) as time);
#
# Bug #28250: Run-Time Check Failure #3 - The variable 'value' is being used
# without being def
@@ -42,6 +57,44 @@
select 10+'a';
select 10.0+cast('a' as decimal);
select 10E+0+'a';
+select cast("a" as double(5,2));
+select cast(1000 as decimal(5,2));
+select cast(-1000 as decimal(5,2));
+select cast(1000 as double(5,2));
+select cast(-1000 as double(5,2));
+select cast(010203101112.121314 as datetime);
+select cast(120010203101112.121314 as datetime);
+select cast(cast(1.1 as decimal) as datetime);
+select cast(cast(-1.1 as decimal) as datetime);
+select cast('0' as date);
+select cast('' as date);
+select cast('0' as datetime);
+select cast('' as datetime);
+select cast('0' as time);
+select cast('' as time);
+select cast(NULL as DATE);
+select cast(NULL as DATETIME);
+select cast(NULL as TIME);
+select cast(NULL as BINARY);
+
+#
+# We have to disable warnings for these as the printed double value is
+# not portable
+#
+--disable_warnings
+select cast(cast(120010203101112.121314 as double) as datetime);
+select cast(cast(1.1 as double) as datetime);
+select cast(cast(-1.1 as double) as datetime);
+--enable_warnings
+
+
+#
+# Some EXPLAIN EXTENDED to ensure the print functions are correct
+#
+
+explain extended select cast(10 as double(5,2));
+explain extended select cast(10 as double);
+explain extended select cast(10 as decimal(5,2));
# out-of-range cases
select cast('18446744073709551616' as unsigned);
@@ -52,6 +105,20 @@
select cast('1a' as signed);
select cast('' as signed);
+--error ER_M_BIGGER_THAN_D
+select cast(1 as double(5,6));
+--error ER_M_BIGGER_THAN_D
+select cast(1 as decimal(5,6));
+--error ER_TOO_BIG_PRECISION
+select cast(1 as double(66,6));
+--error ER_TOO_BIG_PRECISION
+select cast(1 as decimal(66,6));
+--error ER_TOO_BIG_SCALE
+select cast(1 as decimal(64,63));
+--error ER_TOO_BIG_SCALE
+select cast(1 as double(64,63));
+
+
#
# Character set conversion
#
@@ -124,8 +191,6 @@
select cast("2001-1-1" as date) = "2001-01-01";
select cast("2001-1-1" as datetime) = "2001-01-01 00:00:00";
select cast("1:2:3" as TIME) = "1:02:03";
-select cast(NULL as DATE);
-select cast(NULL as BINARY);
#
# Bug #5228 ORDER BY CAST(enumcol) sorts incorrectly under certain conditions
@@ -172,6 +237,14 @@
select cast(1.0e+300 as signed int);
#
+# Test that we create the correct types with create ... select cast()
+#
+
+create table t1 select cast(1 as unsigned), cast(1 as signed), cast(1 as double(5,2)), cast(1 as decimal(5,3)), cast("A" as binary), cast("A" as char(100)), cast("2001-1-1" as DATE), cast("2001-1-1" as DATETIME), cast("1:2:3" as TIME);
+show create table t1;
+drop table t1;
+
+#
# Bugs: #15098: CAST(column double TO signed int), wrong result
#
CREATE TABLE t1 (f1 double);
=== added file 'mysql-test/t/dyncol.test'
--- mysql-test/t/dyncol.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/dyncol.test 2011-04-29 11:02:53 +0000
@@ -0,0 +1,361 @@
+#
+# Dynamic column function test
+#
+
+--echo #
+--echo # column create
+--echo #
+select hex(COLUMN_CREATE(1, NULL AS char character set utf8));
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8));
+select hex(COLUMN_CREATE(1, 1212 AS char character set utf8));
+select hex(COLUMN_CREATE(1, 12.12 AS char character set utf8));
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS char character set utf8));
+select hex(COLUMN_CREATE(1, NULL AS unsigned int));
+select hex(COLUMN_CREATE(1, 1212 AS unsigned int));
+select hex(COLUMN_CREATE(1, 7 AS unsigned int));
+select hex(COLUMN_CREATE(1, 8 AS unsigned int));
+select hex(COLUMN_CREATE(1, 127 AS unsigned int));
+select hex(COLUMN_CREATE(1, 128 AS unsigned int));
+select hex(COLUMN_CREATE(1, 12.12 AS unsigned int));
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS unsigned int));
+select hex(COLUMN_CREATE(1, NULL AS int));
+select hex(COLUMN_CREATE(1, 1212 AS int));
+select hex(COLUMN_CREATE(1, 7 AS int));
+select hex(COLUMN_CREATE(1, 8 AS int));
+select hex(COLUMN_CREATE(1, 127 AS int));
+select hex(COLUMN_CREATE(1, 128 AS int));
+select hex(COLUMN_CREATE(1, 12.12 AS int));
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS int));
+select hex(COLUMN_CREATE(1, NULL AS double));
+select hex(COLUMN_CREATE(1, 1212 AS double));
+select hex(COLUMN_CREATE(1, 12.12 AS double));
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS double));
+select hex(COLUMN_CREATE(1, NULL AS decimal));
+select hex(COLUMN_CREATE(1, 1212 AS decimal));
+select hex(COLUMN_CREATE(1, 7 AS decimal));
+select hex(COLUMN_CREATE(1, 8 AS decimal));
+select hex(COLUMN_CREATE(1, 127 AS decimal));
+select hex(COLUMN_CREATE(1, 128 AS decimal));
+select hex(COLUMN_CREATE(1, 12.12 AS decimal));
+select hex(COLUMN_CREATE(1, 99999999999999999999999999999 AS decimal));
+select hex(COLUMN_CREATE(1, NULL AS date));
+select hex(COLUMN_CREATE(1, "2011-04-05" AS date));
+select hex(COLUMN_CREATE(1, NULL AS time));
+select hex(COLUMN_CREATE(1, "0:45:49.000001" AS time));
+select hex(COLUMN_CREATE(1, NULL AS datetime));
+select hex(COLUMN_CREATE(1, "2011-04-05 0:45:49.000001" AS datetime));
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+ 2, 1212 AS unsigned int,
+ 3, 1212 AS int,
+ 4, 12.12 AS double,
+ 4+1, 12.12 AS decimal,
+ 6, "2011-04-05" AS date,
+ 7, "- 0:45:49.000001" AS time,
+ 8, "2011-04-05 0:45:49.000001" AS datetime));
+explain extended
+select hex(COLUMN_CREATE(1, "afaf" AS char character set utf8,
+ 2, 1212 AS unsigned int,
+ 3, 1212 AS int,
+ 4, 12.12 AS double,
+ 4+1, 12.12 AS decimal,
+ 6, "2011-04-05" AS date,
+ 7, "- 0:45:49.000001" AS time,
+ 8, "2011-04-05 0:45:49.000001" AS datetime));
+
+
+--echo #
+--echo # column get uint
+--echo #
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int);
+explain extended
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned int);
+explain extended
+select column_get(column_create(1, 1212 AS unsigned int), 1 as unsigned);
+select column_get(column_create(1, 1212 AS decimal), 1 as unsigned int);
+select column_get(column_create(1, 1212 AS double), 1 as unsigned int);
+select column_get(column_create(1, 1212 AS int), 1 as unsigned int);
+select column_get(column_create(1, "1212" AS char), 1 as unsigned int);
+select column_get(column_create(1, "2011-04-05" AS date), 1 as unsigned int);
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as unsigned int);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as unsigned int);
+select column_get(column_create(1, NULL AS unsigned int), 1 as unsigned int);
+--echo # column geint truncation & warnings
+select column_get(column_create(1, -1212 AS int), 1 as unsigned int);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as unsigned int);
+select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as unsigned int);
+select column_get(column_create(1, -1 AS decimal), 1 as unsigned int);
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as unsigned int);
+select column_get(column_create(1, 999.9 AS double), 1 as unsigned int);
+select column_get(column_create(1, -1 AS double), 1 as unsigned int);
+select column_get(column_create(1, "1212III" AS char), 1 as unsigned int);
+
+--echo #
+--echo # column get int
+--echo #
+select column_get(column_create(1, 1212 AS int), 1 as int);
+explain extended
+select column_get(column_create(1, 1212 AS int), 1 as int);
+explain extended
+select column_get(column_create(1, 1212 AS int), 1 as signed int);
+select column_get(column_create(1, -1212 AS int), 1 as int);
+select column_get(column_create(1, 1212 AS decimal), 1 as int);
+select column_get(column_create(1, 1212 AS double), 1 as int);
+select column_get(column_create(1, 1212 AS unsigned int), 1 as int);
+select column_get(column_create(1, "1212" AS char), 1 as int);
+select column_get(column_create(1, "-1212" AS char), 1 as int);
+select column_get(column_create(1, "2011-04-05" AS date), 1 as int);
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as int);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as int);
+select column_get(column_create(1, NULL AS int), 1 as int);
+--echo #column gett truncation & warnings
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as int);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as int);
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as int);
+select column_get(column_create(1, 999.9999999999999999 AS decimal), 1 as int);
+select column_get(column_create(1, 999.9 AS double), 1 as int);
+select column_get(column_create(1, -99999999999999999999999999999 AS double), 1 as int);
+select column_get(column_create(1, "-1212III" AS char), 1 as int);
+select column_get(column_create(1, "1212III" AS char), 1 as int);
+
+--echo #
+--echo #column get char
+--echo #
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8);
+explain extended
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset utf8);
+select column_get(column_create(1, 1212 AS unsigned int), 1 as char charset utf8);
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as char charset utf8);
+select column_get(column_create(1, 1212 AS int), 1 as char charset utf8);
+select column_get(column_create(1, -1212 AS int), 1 as char charset utf8);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as char charset utf8);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as char charset utf8);
+select column_get(column_create(1, 1212.12 AS decimal), 1 as char charset utf8);
+select column_get(column_create(1, 1212.12 AS double), 1 as char charset utf8);
+select column_get(column_create(1, "2011-04-05" AS date), 1 as char charset utf8);
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as char charset utf8);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as char charset utf8);
+select column_get(column_create(1, NULL AS char charset utf8), 1 as char charset utf8);
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary);
+explain extended
+select column_get(column_create(1, "1212" AS char charset utf8), 1 as char charset binary);
+
+--echo #
+--echo # column get real
+--echo #
+select column_get(column_create(1, 1212.12 AS double), 1 as double);
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as double);
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as double(6,2));
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as double);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as double);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as double);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal), 1 as double);
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as double);
+select column_get(column_create(1, "2011-04-05" AS date), 1 as double);
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as double);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as double(20,6));
+select column_get(column_create(1, NULL AS double), 1 as double);
+
+-- echo # column get real truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as double);
+select column_get(column_create(1, "aa" AS char), 1 as double);
+select column_get(column_create(1, "1223.5555" AS double), 1 as double(5,2));
+select column_get(column_create(1, "1223.5555" AS double), 1 as double(3,2));
+
+--echo #
+--echo # column get decimal
+--echo #
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal);
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2));
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal);
+explain extended
+select column_get(column_create(1, 1212.12 AS double), 1 as decimal(6,2));
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal(20,0));
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal(32,0));
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal(32,0));
+select column_get(column_create(1, -99999999999999999999999999999 AS decimal), 1 as decimal(40,10));
+select column_get(column_create(1, "2011-04-05" AS date), 1 as decimal(32,6));
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as decimal(32,6));
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal(32,6));
+select column_get(column_create(1, NULL as decimal), 1 as decimal(32,10));
+select column_get(column_create(1, "1223.5555" as decimal(10,5)), 1 as decimal(6,2));
+
+-- echo # column get decimal truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as decimal(32,10));
+select column_get(column_create(1, "aa" AS char), 1 as decimal(32,10));
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as decimal);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as decimal);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as decimal);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as decimal);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as decimal);
+select column_get(column_create(1, "1223.5555" as double), 1 as decimal(5,2));
+select column_get(column_create(1, "-1223.5555" as double), 1 as decimal(5,2));
+select column_get(column_create(1, "1223.5555" AS double), 1 as decimal(3,2));
+select column_get(column_create(1, "1223.5555" AS decimal(10,5)), 1 as decimal(3,2));
+
+--echo #
+--echo # column get datetime
+--echo #
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as datetime);
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as datetime);
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as datetime);
+select column_get(column_create(1, 20010203101112 as int), 1 as datetime);
+select column_get(column_create(1, "20010203101112" as char), 1 as datetime);
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as datetime);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as datetime);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as datetime);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as datetime);
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as datetime);
+
+select column_get(column_create(1, 20010203 as unsigned int), 1 as datetime);
+select column_get(column_create(1, 20010203 as int), 1 as datetime);
+select column_get(column_create(1, 20010203), 1 as datetime);
+select column_get(column_create(1, 20010203.0), 1 as datetime);
+select column_get(column_create(1, 20010203.0 as double), 1 as datetime);
+select column_get(column_create(1, "2001-02-03"), 1 as datetime);
+select column_get(column_create(1, "20010203"), 1 as datetime);
+select column_get(column_create(1, 0), 1 as datetime);
+select column_get(column_create(1, "2001021"), 1 as datetime);
+
+select column_get(column_create(1, "8:46:06.23434" AS time), 1 as datetime);
+
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as datetime);
+set @@sql_mode="";
+
+-- echo # column get datetime truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as datetime);
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as datetime);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as datetime);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as datetime);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as datetime);
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as datetime);
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as datetime);
+select column_get(column_create(1, "20010231"), 1 as datetime);
+select column_get(column_create(1, "0" AS CHAR), 1 as datetime);
+
+
+--echo #
+--echo # column get date
+--echo #
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as date);
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as date);
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as date);
+select column_get(column_create(1, 20010203101112 as int), 1 as date);
+select column_get(column_create(1, "20010203101112" as char), 1 as date);
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as date);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as date);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as date);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as date);
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as date);
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as date);
+
+select column_get(column_create(1, 20010203 as unsigned int), 1 as date);
+select column_get(column_create(1, 20010203 as int), 1 as date);
+select column_get(column_create(1, 20010203), 1 as date);
+select column_get(column_create(1, 20010203.0), 1 as date);
+select column_get(column_create(1, 20010203.0 as double), 1 as date);
+select column_get(column_create(1, "2001-02-03"), 1 as date);
+select column_get(column_create(1, "20010203"), 1 as date);
+select column_get(column_create(1, 0), 1 as date);
+select column_get(column_create(1, "2001021"), 1 as date);
+
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as date);
+select column_get(column_create(1, "0000-00-000" AS CHAR), 1 as date);
+select column_get(column_create(1, "2001-00-02" AS CHAR), 1 as date);
+set @@sql_mode="";
+
+-- echo # column get date truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as date);
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as date);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as date);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as date);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as date);
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as date);
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as date);
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as date);
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as date);
+select column_get(column_create(1, "20010231"), 1 as date);
+select column_get(column_create(1, "0" AS CHAR), 1 as date);
+
+--echo #
+--echo # column get time
+--echo #
+select column_get(column_create(1, 20010203101112.121314 as double), 1 as time);
+select column_get(column_create(1, 20010203101112.121314 as decimal), 1 as time);
+select column_get(column_create(1, 20010203101112 as unsigned int), 1 as time);
+select column_get(column_create(1, 20010203101112 as int), 1 as time);
+select column_get(column_create(1, "20010203101112" as char), 1 as time);
+select column_get(column_create(1, "2001-02-03 10:11:12" as char), 1 as time);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314" as char), 1 as time);
+select column_get(column_create(1, "2001-02-03 10:11:12.121314"), 1 as time);
+select column_get(column_create(1, "2011-04-05 8:46:06.23434" AS datetime), 1 as time);
+select column_get(column_create(1, "2011-00-00 8:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "2011-00-01 8:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "830:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "-830:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "0" AS CHAR), 1 as time);
+select column_get(column_create(1, "6" AS CHAR), 1 as time);
+select column_get(column_create(1, "1:6" AS CHAR), 1 as time);
+select column_get(column_create(1, "2:1:6" AS CHAR), 1 as time);
+
+select column_get(column_create(1, 0), 1 as time);
+select column_get(column_create(1, "2001021"), 1 as time);
+
+set @@sql_mode="allow_invalid_dates";
+select column_get(column_create(1, "2011-02-30 18:46:06.23434" AS CHAR), 1 as time);
+set @@sql_mode="";
+
+-- echo # column get date truncation & warnings
+select column_get(column_create(1, "1223.5aa" AS char), 1 as time);
+select column_get(column_create(1, 18446744073709551615 AS unsigned int), 1 as time);
+select column_get(column_create(1, 9223372036854775807 AS int), 1 as time);
+select column_get(column_create(1, -9223372036854775808 AS int), 1 as time);
+select column_get(column_create(1, 99999999999999999999999999999 AS decimal(32,10)), 1 as time);
+select column_get(column_create(1, 99999999999999999999999999999 AS double), 1 as time);
+select column_get(column_create(1, "2011-02-32 8:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "2011-13-01 8:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "2011-02-30 8:46:06.23434" AS CHAR), 1 as time);
+select column_get(column_create(1, "2001-02-03"), 1 as time);
+select column_get(column_create(1, "20010203"), 1 as time);
+
+
+-- echo # column add
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer));
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer));
+select hex(column_add(column_create(1, 1212 as integer), 1, NULL as integer));
+select hex(column_add(column_create(1, 1212 as integer), 2, NULL as integer));
+select hex(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer));
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 1 as integer);
+select column_get(column_add(column_create(1, 1212 as integer), 2, 1212 as integer, 1, 11 as integer), 2 as integer);
+select hex(column_add(column_create(1, 1212 as integer), 1, 1212 as integer, 2, 11 as integer));
+select hex(column_add(column_create(1, NULL as integer), 1, 1212 as integer, 2, 11 as integer));
+select hex(column_add(column_create(1, 1212 as integer, 2, 1212 as integer), 1, 11 as integer));
+
+-- echo # column delete
+select hex(column_delete(column_create(1, 1212 as integer, 2, 1212 as integer), 1));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 4));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 1));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 2, 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3));
+select hex(column_delete(column_create(1, 1 as integer, 2, 2 as integer, 3, 3 as integer), 1, 2, 3, 10));
+
+-- echo # column exists
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 1);
+select column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4);
+
+-- echo # column list
+select column_list(column_create(1, 1212 as integer, 2, 1212 as integer));
+select column_list(column_create(1, 1212 as integer));
+select column_list(column_create(1, NULL as integer));
=== modified file 'mysql-test/t/strict.test'
--- mysql-test/t/strict.test 2009-06-11 16:21:32 +0000
+++ mysql-test/t/strict.test 2011-04-29 09:52:28 +0000
@@ -367,6 +367,8 @@
INSERT INTO t1 (col1) VALUES(CONVERT('2004-10-0' , DATE));
--error 1292
INSERT INTO t1 (col1) VALUES(CONVERT('2004-0-10' , DATE));
+--error 1292
+INSERT INTO t1 (col1) VALUES('2004-0-10');
# deactivated because of Bug#8294
# Bug#8294 Traditional: Misleading error message for invalid CAST to DATE
=== modified file 'mysys/Makefile.am'
--- mysys/Makefile.am 2011-02-28 17:39:30 +0000
+++ mysys/Makefile.am 2011-04-29 09:52:28 +0000
@@ -27,7 +27,7 @@
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c my_getpagesize.c \
- my_crc32.c \
+ my_crc32.c ma_dyncol.c \
mf_iocache.c mf_iocache2.c mf_cache.c mf_tempfile.c \
mf_tempdir.c my_lock.c mf_brkhant.c my_alarm.c \
my_malloc.c my_realloc.c my_once.c mulalloc.c \
=== added file 'mysys/ma_dyncol.c'
--- mysys/ma_dyncol.c 1970-01-01 00:00:00 +0000
+++ mysys/ma_dyncol.c 2011-04-29 09:52:28 +0000
@@ -0,0 +1,1831 @@
+#include <ma_dyncol.h>
+
+/*
+ Flag byte bits
+
+ 2 bits which determinate size of offset in the header -1
+*/
+/* mask to get above bits */
+#define DYNCOL_FLG_OFFSET 3
+/* All known flags mask */
+#define DYNCOL_FLG_KNOWN 3
+
+/* dynamic column size reserve */
+#define DYNCOL_SYZERESERVE 80
+
+/* length of fixed string header 1 byte - flags, 2 bytes - columns counter */
+#define FIXED_HEADER_SIZE 3
+
+#define COLUMN_NUMBER_SIZE 2
+
+
+static int dynamic_column_time_add(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value);
+static int dynamic_column_date_add(DYNAMIC_COLUMN *str,
+ MYSQL_TIME *value);
+static int
+dynamic_column_time_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+static int
+dynamic_column_date_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data, size_t length);
+
+/**
+ Initialize dynamic column string with (make it empty but correct format)
+
+ @param str The string to initialize
+ @param size Amount of preallocated memory for the string
+
+ @retval FALSE OK
+ @retval TRUE error
+*/
+
+my_bool dynamic_column_init_str(DYNAMIC_COLUMN *str, size_t size)
+{
+ if (!size)
+ size= DYNCOL_SYZERESERVE;
+ /*
+ Make string with no fields (empty header)
+ - First \0 is flags
+ - other four \0 is 0 fileds counter
+ */
+ if (init_dynamic_string(str, NULL,
+ size + FIXED_HEADER_SIZE, DYNCOL_SYZERESERVE))
+ return TRUE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ return FALSE;
+}
+
+
+/**
+ Calculate how many bytes needed to store val as variable length integer
+ where fist bit indicate continuation of the sequence.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+static size_t dynamic_column_var_uint_bytes(ulonglong val)
+{
+ size_t len= 0;
+ do
+ {
+ len++;
+ val>>= 7;
+ } while (val);
+ return len;
+}
+
+
+/**
+ Add variable value int to the string.
+
+ @param str The string where to put the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_var_uint_add(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (dynstr_realloc(str, 10)) // max what we can use
+ return ER_DYNCOL_RESOURCE;
+
+ do
+ {
+ ulonglong rest= val >> 7;
+ str->str[str->length++]= ((val & 0x7f) | (rest ? 0x80 : 0x00));
+ val= rest;
+ } while (val);
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Reads variable length unsigned int value from the string
+
+ @param data The string which should be read
+ @param len Where to put length of the string read in bytes
+
+ @return value of the unsigned integer read from the string
+*/
+
+ulonglong dynamic_column_var_uint_get(uchar *data, size_t *len)
+{
+ ulonglong val= 0;
+ *len= 0;
+ for(;;)
+ {
+ val+= (((ulonglong)(data[len[0]] & 0x7f)) << (len[0]*7));
+ if (!(data[len[0]] & 0x80))
+ break;
+ len[0]++;
+ }
+ len[0]++;
+ return val;
+}
+
+/**
+ Calculate how many bytes needed to store val as unsigned.
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_uint_bytes(ulonglong val)
+{
+ size_t len= 0;
+ do
+ {
+ len++;
+ val>>= 8;
+ } while (val);
+ return len;
+}
+
+
+/**
+ Append the string with given unsigned int value.
+
+ @param str The string where to put the value
+ @param val The value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_uint_add(DYNAMIC_COLUMN *str, ulonglong val)
+{
+ if (dynstr_realloc(str, 8)) // max what we can use
+ return ER_DYNCOL_RESOURCE;
+ do
+ {
+ str->str[str->length++]= val & 0xff;
+ val>>= 8;
+ } while (val);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read unsigned int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_uint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ ulonglong value= 0;
+ size_t i;
+ for (i= 0; i < length; i++)
+ {
+ value+= ((ulonglong)data[i]) << (i*8);
+ }
+ store_it_here->ulong_value= value;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Calculate how many bytes needed to store val as signed in following encoding:
+ 0 -> 0
+ -1 -> 1
+ 1 -> 2
+ -2 -> 3
+ 2 -> 4
+ ...
+
+ @param val The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_sint_bytes(longlong val)
+{
+ return dynamic_column_uint_bytes((val << 1) ^
+ (val < 0 ? ULL(0xffffffffffffffff) : 0));
+}
+
+
+/**
+ Append the string with given signed int value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_sint_add(DYNAMIC_COLUMN *str, longlong val)
+{
+ return dynamic_column_uint_add(str,
+ (val << 1) ^
+ (val < 0 ? ULL(0xffffffffffffffff) : 0));
+}
+
+
+/**
+ Read signed int value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_sint_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ ulonglong val;
+ dynamic_column_uint_read(store_it_here, data, length);
+ val= store_it_here->ulong_value;
+ if (val & 1)
+ val= (val >> 1) ^ ULL(0xffffffffffffffff);
+ else
+ val>>= 1;
+ store_it_here->long_value= (longlong)(val);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Calculate how many bytes needed to store the value.
+
+ @param value The value for which we are calculating length
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_value_len(DYNAMIC_COLUMN_VALUE *value)
+{
+ switch (value->type) {
+ case DYN_COL_NULL:
+ return 0;
+ case DYN_COL_INT:
+ return dynamic_column_sint_bytes(value->long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_bytes(value->ulong_value);
+ case DYN_COL_DOUBLE:
+ return 8;
+ case DYN_COL_STRING:
+ return (dynamic_column_var_uint_bytes(value->charset->number) +
+ value->string_value.length);
+ case DYN_COL_DECIMAL:
+ return (dynamic_column_var_uint_bytes(value->decimal_value.intg) +
+ dynamic_column_var_uint_bytes(value->decimal_value.frac) +
+ decimal_bin_size(value->decimal_value.intg +
+ value->decimal_value.frac,
+ value->decimal_value.frac));
+ case DYN_COL_DATETIME:
+ /* date+time in bits: 14 + 4 + 5 + 10 + 6 + 6 + 20 + 1 66bits ~= 9 bytes */
+ return 9;
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return 3;
+ case DYN_COL_TIME:
+ /* time in bits: 10 + 6 + 6 + 20 + 1 = 43bits ~= 6bytes*/
+ return 6;
+ default:
+ DBUG_ASSERT(0);
+ return 0;
+ }
+}
+
+
+/**
+ Append the string with given double value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_double_add(DYNAMIC_COLUMN *str, double val)
+{
+ if (dynstr_realloc(str, 8))
+ return ER_DYNCOL_RESOURCE;
+ float8store(str->str + str->length, val);
+ str->length+= 8;
+ return ER_DYNCOL_OK;
+}
+
+/**
+ Read double value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_double_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 8)
+ return ER_DYNCOL_FORMAT;
+ float8get(store_it_here->double_value, data);
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given string value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_string_add(DYNAMIC_COLUMN *str, LEX_STRING *string,
+ CHARSET_INFO *charset)
+{
+ int rc;
+ if ((rc= dynamic_column_var_uint_add(str, charset->number)))
+ return rc;
+ if (dynstr_append_mem(str, string->str, string->length))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read string value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_string_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ size_t len;
+ store_it_here->charset= get_charset(dynamic_column_var_uint_get(data, &len),
+ MYF(0));
+ if (store_it_here->charset == NULL || len > length)
+ return ER_DYNCOL_FORMAT;
+ data+= len;
+ store_it_here->string_value.length= (length-= len);
+ store_it_here->string_value.str= (char*)data;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given decimal value.
+
+ @param str the string where to put the value
+ @param val the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_decimal_add(DYNAMIC_COLUMN *str,
+ decimal_t *value)
+{
+ int rc;
+ uint bin_size= decimal_bin_size(value->intg + value->frac, value->frac);
+ if ((rc= dynamic_column_var_uint_add(str, value->intg)) ||
+ (rc= dynamic_column_var_uint_add(str, value->frac)))
+ return rc;
+ if (dynstr_realloc(str, bin_size))
+ return ER_DYNCOL_RESOURCE;
+ decimal2bin(value, (uchar *)str->str + str->length, value->intg + value->frac,
+ value->frac);
+ str->length+= bin_size;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Prepare the value to be used as decimal.
+
+ @param value The value structure which sould be setup.
+*/
+
+void dynamic_column_prepare_decimal(DYNAMIC_COLUMN_VALUE *value)
+{
+ value->decimal_value.buf= value->decimal_buffer;
+ value->decimal_value.len= DECIMAL_BUFF_LENGTH;
+ // just to be safe
+ value->type= DYN_COL_DECIMAL;
+ decimal_make_zero(&value->decimal_value);
+}
+
+
+/**
+ Read decimal value of given length from the string
+
+ @param store_it_here The structure to store the value
+ @param data The string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_decimal_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length __attribute__((unused)))
+{
+ size_t len;
+ uint intg, frac;
+
+ dynamic_column_prepare_decimal(store_it_here);
+ intg= dynamic_column_var_uint_get(data, &len);
+ data+= len;
+ frac= dynamic_column_var_uint_get(data, &len);
+ data+= len;
+ if (bin2decimal(data, &store_it_here->decimal_value, intg + frac, frac) !=
+ E_DEC_OK)
+ return ER_DYNCOL_FORMAT;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Append the string with given datetime value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_time_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ int rc;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if ((rc= dynamic_column_date_add(str, value)) ||
+ (rc= dynamic_column_time_add(str, value)))
+ return rc;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read datetime value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ uint rc= ER_DYNCOL_FORMAT;
+ /*
+ 0<----year----><mn><day>00000!<-hours--><min-><sec-><---microseconds--->
+ 12345678901234123412345 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456><123456><123456><123456>
+ */
+ if (length != 9)
+ goto err;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ if ((rc= dynamic_column_date_read_int(store_it_here, data, 3)) ||
+ (rc= dynamic_column_time_read_int(store_it_here, data + 3, 6)))
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return rc;
+}
+
+
+/**
+ Append the string with given time value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ uchar *buf= ((uchar *)str->str) + str->length;
+ if (dynstr_realloc(str, 6))
+ return ER_DYNCOL_RESOURCE;
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_DATE)
+ value->neg= value->second_part= value->hour=
+ value->minute= value->second= 0;
+ DBUG_ASSERT(value->hour <= 838);
+ DBUG_ASSERT(value->minute <= 59);
+ DBUG_ASSERT(value->second <= 59);
+ DBUG_ASSERT(value->second_part <= 999999);
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ buf[0]= (value->second_part & 0xff);
+ buf[1]= ((value->second_part & 0xff00) >> 8);
+ buf[2]= (((value->second & 0xf) << 4) |
+ ((value->second_part & 0xf0000) >> 16));
+ buf[3]= ((value->minute << 2) | ((value->second & 0x30) >> 4));
+ buf[4]= (value->hour & 0xff);
+ buf[5]= ((value->neg ? 0x4 : 0) | (value->hour >> 8));
+ str->length+= 6;
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Read time value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ store_it_here->time_value.year= store_it_here->time_value.month=
+ store_it_here->time_value.day= 0;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ return dynamic_column_time_read_int(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading time part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_time_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 6)
+ goto err;
+ /*
+ 00000!<-hours--><min-><sec-><---microseconds--->
+ 1123456789012345612345612345678901234567890
+ <123456><123456><123456><123456><123456><123456>
+ */
+ store_it_here->time_value.second_part= (data[0] |
+ (data[1] << 8) |
+ ((data[2] & 0xf) << 16));
+ store_it_here->time_value.second= ((data[2] >> 4) |
+ ((data[3] & 0x3) << 4));
+ store_it_here->time_value.minute= (data[3] >> 2);
+ store_it_here->time_value.hour= (((((uint)data[5]) & 0x3 ) << 8) | data[4]);
+ store_it_here->time_value.neg= ((data[5] & 0x4) ? 1 : 0);
+ if (store_it_here->time_value.second > 59 ||
+ store_it_here->time_value.minute > 59 ||
+ store_it_here->time_value.hour > 838 ||
+ store_it_here->time_value.second_part > 999999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given date value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_add(DYNAMIC_COLUMN *str, MYSQL_TIME *value)
+{
+ uchar *buf= ((uchar *)str->str) + str->length;
+ if (dynstr_realloc(str, 3))
+ return ER_DYNCOL_RESOURCE;
+ if (value->time_type == MYSQL_TIMESTAMP_NONE ||
+ value->time_type == MYSQL_TIMESTAMP_ERROR ||
+ value->time_type == MYSQL_TIMESTAMP_TIME)
+ value->year= value->month= value->day = 0;
+ DBUG_ASSERT(value->year <= 9999);
+ DBUG_ASSERT(value->month <= 12);
+ DBUG_ASSERT(value->day <= 31);
+ /*
+ 0<----year----><mn><day>
+ 012345678901234123412345
+ <123456><123456><123456>
+ */
+ buf[0]= (value->day |
+ ((value->month & 0x7) << 5));
+ buf[1]= ((value->month >> 3) | ((value->year & 0x7F) << 1));
+ buf[2]= (value->year >> 7);
+ str->length+= 3;
+ return ER_DYNCOL_OK;
+}
+
+
+
+/**
+ Read date value of given length from the packed string
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+my_bool dynamic_column_date_read(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ store_it_here->time_value.neg= store_it_here->time_value.second_part=
+ store_it_here->time_value.hour= store_it_here->time_value.minute=
+ store_it_here->time_value.second= 0;
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ return dynamic_column_date_read_int(store_it_here, data, length);
+}
+
+/**
+ Internal function for reading date part from the string.
+
+ @param store_it_here The structure to store the value
+ @param data The packed string which should be read
+ @param length The length (in bytes) of the value in nthe string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_date_read_int(DYNAMIC_COLUMN_VALUE *store_it_here,
+ uchar *data,
+ size_t length)
+{
+ if (length != 3)
+ goto err;
+ /*
+ 0<----year----><mn><day>
+ 12345678901234123412345
+ <123456><123456><123456>
+ */
+ store_it_here->time_value.day= (data[0] & 0x1f);
+ store_it_here->time_value.month= (((data[1] & 0x1) << 3) |
+ (data[0] >> 5));
+ store_it_here->time_value.year= ((((uint)data[2]) << 7) |
+ (data[1] >> 1));
+ if (store_it_here->time_value.day > 31 ||
+ store_it_here->time_value.month > 12 ||
+ store_it_here->time_value.year > 9999)
+ goto err;
+ return ER_DYNCOL_OK;
+
+err:
+ store_it_here->time_value.time_type= MYSQL_TIMESTAMP_ERROR;
+ return ER_DYNCOL_FORMAT;
+}
+
+
+/**
+ Append the string with given value.
+
+ @param str the string where to put the value
+ @param value the value to put in the string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int data_add(DYNAMIC_COLUMN *str, DYNAMIC_COLUMN_VALUE *value)
+{
+ switch (value->type) {
+ case DYN_COL_INT:
+ return dynamic_column_sint_add(str, value->long_value);
+ case DYN_COL_UINT:
+ return dynamic_column_uint_add(str, value->ulong_value);
+ case DYN_COL_DOUBLE:
+ return dynamic_column_double_add(str, value->double_value);
+ case DYN_COL_STRING:
+ return dynamic_column_string_add(str, &value->string_value,
+ value->charset);
+ case DYN_COL_DECIMAL:
+ return dynamic_column_decimal_add(str, &value->decimal_value);
+ case DYN_COL_DATETIME:
+ /* date+time in bits: 14 + 4 + 5 + 5 + 6 + 6 40bits = 5 bytes */
+ return dynamic_column_date_time_add(str, &value->time_value);
+ case DYN_COL_DATE:
+ /* date in dits: 14 + 4 + 5 = 23bits ~= 3bytes*/
+ return dynamic_column_date_add(str, &value->time_value);
+ case DYN_COL_TIME:
+ /* time in bits: 5 + 6 + 6 = 17bits ~= 3bytes*/
+ return dynamic_column_time_add(str, &value->time_value);
+ default:
+ DBUG_ASSERT(0);
+ return ER_DYNCOL_DATA;
+ }
+}
+
+
+/**
+ Calculate length of offset field for given data length
+
+ @param data_length Length of the data segment
+
+ @return number of bytes
+*/
+
+size_t dynamic_column_offset_bytes(size_t data_length)
+{
+ if (data_length < 0x1f) // all 1 value is reserved
+ return 1;
+ if (data_length < 0x1fff) // all 1 value is reserved
+ return 2;
+ if (data_length < 0x1fffff) // all 1 value is reserved
+ return 3;
+ if (data_length < 0x1fffffff) // all 1 value is reserved
+ return 4;
+ return 5;
+}
+
+/**
+ Store offset and type information in the given place
+
+ @param place Beginning of the index entry
+ @param offset_size Size of offset field in bytes
+ @param type Type to be written
+ @param offset Offset to be written
+*/
+
+void type_and_offset_store(uchar *place, size_t offset_size,
+ DYNAMIC_COLUMN_TYPE type,
+ size_t offset)
+{
+ ulong val = (((ulong) offset) << 3) | (type - 1);;
+ place+= COLUMN_NUMBER_SIZE;
+ DBUG_ASSERT(type != DYN_COL_NULL);
+ DBUG_ASSERT(((type - 1) & (~7)) == 0); // fit in 3 bits
+ switch (offset_size) {
+ case 1:
+ DBUG_ASSERT(offset < 0x1f); // all 1 value is reserved
+ place[0]= (uchar)val;
+ break;
+ case 2:
+ DBUG_ASSERT(offset < 0x1fff); // all 1 value is reserved
+ int2store(place, val);
+ break;
+ case 3:
+ DBUG_ASSERT(offset < 0x1fffff); // all 1 value is reserved
+ int3store(place, val);
+ break;
+ case 4:
+ DBUG_ASSERT(offset < 0x1fffffff); // all 1 value is reserved
+ int4store(place, val);
+ break;
+ default:
+ DBUG_ASSERT(0); // impossible
+ }
+}
+
+
+/**
+ Read offset and type information from index entry
+
+ @param type Where to put type info
+ @param offset Where to put offset info
+ @param place Beginning of the index entry
+ @param offset_size Size of offset field in bytes
+*/
+
+void type_and_offset_read(DYNAMIC_COLUMN_TYPE *type,
+ size_t *offset,
+ uchar *place, size_t offset_size)
+{
+ ulong val;
+ place+= COLUMN_NUMBER_SIZE; // skip column number
+ switch (offset_size) {
+ case 1:
+ val= (ulong)place[0];
+ break;
+ case 2:
+ val= uint2korr(place);
+ break;
+ case 3:
+ val= uint3korr(place);
+ break;
+ case 4:
+ val= uint4korr(place);
+ break;
+ default:
+ DBUG_ASSERT(0); // impossible
+ }
+ *type= (val & 0x7) + 1;
+ *offset= val >> 3;
+}
+
+/**
+ Comparator function for references on column numbers for qsort
+*/
+
+int column_sort(const void *a, const void *b)
+{
+ return **((uint **)a) - **((uint **)b);
+}
+
+/**
+ Write information to the fixed header
+
+ @param str String where to write the header
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of columns
+*/
+
+static void set_fixed_header(DYNAMIC_COLUMN *str,
+ uint offset_size,
+ uint column_count)
+{
+ DBUG_ASSERT(column_count <= 0xffff);
+ DBUG_ASSERT(offset_size <= 4);
+ str->str[0]= ((str->str[0] & ~DYNCOL_FLG_OFFSET) |
+ (offset_size - 1)); // size of offset
+ int2store(str->str + 1, column_count); // columns number
+ DBUG_ASSERT((str->str[0] & (~DYNCOL_FLG_KNOWN)) == 0);
+}
+
+
+/*
+ Read offset size (O) and column count (C) from string (S)
+*/
+
+#define read_fixed_header(S,O,C) do { \
+ (O)= ((S)->str[0] & DYNCOL_FLG_OFFSET) + 1; \
+ (C)= uint2korr((S)->str + 1); \
+}while(0);
+
+
+/*
+ Calculete entry size (E) and header size (H) by offset size (O) and column
+ count (C).
+*/
+
+#define calc_param(E,H,O,C) do { \
+ (E)= (O) + COLUMN_NUMBER_SIZE; \
+ (H)= (E) * (C); \
+}while(0);
+
+
+/**
+ Adds columns into the empty string
+
+ @param str String where to write the data
+ @param header_size Size of the header without fixed part
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of columns in the arrays
+ @parem non_null_count Number of non-null columns in the arrays
+ @param data_size Size of the data segment
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+ @param new_str True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_new_column_add(DYNAMIC_COLUMN *str,
+ size_t header_size,
+ size_t offset_size,
+ uint column_count,
+ uint non_null_count,
+ size_t data_size,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str)
+{
+ uchar *header_end;
+ uint **columns_order;
+ uint i;
+ uint entry_size= COLUMN_NUMBER_SIZE + offset_size;
+ int err= ER_DYNCOL_RESOURCE;
+ if (!(columns_order= malloc(sizeof(uint*)*column_count)))
+ return ER_DYNCOL_RESOURCE;
+ if (new_str)
+ {
+ if (dynamic_column_init_str(str,
+ data_size + header_size + DYNCOL_SYZERESERVE))
+ goto err;
+ }
+ else
+ {
+ str->length= 0;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ if (dynstr_realloc(str, data_size + header_size + DYNCOL_SYZERESERVE))
+ goto err;
+ }
+
+ /* sort columns for the header */
+ for (i= 0; i < column_count; i++)
+ columns_order[i]= column_numbers + i;
+ qsort(columns_order, (size_t)column_count, sizeof(uint*), &column_sort);
+ /* check numbers */
+ for (i= 0; i < column_count - 1; i++)
+ {
+ if (columns_order[i][0] == columns_order[i + 1][0])
+ {
+ err= ER_DYNCOL_DATA;
+ goto err;
+ }
+ }
+
+ DBUG_ASSERT(str->length == FIXED_HEADER_SIZE);
+ set_fixed_header(str, offset_size, non_null_count);
+ DBUG_ASSERT(str->max_length > str->length + header_size);
+ str->length+= header_size; // reserve place for header
+ header_end= (uchar *)str->str + FIXED_HEADER_SIZE;
+ for (i= 0; i < column_count; i++)
+ {
+ uint ord= columns_order[i] - column_numbers;
+ if (values[ord].type != DYN_COL_NULL)
+ {
+ int2store(header_end, column_numbers[ord]);
+ type_and_offset_store(header_end, offset_size,
+ values[ord].type,
+ str->length - header_size - FIXED_HEADER_SIZE);
+ if ((err= data_add(str, values + ord)))
+ goto err;
+ header_end+= entry_size;
+ }
+ }
+ err= ER_DYNCOL_OK;
+err:
+ free(columns_order);
+ return err;
+}
+
+/**
+ Create packed string which contains given columns (internal)
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+ @param new_str True if we need allocate new string
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create_many_int(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values,
+ my_bool new_str)
+{
+ size_t data_size= 0;
+ size_t header_size, offset_size;
+ uint i;
+ int not_null_column_count= column_count;
+ if (new_str)
+ bzero(str, sizeof(DYNAMIC_COLUMN)); // to make dynstr_free() working;
+ for (i= 0; i < column_count; i++)
+ {
+ data_size+= dynamic_column_value_len(values + i);
+ if (values[i].type == DYN_COL_NULL)
+ not_null_column_count--;
+ }
+
+ if ((offset_size= dynamic_column_offset_bytes(data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+
+ /* header entry is column number + offset&type */
+ header_size= not_null_column_count * (offset_size + 2);
+
+ return dynamic_new_column_add(str,
+ header_size, offset_size,
+ column_count,
+ not_null_column_count,
+ data_size,
+ column_numbers, values,
+ new_str);
+}
+
+
+/**
+ Create packed string which contains given columns
+
+ @param str String where to write the data
+ @param column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create_many(DYNAMIC_COLUMN *str,
+ uint column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ return dynamic_column_create_many_int(str, column_count,
+ column_numbers, values,
+ TRUE);
+}
+
+
+/**
+ Create packed string which contains given column
+
+ @param str String where to write the data
+ @param column_number Column number
+ @param value The columns value
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_create(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return dynamic_column_create_many(str, 1, &column_nr, value);
+}
+
+
+/**
+ Calculate length of data between given two header entries
+
+ @param entry Pointer to the first entry
+ @param entry_next Pointer to the last entry
+ @param header_end Pointer to the header end
+ @param offset_size Size of offset field in bytes
+ @param last_offset Size of the data segment
+
+ @return number of bytes
+*/
+
+size_t get_length_interval (uchar *entry, uchar *entry_next,
+ uchar *header_end, size_t offset_size,
+ size_t last_offset)
+{
+ size_t offset, offset_next;
+ DYNAMIC_COLUMN_TYPE type, type_next;
+ DBUG_ASSERT(entry < entry_next);
+ type_and_offset_read(&type, &offset, entry, offset_size);
+ if (entry_next >= header_end)
+ return last_offset - offset;
+ type_and_offset_read(&type_next, &offset_next, entry_next, offset_size);
+ return offset_next - offset;
+}
+
+/*
+ Calculate length of data of one column
+
+
+ @param entry Pointer to the first entry
+ @param header_end Pointer to the header end
+ @param offset_size Size of offset field in bytes
+ @param last_offset Size of the data segment
+
+ @return number of bytes
+*/
+
+size_t get_length(uchar *entry, uchar *header_end,
+ size_t offset_size,
+ size_t last_offset)
+{
+ return get_length_interval(entry,
+ entry + offset_size + COLUMN_NUMBER_SIZE,
+ header_end, offset_size, last_offset);
+}
+
+
+/**
+ Comparator function for references to header entries for qsort
+*/
+
+int header_compar(const void *a, const void *b)
+{
+ uint va= uint2korr((uchar*)a), vb= uint2korr((uchar*)b);
+ return (va > vb ? 1 : (va < vb ? -1 : 0));
+}
+
+
+/**
+ Find column and fill information about it
+
+ @param type Returns type of the column
+ @param data Returns a pointer to the data
+ @param length Returns length of the data
+ @param offset_size Size of offset field in bytes
+ @param column_count Number of column in the packed string
+ @param data_end Pointer to the data end
+ @param num Number of the column we want to fetch
+ @param entry_pos NULL or place where to put reference to the entry
+*/
+
+void find_column(DYNAMIC_COLUMN_TYPE *type, uchar **data, size_t *length,
+ uchar *header, size_t offset_size, uint column_count,
+ uchar *data_end, uint num, uchar **entry_pos)
+{
+ uchar *entry;
+ size_t offset;
+ size_t header_size, entry_size;
+ uchar key[2+4];
+ if (!entry_pos)
+ entry_pos= &entry;
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ int2store(key, num);
+ entry= bsearch(key, header, (size_t)column_count, entry_size,
+ &header_compar);
+ if (!entry)
+ {
+ *type= DYN_COL_NULL;
+ *entry_pos= NULL;
+ return;
+ }
+ type_and_offset_read(type, &offset, entry, offset_size);
+ *data= header + header_size + offset;
+ DBUG_ASSERT(*data < data_end);
+ *length= get_length(entry, header + header_size, offset_size,
+ data_end - (header + header_size));
+ *entry_pos= entry;
+ return;
+}
+
+
+/**
+ Make simple check of the packed string format
+
+ @param str The string to check
+
+ @retval FALSE OK
+ @retval TRUE error
+*/
+
+static my_bool dynamic_column_str_check(DYNAMIC_COLUMN *str)
+{
+ if (str == NULL)
+ return TRUE;
+ if (str->length == 0)
+ return FALSE;
+ return ((str->length < FIXED_HEADER_SIZE) ||
+ (str->str[0] & (~DYNCOL_FLG_KNOWN)));
+}
+
+/**
+ Get dynamic column value
+
+ @param str The packed string to extract the column
+ @param column_nr Number of column to fetch
+ @param store_it_here Where to store the extracted value
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_get(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *store_it_here)
+{
+ uchar *data;
+ size_t offset_size, length;
+ uint column_count;
+ int rc= ER_DYNCOL_FORMAT;
+
+ if (dynamic_column_str_check(str))
+ goto err;
+
+ if (str->length == 0)
+ goto null;
+
+ read_fixed_header(str, offset_size, column_count);
+ if (column_count == 0)
+ goto null;
+
+ find_column(&store_it_here->type, &data, &length,
+ (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, NULL);
+
+ switch (store_it_here->type)
+ {
+ case DYN_COL_INT:
+ rc= dynamic_column_sint_read(store_it_here, data, length);
+ break;
+ case DYN_COL_UINT:
+ rc= dynamic_column_uint_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DOUBLE:
+ rc= dynamic_column_double_read(store_it_here, data, length);
+ break;
+ case DYN_COL_STRING:
+ rc= dynamic_column_string_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DECIMAL:
+ rc= dynamic_column_decimal_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DATETIME:
+ rc= dynamic_column_date_time_read(store_it_here, data, length);
+ break;
+ case DYN_COL_DATE:
+ rc= dynamic_column_date_read(store_it_here, data, length);
+ break;
+ case DYN_COL_TIME:
+ rc= dynamic_column_time_read(store_it_here, data, length);
+ break;
+ case DYN_COL_NULL:
+ rc= ER_DYNCOL_OK;
+ break;
+ default:
+ goto err;
+ }
+ return rc;
+
+null:
+ rc= ER_DYNCOL_OK;
+err:
+ store_it_here->type= DYN_COL_NULL;
+ return rc;
+}
+
+/**
+ Delete column with given number from the packed string
+
+ @param str The packed string to delete the column
+ @param column_nr Number of column to delete
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_delete(DYNAMIC_COLUMN *str, uint column_nr)
+{
+ uchar *data, *header_entry, *read, *write;
+ size_t offset_size, new_offset_size, length, entry_size, new_entry_size,
+ header_size, new_header_size, data_size, new_data_size,
+ deleted_entry_offset;
+ uint column_count, i;
+ DYNAMIC_COLUMN_TYPE type;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ return ER_DYNCOL_OK; // no columns
+
+ read_fixed_header(str, offset_size, column_count);
+
+ if (column_count == 0)
+ return ER_DYNCOL_OK; // no columns
+
+ find_column(&type, &data, &length, (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, &header_entry);
+
+ if (type == DYN_COL_NULL)
+ return ER_DYNCOL_OK; // no such column
+
+ if (column_count == 1)
+ {
+ /* delete the only column */
+ str->length= FIXED_HEADER_SIZE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ return ER_DYNCOL_OK;
+ }
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ entry_size= 2 + offset_size;
+ header_size= entry_size * column_count;
+ data_size= str->length - FIXED_HEADER_SIZE - header_size;
+
+ new_data_size= data_size - length;
+ if ((new_offset_size= dynamic_column_offset_bytes(new_data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+ DBUG_ASSERT(new_offset_size <= offset_size);
+ calc_param(new_entry_size, new_header_size,
+ new_offset_size, column_count - 1);
+
+ deleted_entry_offset= (data - (uchar*)str->str) -
+ header_size - FIXED_HEADER_SIZE;
+
+
+ /* rewrite header*/
+ set_fixed_header(str, new_offset_size, column_count - 1);
+ for (i= 0, write= read= (uchar *)str->str + FIXED_HEADER_SIZE;
+ i < column_count;
+ i++, read+= entry_size, write+= new_entry_size)
+ {
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+ if (read == header_entry)
+ {
+#ifndef DBUG_OFF
+ nm= uint2korr(read);
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+ DBUG_ASSERT(nm == column_nr);
+ DBUG_ASSERT(offs == deleted_entry_offset);
+#endif
+ write-= new_entry_size; // do not move writer
+ continue; // skip removed field
+ }
+
+ nm= uint2korr(read),
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+
+ if (offs > deleted_entry_offset)
+ offs-= length; // data stored after removed data
+
+ int2store(write, nm);
+ type_and_offset_store(write, new_offset_size, tp, offs);
+ }
+
+ /* move data */
+ {
+ size_t first_chunk_len= (data - (uchar *)str->str) -
+ FIXED_HEADER_SIZE - header_size;
+ size_t second_chunk_len= new_data_size - first_chunk_len;
+ if (first_chunk_len)
+ memmove(str->str + FIXED_HEADER_SIZE + new_header_size,
+ str->str + FIXED_HEADER_SIZE + header_size,
+ first_chunk_len);
+ if (second_chunk_len)
+ memmove(str->str +
+ FIXED_HEADER_SIZE + new_header_size + first_chunk_len,
+ str->str +
+ FIXED_HEADER_SIZE + header_size + first_chunk_len + length,
+ second_chunk_len);
+ }
+
+ /* fix str length */
+ DBUG_ASSERT(str->length >=
+ FIXED_HEADER_SIZE + new_header_size + new_data_size);
+ str->length= FIXED_HEADER_SIZE + new_header_size + new_data_size;
+
+ return FALSE;
+}
+
+
+/**
+ Check existence of the column in the packed string
+
+ @param str The packed string to check the column
+ @param column_nr Number of column to check
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_exists(DYNAMIC_COLUMN *str, uint column_nr)
+{
+ uchar *data;
+ size_t offset_size, length;
+ uint column_count;
+ DYNAMIC_COLUMN_TYPE type;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ return ER_DYNCOL_NO; // no columns
+
+ read_fixed_header(str, offset_size, column_count);
+
+ if (column_count == 0)
+ return ER_DYNCOL_NO; // no columns
+
+ find_column(&type, &data, &length, (uchar*)str->str + FIXED_HEADER_SIZE,
+ offset_size, column_count, (uchar*)str->str + str->length,
+ column_nr, NULL);
+
+ return (type != DYN_COL_NULL ? ER_DYNCOL_YES : ER_DYNCOL_NO);
+}
+
+/**
+ List not-null columns in the packed string
+
+ @param str The packed string
+ @param array_of_uint Where to put reference on created array
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_list(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_uint)
+{
+ uchar *read;
+ size_t offset_size, entry_size;
+ uint column_count, i;
+
+ if (dynamic_column_str_check(str))
+ return ER_DYNCOL_FORMAT;
+
+ if (str->length == 0)
+ {
+ if (init_dynamic_array(array_of_uint, sizeof(uint),
+ 0, 10 CALLER_INFO))
+ return ER_DYNCOL_RESOURCE;
+ return ER_DYNCOL_OK; // no columns
+ }
+
+
+ read_fixed_header(str, offset_size, column_count);
+ entry_size= COLUMN_NUMBER_SIZE + offset_size;
+
+ if (init_dynamic_array(array_of_uint, sizeof(uint),
+ column_count, 10 CALLER_INFO))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0, read= (uchar *)str->str + FIXED_HEADER_SIZE;
+ i < column_count;
+ i++, read+= entry_size)
+ {
+ uint nm= uint2korr(read);
+ if (insert_dynamic(array_of_uint, (uchar *)&nm))
+ {
+ delete_dynamic(array_of_uint);
+ return ER_DYNCOL_RESOURCE;
+ }
+ }
+ return ER_DYNCOL_OK;
+}
+
+
+/**
+ Find the place of the column in the header or place where it should be put
+
+ @param num Number of the column
+ @param header Pointer to the header
+ @param entry_size Size of a header entry
+ @param column_count Number of columns in the packed string
+ @param entry Return pointer to the entry or next entry
+
+ @retval TRUE found
+ @retval FALSE pointer set to the next row
+*/
+
+my_bool find_place(uint num,
+ uchar *header, size_t entry_size, uint column_count,
+ uchar **entry)
+{
+ uint mid, start, end, val;
+ int flag;
+
+ start= 0;
+ end= column_count -1;
+ mid= 1;
+ while (start != end)
+ {
+ uint val;
+ mid= (start + end) / 2;
+ val= uint2korr(header + mid * entry_size);
+ if ((flag= CMP_NUM(num, val)) <= 0)
+ end= mid;
+ else
+ start= mid + 1;
+ }
+ if (start != mid)
+ {
+ val= uint2korr(header + start * entry_size);
+ flag= CMP_NUM(num, val);
+ }
+ *entry= header + start * entry_size;
+ if (flag > 0)
+ *entry+= entry_size; /* Point at next bigger key */
+ return flag == 0;
+}
+
+/*
+ Description of plan of adding/removing/updating a packed string
+*/
+
+typedef enum {PLAN_REPLACE, PLAN_ADD, PLAN_DELETE, PLAN_NOP} PLAN_ACT;
+
+struct st_plan {
+ DYNAMIC_COLUMN_VALUE *val;
+ uint *num;
+ uchar *place;
+ size_t length;
+ int hdelta, ddelta;
+ PLAN_ACT act;
+};
+typedef struct st_plan PLAN;
+
+
+int plan_sort(const void *a, const void *b)
+{
+ return ((PLAN *)a)->num[0] - ((PLAN *)b)->num[0];
+}
+
+#define DELTA_CHECK(S, D, C) \
+ if ((S) == 0) \
+ (S)= (D); \
+ else if (((S) > 0 && (D) < 0) || \
+ ((S) < 0 && (D) > 0)) \
+ { \
+ (C)= TRUE; \
+ break; \
+ } \
+
+/**
+ Update the packed string with the given columns
+
+ @param str String where to write the data
+ @param add_column_count Number of columns in the arrays
+ @param column_numbers Array of columns numbers
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+int dynamic_column_update_many(DYNAMIC_COLUMN *str,
+ uint add_column_count,
+ uint *column_numbers,
+ DYNAMIC_COLUMN_VALUE *values)
+{
+ PLAN *plan;
+ uchar *header_end;
+ long data_delta= 0;
+ uint i, j, k;
+ uint new_column_count, column_count,
+ not_null= add_column_count;
+ int rc;
+ int header_delta= 0;
+ int header_delta_sign, data_delta_sign;
+ size_t offset_size, entry_size, header_size, data_size;
+ size_t new_offset_size, new_entry_size, new_header_size, new_data_size;
+ size_t max_offset;
+ my_bool copy;
+
+
+ if (add_column_count == 0)
+ return ER_DYNCOL_OK;
+
+ if (!(plan= malloc(sizeof(PLAN) * (add_column_count + 1))))
+ return ER_DYNCOL_RESOURCE;
+
+ for (i= 0; i < add_column_count; i++)
+ {
+ plan[i].val= values + i;
+ plan[i].num= column_numbers + i;
+ if (values[i].type == DYN_COL_NULL)
+ not_null--;
+ }
+ qsort(plan, (size_t)add_column_count, sizeof(PLAN), &plan_sort);
+
+ if (str->length == 0)
+ {
+ /* There is no columns so we just add them */
+ if (not_null == 0)
+ {
+ if (str->str)
+ {
+ if (dynstr_realloc(str, FIXED_HEADER_SIZE + DYNCOL_SYZERESERVE))
+ return ER_DYNCOL_RESOURCE;
+ bzero(str->str, FIXED_HEADER_SIZE);
+ str->length= FIXED_HEADER_SIZE;
+ }
+ else
+ {
+ if (dynamic_column_init_str(str,
+ FIXED_HEADER_SIZE + DYNCOL_SYZERESERVE))
+ return ER_DYNCOL_RESOURCE;
+ }
+ return ER_DYNCOL_OK;
+ }
+ return dynamic_column_create_many_int(str, add_column_count,
+ column_numbers, values,
+ str->str == NULL);
+ }
+
+ read_fixed_header(str, offset_size, column_count);
+ new_column_count= column_count;
+
+ if (column_count == 0)
+ {
+ /* There is no columns so we just add them */
+ if (not_null == 0)
+ return ER_DYNCOL_OK;
+ return dynamic_column_create_many_int(str, add_column_count,
+ column_numbers, values,
+ FALSE);
+ }
+
+ calc_param(entry_size, header_size, offset_size, column_count);
+ max_offset= str->length - (FIXED_HEADER_SIZE + header_size);
+ header_end= (uchar *)str->str + FIXED_HEADER_SIZE + header_size;
+
+ /* check numbers */
+ for (i= 0; i < add_column_count; i++)
+ {
+ uchar *entry;
+ if (i < add_column_count - 1 && plan[i].num[0] == plan[i + 1].num[0])
+ {
+ rc= ER_DYNCOL_DATA;
+ goto err;
+ }
+
+ if (find_place(plan[i].num[0],
+ (uchar *)str->str + FIXED_HEADER_SIZE,
+ entry_size, column_count, &entry))
+ {
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ size_t entry_data_size;
+ new_column_count--;
+ /* replace the value */
+ plan[i].act= PLAN_DELETE;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta--;
+ /* get data delta in bytes */
+ entry_data_size= get_length(entry, header_end,
+ offset_size, max_offset);
+ plan[i].length= 0;
+ plan[i].ddelta= data_delta;
+ data_delta-= entry_data_size;
+ }
+ else
+ {
+ size_t entry_data_size;
+ /* replace the value */
+ plan[i].act= PLAN_REPLACE;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta;
+ /* get data delta in bytes */
+ entry_data_size= get_length(entry, header_end,
+ offset_size, max_offset);
+ plan[i].length= dynamic_column_value_len(plan[i].val);
+ plan[i].ddelta= data_delta;
+ data_delta+= plan[i].length - entry_data_size;
+ }
+ }
+ else
+ {
+ if (plan[i].val->type == DYN_COL_NULL)
+ {
+ plan[i].act= PLAN_NOP;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta;
+ /* get data delta in bytes */
+ plan[i].length= 0;
+ plan[i].ddelta= data_delta;
+ }
+ else
+ {
+ new_column_count++;
+ /* replace the value */
+ plan[i].act= PLAN_ADD;
+ /* get header delta in entries */
+ plan[i].hdelta= header_delta++;
+ /* get data delta in bytes */
+ plan[i].length= dynamic_column_value_len(plan[i].val);
+ plan[i].ddelta= data_delta;
+ data_delta+= plan[i].length;
+ }
+ }
+ plan[i].place= entry;
+ }
+ plan[add_column_count].hdelta= header_delta;
+ plan[add_column_count].ddelta= data_delta;
+ /*
+ check if it is only "incising" or only "decreasing" plan for (header
+ and data separately).
+ */
+ data_size= str->length - header_size - FIXED_HEADER_SIZE;
+ new_data_size= data_size + data_delta;
+ if ((new_offset_size= dynamic_column_offset_bytes(new_data_size)) >= 5)
+ return ER_DYNCOL_LIMIT;
+ //if (new_offset_size != offset_size) rewrite_header= TRUE;
+ header_delta_sign= new_offset_size - offset_size;
+ data_delta_sign= 0;
+ copy= FALSE;
+ for (i= 0; i < add_column_count; i++)
+ {
+ DELTA_CHECK(header_delta_sign, plan[i].hdelta, copy);
+ DELTA_CHECK(data_delta_sign, plan[i].ddelta, copy);
+ }
+
+ calc_param(new_entry_size, new_header_size,
+ new_offset_size, new_column_count);
+
+ //if (copy)
+ {
+ DYNAMIC_COLUMN tmp;
+ uchar *header_base= (uchar *)str->str + FIXED_HEADER_SIZE,
+ *write;
+ if (dynamic_column_init_str(&tmp,
+ (FIXED_HEADER_SIZE + new_header_size +
+ new_data_size + DYNCOL_SYZERESERVE)))
+ {
+ rc= ER_DYNCOL_RESOURCE;
+ goto err;
+ }
+ write= (uchar *)tmp.str + FIXED_HEADER_SIZE;
+ tmp.length= FIXED_HEADER_SIZE + new_header_size;
+ set_fixed_header(&tmp, new_offset_size, new_column_count);
+ data_delta= 0;
+ /* Copy data to the new string */
+ for (i= 0, j= 0; i < add_column_count || j < column_count; i++)
+ {
+ size_t first_offset;
+ uint start= j, end;
+ /* skip NOP */
+ while (i < add_column_count && plan[i].act == PLAN_NOP)
+ i++;
+ /* old data portion */
+ while (j < column_count &&
+ (i >= add_column_count ||
+ header_base + j * entry_size < plan[i].place))
+ j++;
+ end= j;
+ if (plan[i].act == PLAN_REPLACE || plan[i].act == PLAN_DELETE)
+ j++;
+ for (k= start; k < end; k++)
+ {
+ uchar *read= header_base + k * entry_size;
+ size_t offs;
+ uint nm;
+ DYNAMIC_COLUMN_TYPE tp;
+ nm= uint2korr(read);
+ type_and_offset_read(&tp, &offs, read,
+ offset_size);
+ if (k == start)
+ first_offset= offs;
+ offs+= plan[i].ddelta;
+ int2store(write, nm);
+ type_and_offset_store(write, new_offset_size, tp, offs);
+ write+= new_entry_size;
+ }
+ if (start < end)
+ {
+ size_t data_size=
+ get_length_interval(header_base + start * entry_size,
+ header_base + end * entry_size,
+ header_end, offset_size, max_offset);
+ memcpy(tmp.str + tmp.length, (char *)header_end + first_offset,
+ data_size);
+ tmp.length+= data_size;
+ }
+
+ /* new data adding */
+ if (i < add_column_count)
+ {
+ if(plan[i].act == PLAN_ADD ||
+ plan[i].act == PLAN_REPLACE)
+ {
+ int2store(write, plan[i].num[0]);
+ type_and_offset_store(write, new_offset_size,
+ plan[i].val[0].type,
+ tmp.length -
+ (FIXED_HEADER_SIZE + new_header_size));
+ write+= new_entry_size;
+ data_add(&tmp, plan[i].val);
+ }
+ data_delta= plan[i].ddelta;
+ }
+ }
+ dynamic_column_column_free(str);
+ *str= tmp;
+ }
+
+ rc= ER_DYNCOL_OK;
+err:
+ free(plan);
+ return rc;
+}
+
+
+/**
+ Update the packed string with the given column
+
+ @param str String where to write the data
+ @param column_number Array of columns number
+ @param values Array of columns values
+
+ @return ER_DYNCOL_* return code
+*/
+
+
+int dynamic_column_update(DYNAMIC_COLUMN *str, uint column_nr,
+ DYNAMIC_COLUMN_VALUE *value)
+{
+ return dynamic_column_update_many(str, 1, &column_nr, value);
+}
=== modified file 'sql-common/my_time.c'
--- sql-common/my_time.c 2011-03-09 13:47:59 +0000
+++ sql-common/my_time.c 2011-04-29 09:52:28 +0000
@@ -482,7 +482,7 @@
*/
my_bool str_to_time(const char *str, uint length, MYSQL_TIME *l_time,
- int *warning)
+ ulong fuzzydate, int *warning)
{
ulong date[5];
ulonglong value;
@@ -509,7 +509,7 @@
int was_cut;
enum enum_mysql_timestamp_type
res= str_to_datetime(str, length, l_time,
- (TIME_FUZZY_DATE | TIME_DATETIME_ONLY), &was_cut);
+ fuzzydate | TIME_DATETIME_ONLY, &was_cut);
if ((int) res >= (int) MYSQL_TIMESTAMP_ERROR)
{
if (was_cut)
@@ -1028,11 +1028,15 @@
int my_time_to_str(const MYSQL_TIME *l_time, char *to)
{
uint extra_hours= 0;
- return my_sprintf(to, (to, "%s%02u:%02u:%02u",
+ return my_sprintf(to, (to,
+ (l_time->second_part ?
+ "%s%02u:%02u:%02u.%06ld" :
+ "%s%02u:%02u:%02u"),
(l_time->neg ? "-" : ""),
extra_hours+ l_time->hour,
l_time->minute,
- l_time->second));
+ l_time->second,
+ l_time->second_part));
}
int my_date_to_str(const MYSQL_TIME *l_time, char *to)
@@ -1045,13 +1049,17 @@
int my_datetime_to_str(const MYSQL_TIME *l_time, char *to)
{
- return my_sprintf(to, (to, "%04u-%02u-%02u %02u:%02u:%02u",
+ return my_sprintf(to, (to,
+ (l_time->second_part ?
+ "%04u-%02u-%02u %02u:%02u:%02u.%06ld" :
+ "%04u-%02u-%02u %02u:%02u:%02u"),
l_time->year,
l_time->month,
l_time->day,
l_time->hour,
l_time->minute,
- l_time->second));
+ l_time->second,
+ l_time->second_part));
}
@@ -1062,6 +1070,9 @@
SYNOPSIS
my_TIME_to_string()
+ RETURN
+ length of string
+
NOTE
The string must have at least MAX_DATE_STRING_REP_LENGTH bytes reserved.
*/
@@ -1118,7 +1129,6 @@
long part1,part2;
*was_cut= 0;
- bzero((char*) time_res, sizeof(*time_res));
time_res->time_type=MYSQL_TIMESTAMP_DATE;
if (nr == LL(0) || nr >= LL(10000101000000))
@@ -1171,6 +1181,8 @@
time_res->hour= (int) (part2/10000L); part2%=10000L;
time_res->minute=(int) part2 / 100;
time_res->second=(int) part2 % 100;
+ time_res->second_part= 0;
+ time_res->neg= 0;
if (time_res->year <= 9999 && time_res->month <= 12 &&
time_res->day <= 31 && time_res->hour <= 23 &&
@@ -1179,15 +1191,58 @@
return nr;
/* Don't want to have was_cut get set if NO_ZERO_DATE was violated. */
- if (!nr && (flags & TIME_NO_ZERO_DATE))
- return LL(-1);
+ if (nr || !(flags & TIME_NO_ZERO_DATE))
+ *was_cut= 1;
+ return LL(-1);
err:
- *was_cut= 1;
+ {
+ /* reset everything except time_type */
+ enum enum_mysql_timestamp_type save= time_res->time_type;
+ bzero((char*) time_res, sizeof(*time_res));
+ time_res->time_type= save; /* Restore range */
+ *was_cut= 1; /* Found invalid date */
+ }
return LL(-1);
}
+/*
+ Convert a double to a date/datetime
+
+ Note that for sub seconds, the precision of double is not good enough!
+
+ RESULT:
+ 0 ok
+ 1 error ; ltime is zeroed
+*/
+
+my_bool double_to_datetime(double value, MYSQL_TIME *ltime,
+ uint fuzzydate)
+{
+ double datepart_value;
+ int was_cut;
+
+ if (value < 0 || value > 99991231235959.0)
+ {
+ bzero((char*) ltime, sizeof(*ltime));
+ return 1;
+ }
+
+ datepart_value= floor(value);
+ if (number_to_datetime((longlong) datepart_value, ltime, fuzzydate,
+ &was_cut) == LL(-1))
+ return 1;
+ if (ltime->time_type == MYSQL_TIMESTAMP_DATETIME ||
+ ltime->time_type == MYSQL_TIMESTAMP_TIME)
+ {
+ /* Add sub seconds to results */
+ ltime->second_part= floor((value - datepart_value)* TIME_SUBSECOND_RANGE);
+ }
+ return 0;
+}
+
+
/* Convert time value to integer in YYYYMMDDHHMMSS format */
ulonglong TIME_to_ulonglong_datetime(const MYSQL_TIME *my_time)
=== modified file 'sql/field.cc'
--- sql/field.cc 2011-03-09 13:47:59 +0000
+++ sql/field.cc 2011-04-29 09:52:28 +0000
@@ -1753,7 +1753,10 @@
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_time_with_warn(res->ptr(), res->length(), ltime))
+ str_to_time_with_warn(res->ptr(), res->length(), ltime,
+ table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE |
+ MODE_INVALID_DATES)))
return 1;
return 0;
}
@@ -3866,40 +3869,11 @@
int Field_longlong::store(double nr)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- int error= 0;
+ bool error;
longlong res;
- nr= rint(nr);
- if (unsigned_flag)
- {
- if (nr < 0)
- {
- res=0;
- error= 1;
- }
- else if (nr >= (double) ULONGLONG_MAX)
- {
- res= ~(longlong) 0;
- error= 1;
- }
- else
- res=(longlong) double2ulonglong(nr);
- }
- else
- {
- if (nr <= (double) LONGLONG_MIN)
- {
- res= LONGLONG_MIN;
- error= (nr < (double) LONGLONG_MIN);
- }
- else if (nr >= (double) (ulonglong) LONGLONG_MAX)
- {
- res= LONGLONG_MAX;
- error= (nr > (double) LONGLONG_MAX);
- }
- else
- res=(longlong) nr;
- }
+ res= double_to_longlong(nr, unsigned_flag, &error);
+
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
@@ -4144,7 +4118,18 @@
int Field_float::store(double nr)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- int error= truncate(&nr, FLT_MAX);
+ int error= truncate_double(&nr, field_length,
+ not_fixed ? NOT_FIXED_DEC : dec,
+ unsigned_flag, FLT_MAX);
+ if (error)
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ if (error < 0) // Wrong double value
+ {
+ error= 1;
+ set_null();
+ }
+ }
float j= (float)nr;
#ifdef WORDS_BIGENDIAN
@@ -4406,7 +4391,18 @@
int Field_double::store(double nr)
{
ASSERT_COLUMN_MARKED_FOR_WRITE_OR_COMPUTED;
- int error= truncate(&nr, DBL_MAX);
+ int error= truncate_double(&nr, field_length,
+ not_fixed ? NOT_FIXED_DEC : dec,
+ unsigned_flag, DBL_MAX);
+ if (error)
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ if (error < 0) // Wrong double value
+ {
+ error= 1;
+ set_null();
+ }
+ }
#ifdef WORDS_BIGENDIAN
if (table->s->db_low_byte_first)
@@ -4430,28 +4426,31 @@
If a field has fixed length, truncate the double argument pointed to by 'nr'
appropriately.
Also ensure that the argument is within [-max_value; max_value] range.
+
+ return
+ 0 ok
+ -1 Illegal double value
+ 1 Value was truncated
*/
-int Field_real::truncate(double *nr, double max_value)
+int truncate_double(double *nr, uint field_length, uint dec,
+ bool unsigned_flag, double max_value)
{
- int error= 1;
+ int error= 0;
double res= *nr;
if (isnan(res))
{
- res= 0;
- set_null();
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- goto end;
+ *nr= 0;
+ return -1;
}
else if (unsigned_flag && res < 0)
{
- res= 0;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
- goto end;
+ *nr= 0;
+ return 1;
}
- if (!not_fixed)
+ if (dec < NOT_FIXED_DEC)
{
uint order= field_length - dec;
uint step= array_elements(log_10) - 1;
@@ -4467,22 +4466,70 @@
if (res < -max_value)
{
- res= -max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ res= -max_value;
+ error= 1;
}
else if (res > max_value)
{
res= max_value;
- set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ error= 1;
}
- else
- error= 0;
-end:
*nr= res;
return error;
}
+/*
+ Convert double to longlong / ulonglong.
+ If double is outside of range, adjust return value and set error.
+
+ SYNOPSIS
+ double_to_longlong()
+ nr Number to convert
+ unsigned_flag 1 if result is unsigned
+ error Will be set to 1 in case of overflow.
+*/
+
+longlong double_to_longlong(double nr, bool unsigned_flag, bool *error)
+{
+ longlong res;
+
+ *error= 0;
+
+ nr= rint(nr);
+ if (unsigned_flag)
+ {
+ if (nr < 0)
+ {
+ res= 0;
+ *error= 1;
+ }
+ else if (nr >= (double) ULONGLONG_MAX)
+ {
+ res= ~(longlong) 0;
+ *error= 1;
+ }
+ else
+ res= (longlong) double2ulonglong(nr);
+ }
+ else
+ {
+ if (nr <= (double) LONGLONG_MIN)
+ {
+ res= LONGLONG_MIN;
+ *error= (nr < (double) LONGLONG_MIN);
+ }
+ else if (nr >= (double) (ulonglong) LONGLONG_MAX)
+ {
+ res= LONGLONG_MAX;
+ *error= (nr > (double) LONGLONG_MAX);
+ }
+ else
+ res= (longlong) nr;
+ }
+ return res;
+}
+
int Field_real::store_decimal(const my_decimal *dm)
{
@@ -4511,6 +4558,7 @@
ASSERT_COLUMN_MARKED_FOR_READ;
double j;
longlong res;
+ bool error;
#ifdef WORDS_BIGENDIAN
if (table->s->db_low_byte_first)
{
@@ -4519,20 +4567,9 @@
else
#endif
doubleget(j,ptr);
- /* Check whether we fit into longlong range */
- if (j <= (double) LONGLONG_MIN)
- {
- res= (longlong) LONGLONG_MIN;
- goto warn;
- }
- if (j >= (double) (ulonglong) LONGLONG_MAX)
- {
- res= (longlong) LONGLONG_MAX;
- goto warn;
- }
- return (longlong) rint(j);
-warn:
+ res= double_to_longlong(j, 0, &error);
+ if (error)
{
char buf[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
String tmp(buf, sizeof(buf), &my_charset_latin1), *str;
@@ -5147,7 +5184,10 @@
int error= 0;
int warning;
- if (str_to_time(from, len, <ime, &warning))
+ if (str_to_time(from, len, <ime,
+ table->in_use->variables.sql_mode &
+ (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE |
+ MODE_INVALID_DATES), &warning))
{
tmp=0L;
error= 2;
@@ -5305,6 +5345,7 @@
ltime.hour= (uint) (tmp/10000);
ltime.minute= (uint) (tmp/100 % 100);
ltime.second= (uint) (tmp % 100);
+ ltime.second_part= 0;
make_time((DATE_TIME_FORMAT*) 0, <ime, val_buffer);
return val_buffer;
}
=== modified file 'sql/field.h'
--- sql/field.h 2011-03-09 13:47:59 +0000
+++ sql/field.h 2011-04-29 09:52:28 +0000
@@ -33,6 +33,9 @@
struct st_cache_field;
int field_conv(Field *to,Field *from);
+int truncate_double(double *nr, uint field_length, uint dec,
+ bool unsigned_flag, double max_value);
+longlong double_to_longlong(double nr, bool unsigned_flag, bool *error);
inline uint get_enum_pack_length(int elements)
{
@@ -808,7 +811,6 @@
{}
int store_decimal(const my_decimal *);
my_decimal *val_decimal(my_decimal *);
- int truncate(double *nr, double max_length);
uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); }
virtual const uchar *unpack(uchar* to, const uchar *from,
=== modified file 'sql/item.cc'
--- sql/item.cc 2011-04-27 04:11:06 +0000
+++ sql/item.cc 2011-04-29 09:52:28 +0000
@@ -985,19 +985,13 @@
bool Item::get_date(MYSQL_TIME *ltime,uint fuzzydate)
{
- if (result_type() == STRING_RESULT)
- {
- char buff[40];
- String tmp(buff,sizeof(buff), &my_charset_bin),*res;
- if (!(res=val_str(&tmp)) ||
- str_to_datetime_with_warn(res->ptr(), res->length(),
- ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
- goto err;
- }
- else
- {
+ switch (result_type()) {
+ case INT_RESULT:
+ {
+ int was_cut;
longlong value= val_int();
- int was_cut;
+ if (null_value)
+ goto err;
if (number_to_datetime(value, ltime, fuzzydate, &was_cut) == LL(-1))
{
char buff[22], *end;
@@ -1005,8 +999,52 @@
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
buff, (int) (end-buff), MYSQL_TIMESTAMP_NONE,
NullS);
- goto err;
- }
+ null_value= 1;
+ return 1;
+ }
+ break;
+ }
+ case REAL_RESULT:
+ {
+ double value= val_real();
+ if (null_value)
+ goto err;
+ if (double_to_datetime_with_warn(value, ltime, fuzzydate))
+ {
+ null_value= 1;
+ return 1;
+ }
+ break;
+ }
+ case DECIMAL_RESULT: // This we could do better but string is ok for now
+ {
+ my_decimal value, *res;
+ if (!(res= val_decimal(&value)))
+ goto err; // Null
+ if (decimal_to_datetime_with_warn(res, ltime, fuzzydate))
+ {
+ null_value= 1;
+ return 1;
+ }
+ break;
+ }
+ default:
+ {
+ /*
+ Default go trough string as this is the safest way to ensure that
+ we also get the microseconds.
+ */
+ char buff[40];
+ String tmp(buff,sizeof(buff), &my_charset_bin),*res;
+ if (!(res=val_str(&tmp)) ||
+ str_to_datetime_with_warn(res->ptr(), res->length(),
+ ltime, fuzzydate) <= MYSQL_TIMESTAMP_ERROR)
+ {
+ null_value= 1;
+ goto err;
+ }
+ break;
+ }
}
return 0;
@@ -1026,7 +1064,11 @@
char buff[40];
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
if (!(res=val_str(&tmp)) ||
- str_to_time_with_warn(res->ptr(), res->length(), ltime))
+ str_to_time_with_warn(res->ptr(), res->length(), ltime,
+ TIME_FUZZY_DATE |
+ (current_thd->variables.sql_mode &
+ (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE |
+ MODE_INVALID_DATES))))
{
bzero((char*) ltime,sizeof(*ltime));
return 1;
=== modified file 'sql/item.h'
--- sql/item.h 2011-04-27 04:11:06 +0000
+++ sql/item.h 2011-04-29 09:52:28 +0000
@@ -18,6 +18,10 @@
#pragma interface /* gcc class implementation */
#endif
+C_MODE_START
+#include <ma_dyncol.h>
+C_MODE_END
+
inline
bool trace_unsupported_func(const char *where, const char *processor_name)
{
@@ -471,6 +475,17 @@
};
+struct st_dyncall_create_def
+{
+ Item *num, *value;
+ CHARSET_INFO *cs;
+ uint len, frac;
+ DYNAMIC_COLUMN_TYPE type;
+};
+
+typedef struct st_dyncall_create_def DYNCALL_CREATE_DEF;
+
+
typedef bool (Item::*Item_processor) (uchar *arg);
/*
Analyzer function
@@ -804,7 +819,11 @@
{ return val_decimal(val); }
virtual bool val_bool_result() { return val_bool(); }
virtual bool is_null_result() { return is_null(); }
-
+ /*
+ Returns 1 if result type and collation for val_str() can change between
+ calls
+ */
+ virtual bool dynamic_result() { return 0; }
/*
Bitmap of tables used by item
(note: if you need to check dependencies on individual columns, check out
=== modified file 'sql/item_cmpfunc.cc'
--- sql/item_cmpfunc.cc 2011-04-27 04:11:06 +0000
+++ sql/item_cmpfunc.cc 2011-04-29 09:52:28 +0000
@@ -6074,3 +6074,34 @@
DBUG_ASSERT(0);
return NULL;
}
+
+
+longlong Item_func_dyncol_exists::val_int()
+{
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+ DYNAMIC_COLUMN col;
+ String *str;
+ uint num;
+ int rc;
+
+ num= args[1]->val_int();
+ str= args[0]->val_str(&tmp);
+ if (args[0]->null_value || args[1]->null_value)
+ goto null;
+ col.length= str->length();
+ /* We do not change the string, so could do this trick */
+ col.str= (char *)str->ptr();
+ rc= dynamic_column_exists(&col, num);
+ if (rc < 0)
+ {
+ dynamic_column_error_message(rc);
+ goto null;
+ }
+ null_value= FALSE;
+ return rc == ER_DYNCOL_YES;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
=== modified file 'sql/item_cmpfunc.h'
--- sql/item_cmpfunc.h 2011-04-27 04:11:06 +0000
+++ sql/item_cmpfunc.h 2011-04-29 09:52:28 +0000
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates.
+/*dyncol_exists Copyright (c) 2000, 2010, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1869,3 +1869,11 @@
bool get_mysql_time_from_str(THD *thd, String *str, timestamp_type warn_type,
const char *warn_name, MYSQL_TIME *l_time);
+
+class Item_func_dyncol_exists :public Item_bool_func
+{
+public:
+ Item_func_dyncol_exists(Item *str, Item *num) :Item_bool_func(str, num) {}
+ longlong val_int();
+ const char *func_name() const { return "column_exists"; }
+};
=== modified file 'sql/item_create.cc'
--- sql/item_create.cc 2011-02-20 16:51:43 +0000
+++ sql/item_create.cc 2011-04-29 09:52:28 +0000
@@ -27,6 +27,50 @@
/*
=============================================================================
+ HELPER FUNCTIONS
+=============================================================================
+*/
+
+/*
+ Get precision and scale for a declaration
+
+ return
+ 0 ok
+ 1 error
+*/
+
+bool get_length_and_scale(ulonglong length, ulonglong decimals,
+ ulong *out_length, uint *out_decimals,
+ uint max_precision, uint max_scale,
+ const char *name)
+{
+ if (length > (ulonglong) max_precision)
+ {
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), (int) length, name,
+ max_precision);
+ return 1;
+ }
+ if (decimals > (ulonglong) max_scale)
+ {
+ my_error(ER_TOO_BIG_SCALE, MYF(0), (int) decimals, name,
+ DECIMAL_MAX_SCALE);
+ return 1;
+ }
+
+ *out_length= (ulong) length;
+ *out_decimals= (uint) decimals;
+ my_decimal_trim(out_length, out_decimals);
+
+ if (*out_length < *out_decimals)
+ {
+ my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
+ return 1;
+ }
+ return 0;
+}
+
+/*
+=============================================================================
LOCAL DECLARATIONS
=============================================================================
*/
@@ -5054,6 +5098,17 @@
CHARSET_INFO *cs)
{
Item *UNINIT_VAR(res);
+ ulonglong length= 0, decimals= 0;
+ int error;
+
+ /*
+ We don't have to check for error here as sql_yacc.yy has guaranteed
+ that the values are in range of ulonglong
+ */
+ if (c_len)
+ length= (ulonglong) my_strtoll10(c_len, NULL, &error);
+ if (c_dec)
+ decimals= (ulonglong) my_strtoll10(c_dec, NULL, &error);
switch (cast_type) {
case ITEM_CAST_BINARY:
@@ -5076,72 +5131,45 @@
break;
case ITEM_CAST_DECIMAL:
{
- ulong len= 0;
- uint dec= 0;
-
- if (c_len)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if (errno != 0)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name,
- DECIMAL_MAX_PRECISION);
- return NULL;
- }
- len= decoded_size;
- }
-
- if (c_dec)
- {
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_dec, NULL, 10);
- if ((errno != 0) || (decoded_size > UINT_MAX))
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name,
- DECIMAL_MAX_SCALE);
- return NULL;
- }
- dec= decoded_size;
- }
- my_decimal_trim(&len, &dec);
- if (len < dec)
- {
- my_error(ER_M_BIGGER_THAN_D, MYF(0), "");
- return 0;
- }
- if (len > DECIMAL_MAX_PRECISION)
- {
- my_error(ER_TOO_BIG_PRECISION, MYF(0), len, a->name,
- DECIMAL_MAX_PRECISION);
- return 0;
- }
- if (dec > DECIMAL_MAX_SCALE)
- {
- my_error(ER_TOO_BIG_SCALE, MYF(0), dec, a->name,
- DECIMAL_MAX_SCALE);
- return 0;
- }
+ ulong len;
+ uint dec;
+ if (get_length_and_scale(length, decimals, &len, &dec,
+ DECIMAL_MAX_PRECISION, DECIMAL_MAX_SCALE,
+ a->name))
+ return NULL;
res= new (thd->mem_root) Item_decimal_typecast(a, len, dec);
break;
}
+ case ITEM_CAST_DOUBLE:
+ {
+ ulong len;
+ uint dec;
+
+ if (!c_len)
+ {
+ length= DBL_DIG+7;
+ decimals= NOT_FIXED_DEC;
+ }
+ else if (get_length_and_scale(length, decimals, &len, &dec,
+ DECIMAL_MAX_PRECISION, NOT_FIXED_DEC-1,
+ a->name))
+ return NULL;
+ res= new (thd->mem_root) Item_double_typecast(a, length, decimals);
+ break;
+ }
case ITEM_CAST_CHAR:
{
int len= -1;
CHARSET_INFO *real_cs= (cs ? cs : thd->variables.collation_connection);
if (c_len)
{
- ulong decoded_size;
- errno= 0;
- decoded_size= strtoul(c_len, NULL, 10);
- if ((errno != 0) || (decoded_size > MAX_FIELD_BLOBLENGTH))
+ if (length > MAX_FIELD_BLOBLENGTH)
{
- my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char", MAX_FIELD_BLOBLENGTH);
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), "cast as char",
+ MAX_FIELD_BLOBLENGTH);
return NULL;
}
- len= (int) decoded_size;
+ len= (int) length;
}
res= new (thd->mem_root) Item_char_typecast(a, len, real_cs);
break;
@@ -5155,3 +5183,99 @@
}
return res;
}
+
+
+static List<Item> *create_func_dyncol_prepare(THD *thd,
+ DYNCALL_CREATE_DEF **dfs,
+ List<DYNCALL_CREATE_DEF> &list)
+{
+ List_iterator_fast<DYNCALL_CREATE_DEF> li(list);
+ List<Item> *args= new (thd->mem_root) List<Item>;
+
+ *dfs=
+ (DYNCALL_CREATE_DEF *)alloc_root(thd->mem_root,
+ sizeof(DYNCALL_CREATE_DEF) *
+ list.elements);
+ DYNCALL_CREATE_DEF *def;
+ uint i= 0;
+
+ if (!args || !dfs)
+ return NULL;
+
+ while ((def= li++))
+ {
+ dfs[0][i++]= *def;
+ args->push_back(def->num);
+ args->push_back(def->value);
+ }
+ return args;
+}
+
+Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list)
+{
+ List<Item> *args;
+ DYNCALL_CREATE_DEF *dfs;
+ if (!(args= create_func_dyncol_prepare(thd, &dfs, list)))
+ return NULL;
+
+ return new (thd->mem_root) Item_func_dyncol_create(*args, dfs);
+}
+
+
+Item *create_func_dyncol_add(THD *thd, Item *str,
+ List<DYNCALL_CREATE_DEF> &list)
+{
+ List<Item> *args;
+ DYNCALL_CREATE_DEF *dfs;
+
+ if (!(args= create_func_dyncol_prepare(thd, &dfs, list)))
+ return NULL;
+
+ args->push_back(str);
+
+ return new (thd->mem_root) Item_func_dyncol_add(*args, dfs);
+}
+
+
+
+Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
+{
+ DYNCALL_CREATE_DEF *dfs;
+ List<Item> *args= new (thd->mem_root) List<Item>;
+ List_iterator_fast<Item> it(nums);
+ Item *num;
+ uint i;
+
+ dfs=
+ (DYNCALL_CREATE_DEF *)alloc_root(thd->mem_root,
+ sizeof(DYNCALL_CREATE_DEF) *
+ nums.elements);
+ if (!args || !dfs)
+ return NULL;
+
+ for (i= 0; (num= it++); i++)
+ {
+ dfs[i].num= num;
+ dfs[i].value= new Item_null();
+ dfs[i].type= DYN_COL_INT;
+ args->push_back(dfs[i].num);
+ args->push_back(dfs[i].value);
+ }
+
+ args->push_back(str);
+
+ return new (thd->mem_root) Item_func_dyncol_add(*args, dfs);
+}
+
+
+Item *create_func_dyncol_get(THD *thd, Item *str, Item *num,
+ Cast_target cast_type,
+ const char *c_len, const char *c_dec,
+ CHARSET_INFO *cs)
+{
+ Item *res;
+
+ if (!(res= new (thd->mem_root) Item_dyncol_get(str, num)))
+ return res; // Return NULL
+ return create_func_cast(thd, res, cast_type, c_len, c_dec, cs);
+}
=== modified file 'sql/item_create.h'
--- sql/item_create.h 2011-02-20 16:51:43 +0000
+++ sql/item_create.h 2011-04-29 09:52:28 +0000
@@ -164,5 +164,15 @@
create_func_cast(THD *thd, Item *a, Cast_target cast_type,
const char *len, const char *dec,
CHARSET_INFO *cs);
+
+Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list);
+Item *create_func_dyncol_add(THD *thd, Item *str,
+ List<DYNCALL_CREATE_DEF> &list);
+Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums);
+Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
+ Cast_target cast_type,
+ const char *c_len, const char *c_dec,
+ CHARSET_INFO *cs);
+
#endif
=== modified file 'sql/item_func.cc'
--- sql/item_func.cc 2011-03-24 14:34:06 +0000
+++ sql/item_func.cc 2011-04-29 09:52:28 +0000
@@ -989,9 +989,24 @@
null_value= args[0]->null_value;
return value;
}
+ else if (args[0]->dynamic_result())
+ {
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 0; // Mark that we want to have a signed value
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag && value < 0)
+ goto err; // Warn about overflow
+ return value;
+ }
value= val_int_from_str(&error);
if (value < 0 && error == 0)
+ goto err;
+ return value;
+
+err:
+ if (value < 0 && error == 0)
{
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Cast to signed converted positive out-of-range integer to "
@@ -1024,19 +1039,36 @@
value= 0;
return value;
}
+ else if (args[0]->dynamic_result())
+ {
+ /* We come here when argument has an unknown type */
+ args[0]->unsigned_flag= 1; // Mark that we want to have an unsigned value
+ value= args[0]->val_int();
+ null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
+ return value;
+ }
else if (args[0]->cast_to_int_type() != STRING_RESULT ||
args[0]->result_as_longlong())
{
value= args[0]->val_int();
null_value= args[0]->null_value;
+ if (!null_value && args[0]->unsigned_flag == 0 && value < 0)
+ goto err; // Warn about overflow
return value;
}
value= val_int_from_str(&error);
if (error < 0)
- push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
- "Cast to unsigned converted negative integer to it's "
- "positive complement");
+ goto err;
+
+ return value;
+
+err:
+ push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "Cast to unsigned converted negative integer to it's "
+ "positive complement");
return value;
}
@@ -1134,6 +1166,51 @@
}
+double Item_double_typecast::val_real()
+{
+ int error;
+ double tmp= args[0]->val_real();
+ if ((null_value= args[0]->null_value))
+ return 0.0;
+
+ if ((error= truncate_double(&tmp, max_length, decimals, 0, DBL_MAX)))
+ {
+ push_warning_printf(current_thd,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_DATA_OUT_OF_RANGE,
+ ER(ER_WARN_DATA_OUT_OF_RANGE),
+ name, 1);
+ if (error < 0)
+ {
+ null_value= 1; // Illegal value
+ tmp= 0.0;
+ }
+ }
+ return tmp;
+}
+
+
+void Item_double_typecast::print(String *str, enum_query_type query_type)
+{
+ char len_buf[20*3 + 1];
+ char *end;
+
+ str->append(STRING_WITH_LEN("cast("));
+ args[0]->print(str, query_type);
+ str->append(STRING_WITH_LEN(" as double"));
+ if (decimals != NOT_FIXED_DEC)
+ {
+ str->append('(');
+ end= int10_to_str(max_length, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(',');
+ end= int10_to_str(decimals, len_buf,10);
+ str->append(len_buf, (uint32) (end - len_buf));
+ str->append(')');
+ }
+ str->append(')');
+}
+
double Item_func_plus::real_op()
{
double value= args[0]->val_real() + args[1]->val_real();
=== modified file 'sql/item_func.h'
--- sql/item_func.h 2011-03-24 14:34:06 +0000
+++ sql/item_func.h 2011-04-29 09:52:28 +0000
@@ -470,12 +470,29 @@
my_decimal *val_decimal(my_decimal*);
enum Item_result result_type () const { return DECIMAL_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
- void fix_length_and_dec() {};
+ void fix_length_and_dec() {}
const char *func_name() const { return "decimal_typecast"; }
virtual void print(String *str, enum_query_type query_type);
};
+class Item_double_typecast :public Item_real_func
+{
+public:
+ Item_double_typecast(Item *a, int len, int dec) :Item_real_func(a)
+ {
+ decimals= dec;
+ max_length= len;
+ }
+ double val_real();
+ enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
+ void fix_length_and_dec() { maybe_null= 1; }
+ const char *func_name() const { return "double_typecast"; }
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+
class Item_func_additive_op :public Item_num_op
{
public:
@@ -1713,7 +1730,7 @@
{
ITEM_CAST_BINARY, ITEM_CAST_SIGNED_INT, ITEM_CAST_UNSIGNED_INT,
ITEM_CAST_DATE, ITEM_CAST_TIME, ITEM_CAST_DATETIME, ITEM_CAST_CHAR,
- ITEM_CAST_DECIMAL
+ ITEM_CAST_DECIMAL, ITEM_CAST_DOUBLE
};
@@ -1877,4 +1894,3 @@
return trace_unsupported_by_check_vcol_func_processor(func_name());
}
};
-
=== modified file 'sql/item_strfunc.cc'
--- sql/item_strfunc.cc 2011-03-24 14:34:06 +0000
+++ sql/item_strfunc.cc 2011-04-29 09:52:28 +0000
@@ -3451,3 +3451,740 @@
return str;
}
+
+
+Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args,
+ DYNCALL_CREATE_DEF *dfs)
+ : Item_str_func(args), defs(dfs), vals(0), nums(0)
+{
+ DBUG_ASSERT((args.elements & 0x1) == 0); // even number of arguments
+}
+
+
+bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref)
+{
+ bool res= Item_func::fix_fields(thd, ref); // no need Item_str_func here
+ vals= (DYNAMIC_COLUMN_VALUE *) alloc_root(thd->mem_root,
+ sizeof(DYNAMIC_COLUMN_VALUE) *
+ (arg_count / 2));
+ nums= (uint *) alloc_root(thd->mem_root,
+ sizeof(uint) * (arg_count / 2));
+ return res || vals == 0 || nums == 0;
+}
+
+
+void Item_func_dyncol_create::fix_length_and_dec()
+{
+ maybe_null= TRUE;
+ collation.set(&my_charset_bin);
+ decimals= 0;
+}
+
+void Item_func_dyncol_create::prepare_arguments()
+{
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String *res, tmp(buff, sizeof(buff), &my_charset_bin);
+ uint column_count= (arg_count / 2);
+ uint i;
+ my_decimal dtmp, *dres;
+
+ /* get values */
+ for (i= 0; i < column_count; i++)
+ {
+ uint valpos= i * 2 + 1;
+ DYNAMIC_COLUMN_TYPE type= defs[i].type;
+ if (type == DYN_COL_NULL) // auto detect
+ {
+ switch (args[valpos]->field_type()) {
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ type= DYN_COL_DECIMAL;
+ break;
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_LONGLONG:
+ case MYSQL_TYPE_INT24:
+ case MYSQL_TYPE_YEAR:
+ case MYSQL_TYPE_BIT:
+ type= DYN_COL_INT;
+ break;
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ type= DYN_COL_DOUBLE;
+ break;
+ case MYSQL_TYPE_NULL:
+ type= DYN_COL_NULL;
+ break;
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ type= DYN_COL_DATETIME;
+ break;
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_NEWDATE:
+ type= DYN_COL_DATE;
+ break;
+ case MYSQL_TYPE_TIME:
+ type= DYN_COL_TIME;
+ break;
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_GEOMETRY:
+ type= DYN_COL_STRING;
+ break;
+ default:
+ DBUG_ASSERT(0);
+ type= DYN_COL_STRING;
+ }
+ }
+ nums[i]= args[i * 2]->val_int();
+ vals[i].type= type;
+ switch (type) {
+ case DYN_COL_NULL:
+ break;
+ case DYN_COL_INT:
+ vals[i].long_value= args[valpos]->val_int();
+ break;
+ case DYN_COL_UINT:
+ vals[i].ulong_value= args[valpos]->val_int();
+ break;
+ case DYN_COL_DOUBLE:
+ vals[i].double_value= args[valpos]->val_real();
+ break;
+ case DYN_COL_STRING:
+ res= args[valpos]->val_str(&tmp);
+ if (res)
+ {
+ vals[i].string_value.str= (char *)my_malloc(res->length(), MYF(0));
+ if (vals[i].string_value.str)
+ memcpy(vals[i].string_value.str, res->ptr(), res->length());
+ vals[i].string_value.length= res->length();
+ vals[i].charset= res->charset();
+ }
+ else
+ {
+ vals[i].string_value.str= NULL;
+ vals[i].string_value.length= 0; // just to be safe
+ DBUG_ASSERT(args[valpos]->null_value);
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ dres= args[valpos]->val_decimal(&dtmp);
+ if (dres)
+ {
+ dynamic_column_prepare_decimal(&vals[i]);
+ DBUG_ASSERT(vals[i].decimal_value.len == dres->len);
+ vals[i].decimal_value.intg= dres->intg;
+ vals[i].decimal_value.frac= dres->frac;
+ vals[i].decimal_value.sign= dres->sign();
+ memcpy(vals[i].decimal_buffer, dres->buf,
+ sizeof(vals[i].decimal_buffer));
+ }
+ else
+ {
+ dynamic_column_prepare_decimal(&vals[i]); // just to be safe
+ DBUG_ASSERT(args[valpos]->null_value);
+ }
+ break;
+ case DYN_COL_DATETIME:
+ args[valpos]->get_date(&vals[i].time_value, TIME_FUZZY_DATE);
+ break;
+ case DYN_COL_DATE:
+ args[valpos]->get_date(&vals[i].time_value, TIME_FUZZY_DATE);
+ break;
+ case DYN_COL_TIME:
+ args[valpos]->get_time(&vals[i].time_value);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ vals[i].type= DYN_COL_NULL;
+ }
+ if (vals[i].type != DYN_COL_NULL && args[valpos]->null_value)
+ {
+ if (vals[i].type == DYN_COL_STRING)
+ my_free(vals[i].string_value.str, MYF(MY_ALLOW_ZERO_PTR));
+ vals[i].type= DYN_COL_NULL;
+ }
+ }
+}
+
+void Item_func_dyncol_create::cleanup_arguments()
+{
+ uint column_count= (arg_count / 2);
+ uint i;
+
+ for (i= 0; i < column_count; i++)
+ {
+ if (vals[i].type == DYN_COL_STRING)
+ my_free(vals[i].string_value.str, MYF(MY_ALLOW_ZERO_PTR));
+ }
+}
+
+String *Item_func_dyncol_create::val_str(String *str)
+{
+ DYNAMIC_COLUMN col;
+ String *res;
+ uint column_count= (arg_count / 2);
+ int rc;
+ DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments
+
+ prepare_arguments();
+
+ if ((rc= dynamic_column_create_many(&col, column_count, nums, vals)))
+ {
+ dynamic_column_error_message(rc);
+ res= NULL;
+ null_value= TRUE;
+ }
+ else
+ {
+ res= str;
+ str->copy(col.str, col.length, &my_charset_bin);
+ }
+
+ /* cleanup */
+ dynamic_column_column_free(&col);
+ cleanup_arguments();
+
+ return res;
+}
+
+void Item_func_dyncol_create::print_arguments(String *str,
+ enum_query_type query_type)
+{
+ uint i;
+ uint column_count= (arg_count / 2);
+ for (i= 0; i < column_count; i++)
+ {
+ args[i*2]->print(str, query_type);
+ str->append(',');
+ args[i*2 + 1]->print(str, query_type);
+ switch (defs[i].type) {
+ case DYN_COL_NULL: // automatic type => write nothing
+ break;
+ case DYN_COL_INT:
+ str->append(STRING_WITH_LEN(" AS int"));
+ break;
+ case DYN_COL_UINT:
+ str->append(STRING_WITH_LEN(" AS unsigned int"));
+ break;
+ case DYN_COL_DOUBLE:
+ str->append(STRING_WITH_LEN(" AS double"));
+ break;
+ case DYN_COL_STRING:
+ str->append(STRING_WITH_LEN(" AS char"));
+ if (defs[i].cs)
+ {
+ str->append(STRING_WITH_LEN(" charset "));
+ str->append(defs[i].cs->csname);
+ str->append(' ');
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ str->append(STRING_WITH_LEN(" AS decimal"));
+ break;
+ case DYN_COL_DATETIME:
+ str->append(STRING_WITH_LEN(" AS datetime"));
+ break;
+ case DYN_COL_DATE:
+ str->append(STRING_WITH_LEN(" AS date"));
+ break;
+ case DYN_COL_TIME:
+ str->append(STRING_WITH_LEN(" AS time"));
+ break;
+ }
+ if (i < column_count - 1)
+ str->append(',');
+ }
+}
+
+
+void Item_func_dyncol_create::print(String *str,
+ enum_query_type query_type)
+{
+ DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments
+ str->append(STRING_WITH_LEN("column_create("));
+ print_arguments(str, query_type);
+ str->append(')');
+}
+
+
+String *Item_func_dyncol_add::val_str(String *str)
+{
+ DYNAMIC_COLUMN col;
+ String *res;
+ uint column_count= (arg_count / 2);
+ int rc;
+ DBUG_ASSERT((arg_count & 0x1) == 1); // odd number of arguments
+
+ prepare_arguments();
+
+ res= args[arg_count - 1]->val_str(str);
+ if (args[arg_count - 1]->null_value)
+ goto null;
+ init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE,
+ STRING_BUFFER_USUAL_SIZE);
+ col.length= res->length();
+ memcpy(col.str, res->ptr(), col.length);
+ if ((rc= dynamic_column_update_many(&col, column_count, nums, vals)))
+ {
+ dynamic_column_error_message(rc);
+ goto null;
+ }
+
+ str->copy(col.str, col.length, &my_charset_bin);
+
+ /* cleanup */
+ dynamic_column_column_free(&col);
+ cleanup_arguments();
+
+ return str;
+
+null:
+ null_value= TRUE;
+ return NULL;
+}
+
+
+void Item_func_dyncol_add::print(String *str,
+ enum_query_type query_type)
+{
+ DBUG_ASSERT((arg_count & 0x1) == 1); // odd number of arguments
+ str->append(STRING_WITH_LEN("column_create("));
+ args[arg_count - 1]->print(str, query_type);
+ str->append(',');
+ print_arguments(str, query_type);
+ str->append(')');
+}
+
+bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp)
+{
+ DYNAMIC_COLUMN dyn_str;
+ String *res;
+ longlong num;
+ int rc;
+
+ num= args[1]->val_int();
+ if (args[1]->null_value || num < 0 || num > INT_MAX)
+ {
+ null_value= 1;
+ return 1;
+ }
+
+ res= args[0]->val_str(tmp);
+ if (args[0]->null_value)
+ {
+ null_value= 1;
+ return 1;
+ }
+
+ dyn_str.str= (char*) res->ptr();
+ dyn_str.length= res->length();
+ if ((rc= dynamic_column_get(&dyn_str, (uint) num, val)))
+ {
+ dynamic_column_error_message(rc);
+ null_value= 1;
+ return 1;
+ }
+
+ null_value= 0;
+ return 0; // ok
+}
+
+
+String *Item_dyncol_get::val_str(String *str_result)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return NULL;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_INT:
+ case DYN_COL_UINT:
+ str_result->set_int(val.long_value, test(val.type == DYN_COL_UINT),
+ &my_charset_latin1);
+ break;
+ case DYN_COL_DOUBLE:
+ str_result->set_real(val.double_value, NOT_FIXED_DEC, &my_charset_latin1);
+ break;
+ case DYN_COL_STRING:
+ if ((char*) tmp.ptr() <= val.string_value.str &&
+ (char*) tmp.ptr() + tmp.length() >= val.string_value.str)
+ {
+ /* value is allocated in tmp buffer; We have to make a copy */
+ str_result->copy(val.string_value.str, val.string_value.length,
+ val.charset);
+ }
+ else
+ {
+ /*
+ It's safe to use the current value because it's either pointing
+ into a field or in a buffer for another item and this buffer
+ is not going to be deleted during expression evulation
+ */
+ str_result->set(val.string_value.str, val.string_value.length,
+ val.charset);
+ }
+ break;
+ case DYN_COL_DECIMAL:
+ {
+ int res;
+ int length=
+ my_decimal_string_length((const my_decimal*)&val.decimal_value);
+ if (str_result->alloc(length))
+ goto null;
+ if ((res= decimal2string(&val.decimal_value, (char*) str_result->ptr(),
+ &length, 0, 0, ' ')) != E_DEC_OK)
+ {
+ char buff[40];
+ int len= sizeof(buff);
+ DBUG_ASSERT(length < (int)sizeof(buff[40]));
+ decimal2string(&val.decimal_value, buff, &len, 0, 0, ' ');
+ decimal_operation_results(res, buff, "CHAR");
+ }
+ str_result->set_charset(&my_charset_latin1);
+ str_result->length(length);
+ break;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ {
+ int length;
+ if (str_result->alloc(MAX_DATE_STRING_REP_LENGTH) ||
+ !(length= my_TIME_to_str(&val.time_value, (char*) str_result->ptr())))
+ goto null;
+ str_result->set_charset(&my_charset_latin1);
+ str_result->length(length);
+ break;
+ }
+ }
+ return str_result;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+longlong Item_dyncol_get::val_int()
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return 0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ unsigned_flag= 1; // Make it possible for caller to detect sign
+ return val.long_value;
+ case DYN_COL_INT:
+ unsigned_flag= 0; // Make it possible for caller to detect sign
+ return val.long_value;
+ case DYN_COL_DOUBLE:
+ {
+ bool error;
+ longlong num;
+
+ num= double_to_longlong(val.double_value, unsigned_flag, &error);
+ if (error)
+ {
+ char buff[30];
+ sprintf(buff, "%lg", val.double_value);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_DATA_OVERFLOW,
+ ER(ER_DATA_OVERFLOW),
+ buff,
+ unsigned_flag ? "UNSIGNED INT" : "INT");
+ }
+ return num;
+ }
+ case DYN_COL_STRING:
+ {
+ int error;
+ longlong num;
+ char *end= val.string_value.str + val.string_value.length, *org_end= end;
+
+ num= my_strtoll10(val.string_value.str, &end, &error);
+ if (end != org_end || error > 0)
+ {
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff,
+ unsigned_flag ? "UNSIGNED INT" : "INT");
+ }
+ unsigned_flag= error >= 0;
+ return num;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ longlong num;
+ my_decimal2int(E_DEC_FATAL_ERROR, &val.decimal_value, unsigned_flag,
+ &num);
+ return num;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ unsigned_flag= 1;
+ return TIME_to_ulonglong(&val.time_value);
+ }
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+double Item_dyncol_get::val_real()
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return 0.0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ return ulonglong2double(val.ulong_value);
+ case DYN_COL_INT:
+ return (double) val.long_value;
+ case DYN_COL_DOUBLE:
+ return (double) val.double_value;
+ case DYN_COL_STRING:
+ {
+ int error;
+ char *end;
+ double res= my_strntod(val.charset, (char*) val.string_value.str,
+ val.string_value.length, &end, &error);
+
+ if (end != (char*) val.string_value.str + val.string_value.length ||
+ error)
+ {
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff, "DOUBLE");
+ }
+ return res;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ double res;
+ /* This will always succed */
+ decimal2double(&val.decimal_value, &res);
+ return res;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ return (ulonglong2double(TIME_to_ulonglong(&val.time_value)) +
+ val.time_value.second_part / (double) TIME_SUBSECOND_RANGE);
+ }
+
+null:
+ null_value= TRUE;
+ return 0.0;
+}
+
+
+my_decimal *Item_dyncol_get::val_decimal(my_decimal *decimal_value)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+
+ if (get_dyn_value(&val, &tmp))
+ return NULL;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_UINT:
+ int2my_decimal(E_DEC_FATAL_ERROR, val.long_value, TRUE, decimal_value);
+ break;
+ case DYN_COL_INT:
+ int2my_decimal(E_DEC_FATAL_ERROR, val.long_value, FALSE, decimal_value);
+ break;
+ case DYN_COL_DOUBLE:
+ double2my_decimal(E_DEC_FATAL_ERROR, val.double_value, decimal_value);
+ break;
+ case DYN_COL_STRING:
+ {
+ int rc;
+ rc= str2my_decimal(0, val.string_value.str, val.string_value.length,
+ val.charset, decimal_value);
+ char buff[80];
+ strmake(buff, val.string_value.str, min(sizeof(buff)-1,
+ val.string_value.length));
+ if (rc != E_DEC_OK)
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_BAD_DATA,
+ ER(ER_BAD_DATA),
+ buff, "DECIMAL");
+ }
+ break;
+ }
+ case DYN_COL_DECIMAL:
+ {
+ int length= STRING_BUFFER_USUAL_SIZE;
+ decimal2string(&val.decimal_value, buff, &length, 0,0, 0);
+ decimal2my_decimal(&val.decimal_value, decimal_value);
+
+ break;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ {
+ double tmp= (ulonglong2double(TIME_to_ulonglong(&val.time_value)) +
+ val.time_value.second_part / (double) TIME_SUBSECOND_RANGE);
+ /* This can't overflow as time is always in the range of decimal */
+ double2my_decimal(E_DEC_FATAL_ERROR, tmp, decimal_value);
+ break;
+ }
+ }
+ return decimal_value;
+
+null:
+ null_value= TRUE;
+ return 0;
+}
+
+
+bool Item_dyncol_get::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
+{
+ DYNAMIC_COLUMN_VALUE val;
+ char buff[STRING_BUFFER_USUAL_SIZE];
+ String tmp(buff, sizeof(buff), &my_charset_bin);
+ bool signed_value= 0;
+
+ if (get_dyn_value(&val, &tmp))
+ return 0;
+
+ switch (val.type) {
+ case DYN_COL_NULL:
+ goto null;
+ case DYN_COL_INT:
+ signed_value= 1; // For error message
+ /* fall_trough */
+ case DYN_COL_UINT:
+ {
+ ulonglong num;
+ int error;
+
+ num= val.ulong_value;
+ number_to_datetime(num, ltime, fuzzy_date, &error);
+ if (error)
+ {
+ char buff[65];
+ int errnum= error == 2 ? ER_DATA_OVERFLOW : ER_BAD_DATA;
+ longlong2str(num, buff, signed_value ? -10 : 10, 1);
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ errnum,
+ ER(errnum),
+ buff, "DATE or DATETIME");
+ goto null;
+ }
+ return 0;
+ }
+ case DYN_COL_DOUBLE:
+ {
+ if (double_to_datetime_with_warn(val.double_value, ltime, fuzzy_date))
+ goto null;
+ return 0;
+ }
+ case DYN_COL_DECIMAL:
+ if (decimal_to_datetime_with_warn(&val.decimal_value, ltime, fuzzy_date))
+ goto null;
+ return 0;
+ case DYN_COL_STRING:
+ {
+ if (str_to_datetime_with_warn(val.string_value.str,
+ val.string_value.length,
+ ltime, fuzzy_date) <= MYSQL_TIMESTAMP_ERROR)
+ goto null;
+ return 0;
+ }
+ case DYN_COL_DATETIME:
+ case DYN_COL_DATE:
+ case DYN_COL_TIME:
+ *ltime= val.time_value;
+ return 0;
+ }
+
+null:
+ null_value= TRUE;
+ return 1;
+}
+
+void Item_dyncol_get::print(String *str, enum_query_type query_type)
+{
+ str->append(STRING_WITH_LEN("column_get("));
+ args[0]->print(str, query_type);
+ str->append(',');
+ args[1]->print(str, query_type);
+ str->append(')');
+}
+
+String *Item_func_dyncol_list::val_str(String *str)
+{
+ DYNAMIC_ARRAY arr;
+ DYNAMIC_COLUMN col;
+ String *res= args[0]->val_str(str);
+ uint i;
+ int rc;
+
+ if (args[0]->null_value)
+ goto null;
+ col.length= res->length();
+ /* We do not change the string, so could do this trick */
+ col.str= (char *)res->ptr();
+ if ((rc= dynamic_column_list(&col, &arr)))
+ {
+ dynamic_column_error_message(rc);
+ delete_dynamic(&arr);
+ goto null;
+ }
+
+ str->length(0);
+ for (i= 0; i < arr.elements; i++)
+ {
+ str->qs_append(*dynamic_element(&arr, i, uint*));
+ if (i < arr.elements - 1)
+ str->append(',');
+ }
+
+ delete_dynamic(&arr);
+ return str;
+null:
+ null_value= TRUE;
+ return NULL;
+}
=== modified file 'sql/item_strfunc.h'
--- sql/item_strfunc.h 2010-06-01 19:52:20 +0000
+++ sql/item_strfunc.h 2011-04-29 09:52:28 +0000
@@ -871,3 +871,71 @@
}
};
+
+class Item_func_dyncol_create: public Item_str_func
+{
+protected:
+ DYNCALL_CREATE_DEF *defs;
+ DYNAMIC_COLUMN_VALUE *vals;
+ uint *nums;
+ void prepare_arguments();
+ void cleanup_arguments();
+ void print_arguments(String *str, enum_query_type query_type);
+public:
+ Item_func_dyncol_create(List<Item> &args, DYNCALL_CREATE_DEF *dfs);
+ bool fix_fields(THD *thd, Item **ref);
+ void fix_length_and_dec();
+ const char *func_name() const{ return "column_create"; }
+ String *val_str(String *);
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_dyncol_add: public Item_func_dyncol_create
+{
+public:
+ Item_func_dyncol_add(List<Item> &args, DYNCALL_CREATE_DEF *dfs)
+ :Item_func_dyncol_create(args, dfs)
+ {}
+ const char *func_name() const{ return "column_add"; }
+ String *val_str(String *);
+ virtual void print(String *str, enum_query_type query_type);
+};
+
+
+/*
+ The following functions is always called from an Item_cast function
+*/
+
+class Item_dyncol_get: public Item_str_func
+{
+public:
+ Item_dyncol_get(Item *str, Item *num)
+ :Item_str_func(str, num)
+ {
+ max_length= MAX_FIELD_BLOBLENGTH;
+ }
+ void fix_length_and_dec()
+ { maybe_null= 1; }
+ /* Mark that collation can change between calls */
+ bool dynamic_result() { return 1; }
+
+ const char *func_name() const { return "column_get"; }
+ String *val_str(String *);
+ longlong val_int();
+ double val_real();
+ my_decimal *val_decimal(my_decimal *);
+ bool get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp);
+ bool get_date(MYSQL_TIME *ltime,uint fuzzydate);
+ void print(String *str, enum_query_type query_type);
+};
+
+
+class Item_func_dyncol_list: public Item_str_func
+{
+public:
+ Item_func_dyncol_list(Item *str) :Item_str_func(str) {};
+ void fix_length_and_dec() { maybe_null= 1; max_length= MAX_BLOB_WIDTH; };
+ const char *func_name() const{ return "column_list"; }
+ String *val_str(String *);
+};
=== modified file 'sql/item_timefunc.cc'
--- sql/item_timefunc.cc 2011-02-20 16:51:43 +0000
+++ sql/item_timefunc.cc 2011-04-29 09:52:28 +0000
@@ -1952,7 +1952,10 @@
{
String *res;
if (!(res=args[0]->val_str(str)) ||
- (str_to_time_with_warn(res->ptr(), res->length(), &l_time)))
+ (str_to_time_with_warn(res->ptr(), res->length(), &l_time,
+ current_thd->variables.sql_mode &
+ (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE |
+ MODE_INVALID_DATES))))
goto null_date;
l_time.year=l_time.month=l_time.day=0;
@@ -2322,7 +2325,11 @@
char buf[40];
String value(buf, sizeof(buf), &my_charset_bin);;
String *res= args[0]->val_str(&value);
- if (!res || str_to_time_with_warn(res->ptr(), res->length(), <ime))
+ if (!res ||
+ str_to_time_with_warn(res->ptr(), res->length(), <ime,
+ current_thd->variables.sql_mode &
+ (MODE_NO_ZERO_DATE | MODE_NO_ZERO_IN_DATE |
+ MODE_INVALID_DATES)))
{
null_value=1;
return 0;
@@ -2464,7 +2471,8 @@
// Convert character set if differ
uint dummy_errors;
if (!(res= args[0]->val_str(str)) ||
- tmp_value.copy(res->ptr(), res->length(), from_cs,
+ tmp_value.copy(res->ptr(), res->length(),
+ from_cs ? from_cs : res->charset(),
cast_cs, &dummy_errors))
{
null_value= 1;
@@ -2542,15 +2550,19 @@
and thus avoid unnecessary character set conversion.
- If the argument is not a number, then from_cs is set to
the argument's charset.
+ - If argument has a dynamic collation (can change from call to call)
+ we set from_cs to 0 as a marker that we have to take the collation
+ from the result string.
Note (TODO): we could use repertoire technique here.
*/
- from_cs= (args[0]->result_type() == INT_RESULT ||
- args[0]->result_type() == DECIMAL_RESULT ||
- args[0]->result_type() == REAL_RESULT) ?
- (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
- args[0]->collation.collation;
- charset_conversion= (cast_cs->mbmaxlen > 1) ||
+ from_cs= ((args[0]->result_type() == INT_RESULT ||
+ args[0]->result_type() == DECIMAL_RESULT ||
+ args[0]->result_type() == REAL_RESULT) ?
+ (cast_cs->mbminlen == 1 ? cast_cs : &my_charset_latin1) :
+ args[0]->dynamic_result() ? 0 :
+ args[0]->collation.collation);
+ charset_conversion= !from_cs || (cast_cs->mbmaxlen > 1) ||
(!my_charset_same(from_cs, cast_cs) &&
from_cs != &my_charset_bin &&
cast_cs != &my_charset_bin);
@@ -2604,6 +2616,11 @@
return res;
}
+bool Item_time_typecast::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
+{
+ return get_time(ltime);
+}
+
longlong Item_time_typecast::val_int()
{
@@ -2621,7 +2638,7 @@
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
- if (!get_arg0_time(<ime) &&
+ if (!get_time(<ime) &&
!make_datetime(ltime.second_part ? TIME_MICROSECOND : TIME_ONLY,
<ime, str))
return str;
=== modified file 'sql/item_timefunc.h'
--- sql/item_timefunc.h 2011-02-28 17:39:30 +0000
+++ sql/item_timefunc.h 2011-04-29 09:52:28 +0000
@@ -937,6 +937,7 @@
public:
Item_time_typecast(Item *a) :Item_typecast_maybe_null(a) {}
const char *func_name() const { return "cast_as_time"; }
+ bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
String *val_str(String *str);
bool get_time(MYSQL_TIME *ltime);
const char *cast_type() const { return "time"; }
=== modified file 'sql/lex.h'
--- sql/lex.h 2011-04-28 16:56:10 +0000
+++ sql/lex.h 2011-04-29 09:52:28 +0000
@@ -116,6 +116,12 @@
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
{ "COLUMNS", SYM(COLUMNS)},
+ { "COLUMN_ADD", SYM(COLUMN_ADD_SYM)},
+ { "COLUMN_CREATE", SYM(COLUMN_CREATE_SYM)},
+ { "COLUMN_DELETE", SYM(COLUMN_DELETE_SYM)},
+ { "COLUMN_EXISTS", SYM(COLUMN_EXISTS_SYM)},
+ { "COLUMN_GET", SYM(COLUMN_GET_SYM)},
+ { "COLUMN_LIST", SYM(COLUMN_LIST_SYM)},
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
{ "COMMITTED", SYM(COMMITTED_SYM)},
=== modified file 'sql/my_decimal.cc'
--- sql/my_decimal.cc 2011-02-20 16:51:43 +0000
+++ sql/my_decimal.cc 2011-04-29 09:52:28 +0000
@@ -30,21 +30,20 @@
result
*/
-int decimal_operation_results(int result)
+int decimal_operation_results(int result, const char *value, const char *type)
{
switch (result) {
case E_DEC_OK:
break;
case E_DEC_TRUNCATED:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
- "", (ulong) 0);
+ ER_DATA_TRUNCATED, ER(ER_DATA_TRUNCATED),
+ value, type);
break;
case E_DEC_OVERFLOW:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_TRUNCATED_WRONG_VALUE,
- ER(ER_TRUNCATED_WRONG_VALUE),
- "DECIMAL", "");
+ ER_DATA_OVERFLOW, ER(ER_DATA_OVERFLOW),
+ value, type);
break;
case E_DEC_DIV_ZERO:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
@@ -52,9 +51,8 @@
break;
case E_DEC_BAD_NUM:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
- ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
- "decimal", "", "", (ulong) 0);
+ ER_BAD_DATA, ER(ER_BAD_DATA),
+ value, type);
break;
case E_DEC_OOM:
my_error(ER_OUT_OF_RESOURCES, MYF(0));
@@ -283,6 +281,35 @@
return buff;
}
+
+/*
+ Convert a decimal to an ulong with a descreptive error message
+*/
+
+int my_decimal2int(uint mask, const decimal_t *d, my_bool unsigned_flag,
+ longlong *l)
+{
+ int res;
+ my_decimal rounded;
+ /* decimal_round can return only E_DEC_TRUNCATED */
+ decimal_round(d, &rounded, 0, HALF_UP);
+ res= (unsigned_flag ?
+ decimal2ulonglong(&rounded, (ulonglong *) l) :
+ decimal2longlong(&rounded, l));
+ if (res & mask)
+ {
+ char buff[DECIMAL_MAX_STR_LENGTH];
+ int length= sizeof(buff);
+ decimal2string(d, buff, &length, 0, 0, 0);
+
+ decimal_operation_results(res, buff,
+ unsigned_flag ? "UNSIGNED INT" :
+ "INT");
+ }
+ return res;
+}
+
+
#endif /*DBUG_OFF*/
=== modified file 'sql/my_decimal.h'
--- sql/my_decimal.h 2010-11-24 22:57:34 +0000
+++ sql/my_decimal.h 2011-04-29 09:52:28 +0000
@@ -32,32 +32,7 @@
#include <decimal.h>
C_MODE_END
-#define DECIMAL_LONGLONG_DIGITS 22
-#define DECIMAL_LONG_DIGITS 10
-#define DECIMAL_LONG3_DIGITS 8
-
-/** maximum length of buffer in our big digits (uint32). */
-#define DECIMAL_BUFF_LENGTH 9
-
-/* the number of digits that my_decimal can possibly contain */
-#define DECIMAL_MAX_POSSIBLE_PRECISION (DECIMAL_BUFF_LENGTH * 9)
-
-
-/**
- maximum guaranteed precision of number in decimal digits (number of our
- digits * number of decimal digits in one our big digit - number of decimal
- digits in one our big digit decreased by 1 (because we always put decimal
- point on the border of our big digits))
-*/
-#define DECIMAL_MAX_PRECISION (DECIMAL_MAX_POSSIBLE_PRECISION - 8*2)
-#define DECIMAL_MAX_SCALE 30
-#define DECIMAL_NOT_SPECIFIED 31
-
-/**
- maximum length of string representation (number of maximum decimal
- digits + 1 position for sign + 1 position for decimal point)
-*/
-#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
+#include <my_decimal_limits.h>
/**
maximum size of packet length.
@@ -134,9 +109,10 @@
#endif
#ifndef MYSQL_CLIENT
-int decimal_operation_results(int result);
+int decimal_operation_results(int result, const char *value, const char *type);
#else
-inline int decimal_operation_results(int result)
+inline int decimal_operation_results(int result, const char *value,
+ const char *type)
{
return result;
}
@@ -158,7 +134,7 @@
inline int check_result(uint mask, int result)
{
if (result & mask)
- decimal_operation_results(result);
+ decimal_operation_results(result, "", "DECIMAL");
return result;
}
@@ -294,24 +270,14 @@
uint fixed_dec, char filler, String *str);
#endif
-inline
-int my_decimal2int(uint mask, const my_decimal *d, my_bool unsigned_flag,
- longlong *l)
-{
- my_decimal rounded;
- /* decimal_round can return only E_DEC_TRUNCATED */
- decimal_round((decimal_t*)d, &rounded, 0, HALF_UP);
- return check_result(mask, (unsigned_flag ?
- decimal2ulonglong(&rounded, (ulonglong *)l) :
- decimal2longlong(&rounded, l)));
-}
-
-
-inline
-int my_decimal2double(uint, const my_decimal *d, double *result)
+int my_decimal2int(uint mask, const decimal_t *d, my_bool unsigned_flag,
+ longlong *l);
+
+inline
+int my_decimal2double(uint, const decimal_t *d, double *result)
{
/* No need to call check_result as this will always succeed */
- return decimal2double((decimal_t*) d, result);
+ return decimal2double(d, result);
}
@@ -354,6 +320,18 @@
longlong2decimal(i, d)));
}
+inline
+void decimal2my_decimal(decimal_t *from, my_decimal *to)
+{
+ DBUG_ASSERT(to->len >= from->len);
+ to->intg= from->intg;
+ to->frac= from->frac;
+ to->sign(from->sign);
+ memcpy(to->buf, from->buf, to->len*sizeof(decimal_digit_t));
+}
+
+
+
inline
void my_decimal_neg(decimal_t *arg)
=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h 2011-04-28 16:56:10 +0000
+++ sql/mysql_priv.h 2011-04-29 09:52:28 +0000
@@ -1412,6 +1412,7 @@
Field *
find_field_in_table_sef(TABLE *table, const char *name);
int update_virtual_fields(THD *thd, TABLE *table, bool ignore_stored= FALSE);
+int dynamic_column_error_message(int rc);
#endif /* MYSQL_SERVER */
@@ -2322,16 +2323,22 @@
void get_date_from_daynr(long daynr,uint *year, uint *month,
uint *day);
my_time_t TIME_to_timestamp(THD *thd, const MYSQL_TIME *t, my_bool *not_exist);
-bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time);
+bool str_to_time_with_warn(const char *str,uint length,MYSQL_TIME *l_time,
+ ulong fuzzydate);
timestamp_type str_to_datetime_with_warn(const char *str, uint length,
- MYSQL_TIME *l_time, uint flags);
+ MYSQL_TIME *l_time, ulong flags);
void localtime_to_TIME(MYSQL_TIME *to, struct tm *from);
void calc_time_from_sec(MYSQL_TIME *to, long seconds, long microseconds);
-void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+void make_truncated_value_warning(THD *thd,
+ MYSQL_ERROR::enum_warning_level level,
const char *str_val,
uint str_length, timestamp_type time_type,
const char *field_name);
+bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime,
+ ulong fuzzy_date);
+bool decimal_to_datetime_with_warn(decimal_t *value, MYSQL_TIME *ltime,
+ ulong fuzzy_date);
bool date_add_interval(MYSQL_TIME *ltime, interval_type int_type, INTERVAL interval);
bool calc_time_diff(MYSQL_TIME *l_time1, MYSQL_TIME *l_time2, int l_sign,
=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt 2011-04-28 16:56:10 +0000
+++ sql/share/errmsg.txt 2011-04-29 09:55:41 +0000
@@ -5321,7 +5321,7 @@
ER_DIVISION_BY_ZERO 22012
eng "Division by 0"
ger "Division durch 0"
-ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
+ER_TRUNCATED_WRONG_VALUE_FOR_FIELD 22007
eng "Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %lu"
ger "Falscher %-.32s-Wert: '%-.128s' für Feld '%.192s' in Zeile %lu"
ER_ILLEGAL_VALUE_FOR_TYPE 22007
@@ -6251,4 +6251,15 @@
eng "Incorrect value '%-.64s' for option '%-.64s'"
ER_CANT_DO_ONLINE
eng "Can't execute the given '%s' command as online"
-
+ER_DATA_OVERFLOW 22003
+ eng "Got overflow when converting '%-.128s' to %-.32s. Value truncated."
+ER_DATA_TRUNCATED 22003
+ eng "Truncated value '%-.128s' when converting to %-.32s"
+ER_BAD_DATA 22007
+ eng "Encountered illegal value '%-.128s' when converting to %-.32s"
+ER_DYN_COL_WRONG_FORMAT
+ eng "Encountered illegal format of dynamic column string"
+ER_DYN_COL_IMPLEMENTATION_LIMIT
+ eng "Dynamic column implementation limit reached"
+ER_DYN_COL_DATA 22007
+ eng "Illegal value used as argument of dynamic column function"
=== modified file 'sql/sql_base.cc'
--- sql/sql_base.cc 2011-03-31 15:35:57 +0000
+++ sql/sql_base.cc 2011-04-29 09:52:28 +0000
@@ -9406,6 +9406,39 @@
thd->restore_backup_open_tables_state(backup);
}
+
+/**
+ Check result of dynamic column function and issue error if it is needed
+
+ @param rc The result code of dynamic column function
+
+ @return the result code which was get as an argument\
+*/
+
+int dynamic_column_error_message(int rc)
+{
+ switch (rc) {
+ case ER_DYNCOL_YES:
+ case ER_DYNCOL_OK:
+ break; // it is not an error
+ case ER_DYNCOL_FORMAT:
+ my_error(ER_DYN_COL_WRONG_FORMAT, MYF(0));
+ break;
+ case ER_DYNCOL_LIMIT:
+ my_error(ER_DYN_COL_IMPLEMENTATION_LIMIT, MYF(0));
+ break;
+ case ER_DYNCOL_RESOURCE:
+ my_error(ER_OUT_OF_RESOURCES, MYF(0));
+ break;
+ case ER_DYNCOL_DATA:
+ my_error(ER_DYN_COL_DATA, MYF(0));
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ return rc;
+}
+
/**
@} (end of group Data_Dictionary)
*/
=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy 2011-04-28 16:56:10 +0000
+++ sql/sql_yacc.yy 2011-04-29 09:56:51 +0000
@@ -34,6 +34,7 @@
#define YYINITDEPTH 100
#define YYMAXDEPTH 3200 /* Because of 64K stack */
#define Lex (YYTHD->lex)
+
#define Select Lex->current_select
#include "mysql_priv.h"
#include "slave.h"
@@ -671,6 +672,8 @@
sp_head *sphead;
struct p_elem_val *p_elem_value;
enum index_hint_type index_hint;
+ DYNCALL_CREATE_DEF *dyncol_def;
+ List<DYNCALL_CREATE_DEF> *dyncol_def_list;
}
%{
@@ -770,6 +773,12 @@
%token COLLATE_SYM /* SQL-2003-R */
%token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS
+%token COLUMN_ADD_SYM
+%token COLUMN_CREATE_SYM
+%token COLUMN_DELETE_SYM
+%token COLUMN_EXISTS_SYM
+%token COLUMN_GET_SYM
+%token COLUMN_LIST_SYM
%token COLUMN_SYM /* SQL-2003-R */
%token COMMENT_SYM
%token COMMITTED_SYM /* SQL-2003-N */
@@ -1338,7 +1347,7 @@
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
- optional_flush_tables_arguments
+ optional_flush_tables_arguments opt_dyncol_type dyncol_type
%type <ulong_num>
ulong_num real_ulong_num merge_insert_types
@@ -1438,6 +1447,10 @@
%type <boolfunc2creator> comp_op
+%type <dyncol_def> dyncall_create_element
+
+%type <dyncol_def_list> dyncall_create_list
+
%type <NONE>
query verb_clause create change select do drop insert replace insert2
insert_values update delete truncate rename
@@ -7506,6 +7519,131 @@
| ANY_SYM { $$ = 0; }
;
+opt_dyncol_type:
+ /* empty */
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_NULL; /* automatic type */
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | AS dyncol_type { $$= $2; }
+ ;
+
+dyncol_type:
+ INT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_INT;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | UNSIGNED INT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_UINT;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DOUBLE_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | REAL
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | FLOAT_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DOUBLE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DECIMAL_SYM float_options
+ {
+ $$= DYN_COL_DECIMAL;
+ Lex->charset= NULL;
+ }
+ | char opt_binary
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_STRING;
+ lex->length= lex->dec= 0;
+ }
+ | nchar
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_STRING;
+ lex->charset= national_charset_info;
+ lex->length= lex->dec= 0;
+ }
+ | DATE_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DATE;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | TIME_SYM
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_TIME;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ | DATETIME
+ {
+ LEX *lex= Lex;
+ $$= DYN_COL_DATETIME;
+ lex->charset= NULL;
+ lex->length= lex->dec= 0;
+ }
+ ;
+
+dyncall_create_element:
+ expr ',' expr opt_dyncol_type
+ {
+ LEX *lex= Lex;
+ $$= (DYNCALL_CREATE_DEF *)
+ alloc_root(YYTHD->mem_root, sizeof(DYNCALL_CREATE_DEF));
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->num= $1;
+ $$->value= $3;
+ $$->type= (DYNAMIC_COLUMN_TYPE)$4;
+ $$->cs= lex->charset;
+ if (lex->length)
+ $$->len= strtoul(lex->length, NULL, 10);
+ else
+ $$->len= 0;
+ if (lex->dec)
+ $$->frac= strtoul(lex->dec, NULL, 10);
+ else
+ $$->len= 0;
+ }
+
+dyncall_create_list:
+ dyncall_create_element
+ {
+ $$= new (YYTHD->mem_root) List<DYNCALL_CREATE_DEF>;
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ $$->push_back($1);
+ }
+ | dyncall_create_list ',' dyncall_create_element
+ {
+ $1->push_back($3);
+ $$= $1;
+ }
+ ;
+
simple_expr:
simple_ident
| function_call_keyword
@@ -8040,6 +8178,51 @@
MYSQL_YYABORT;
Lex->safe_to_cache_query=0;
}
+ |
+ COLUMN_ADD_SYM '(' expr ',' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_add(YYTHD, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_DELETE_SYM '(' expr ',' expr_list ')'
+ {
+ $$= create_func_dyncol_delete(YYTHD, $3, *$5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_EXISTS_SYM '(' expr ',' expr ')'
+ {
+ $$= new (YYTHD->mem_root) Item_func_dyncol_exists($3, $5);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_LIST_SYM '(' expr ')'
+ {
+ $$= new (YYTHD->mem_root) Item_func_dyncol_list($3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_CREATE_SYM '(' dyncall_create_list ')'
+ {
+ $$= create_func_dyncol_create(YYTHD, *$3);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
+ |
+ COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
+ {
+ LEX *lex= Lex;
+ $$= create_func_dyncol_get(YYTHD, $3, $5, $7,
+ lex->length, lex->dec,
+ lex->charset);
+ if ($$ == NULL)
+ MYSQL_YYABORT;
+ }
;
/*
@@ -8641,6 +8824,8 @@
{ $$=ITEM_CAST_CHAR; Lex->dec= 0; }
| NCHAR_SYM opt_field_length
{ $$=ITEM_CAST_CHAR; Lex->charset= national_charset_info; Lex->dec=0; }
+ | INT_SYM
+ { $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| SIGNED_SYM
{ $$=ITEM_CAST_SIGNED_INT; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| SIGNED_SYM INT_SYM
@@ -8657,7 +8842,10 @@
{ $$=ITEM_CAST_DATETIME; Lex->charset= NULL; Lex->dec=Lex->length= (char*)0; }
| DECIMAL_SYM float_options
{ $$=ITEM_CAST_DECIMAL; Lex->charset= NULL; }
- ;
+ | DOUBLE_SYM
+ { Lex->charset= NULL; Lex->length= Lex->dec= 0;}
+ opt_precision
+ { $$=ITEM_CAST_DOUBLE; }
opt_expr_list:
/* empty */ { $$= NULL; }
@@ -11887,6 +12075,12 @@
| CHECKSUM_SYM {}
| CHECKPOINT_SYM {}
| CLOSE_SYM {}
+ | COLUMN_ADD_SYM {}
+ | COLUMN_CREATE_SYM {}
+ | COLUMN_DELETE_SYM {}
+ | COLUMN_EXISTS_SYM {}
+ | COLUMN_GET_SYM {}
+ | COLUMN_LIST_SYM {}
| COMMENT_SYM {}
| COMMIT_SYM {}
| CONTAINS_SYM {}
=== modified file 'sql/time.cc'
--- sql/time.cc 2010-01-15 15:27:55 +0000
+++ sql/time.cc 2011-04-29 09:52:28 +0000
@@ -223,7 +223,7 @@
timestamp_type
str_to_datetime_with_warn(const char *str, uint length, MYSQL_TIME *l_time,
- uint flags)
+ ulong flags)
{
int was_cut;
THD *thd= current_thd;
@@ -232,15 +232,42 @@
ts_type= str_to_datetime(str, length, l_time,
(flags | (thd->variables.sql_mode &
(MODE_INVALID_DATES |
+ MODE_NO_ZERO_IN_DATE |
MODE_NO_ZERO_DATE))),
&was_cut);
if (was_cut || ts_type <= MYSQL_TIMESTAMP_ERROR)
- make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
str, length, ts_type, NullS);
return ts_type;
}
+bool double_to_datetime_with_warn(double value, MYSQL_TIME *ltime,
+ ulong fuzzydate)
+{
+ if (double_to_datetime(value, ltime, fuzzydate))
+ {
+ char buff[40];
+ uint length= my_sprintf(buff, (buff, "%-30.21g", value));
+ make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ buff, length, MYSQL_TIMESTAMP_DATETIME,
+ NullS);
+ return 1;
+ }
+ return 0;
+}
+
+bool decimal_to_datetime_with_warn(decimal_t *value, MYSQL_TIME *ltime,
+ ulong fuzzydate)
+{
+ char buff[40];
+ int length= sizeof(buff);
+
+ decimal2string(value, buff, &length, 0, 0, 0);
+ return (str_to_datetime_with_warn(buff, length, ltime, fuzzydate) <=
+ MYSQL_TIMESTAMP_ERROR);
+}
+
/*
Convert a datetime from broken-down MYSQL_TIME representation to corresponding
TIMESTAMP value.
@@ -284,10 +311,11 @@
See str_to_time() for more info.
*/
bool
-str_to_time_with_warn(const char *str, uint length, MYSQL_TIME *l_time)
+str_to_time_with_warn(const char *str, uint length, MYSQL_TIME *l_time,
+ ulong fuzzydate)
{
int warning;
- bool ret_val= str_to_time(str, length, l_time, &warning);
+ bool ret_val= str_to_time(str, length, l_time, fuzzydate, &warning);
if (ret_val || warning)
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
str, length, MYSQL_TIMESTAMP_TIME, NullS);
@@ -719,7 +747,8 @@
}
-void make_truncated_value_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+void make_truncated_value_warning(THD *thd,
+ MYSQL_ERROR::enum_warning_level level,
const char *str_val,
uint str_length, timestamp_type time_type,
const char *field_name)
@@ -763,6 +792,7 @@
ER_TRUNCATED_WRONG_VALUE, warn_buff);
}
+
/* Daynumber from year 0 to 9999-12-31 */
#define MAX_DAY_NUMBER 3652424L
=== modified file 'strings/decimal.c'
--- strings/decimal.c 2011-02-28 17:39:30 +0000
+++ strings/decimal.c 2011-04-29 09:52:28 +0000
@@ -255,7 +255,7 @@
}
-static dec1 *remove_leading_zeroes(decimal_t *from, int *intg_result)
+static dec1 *remove_leading_zeroes(const decimal_t *from, int *intg_result)
{
int intg= from->intg, i;
dec1 *buf0= from->buf;
@@ -333,7 +333,7 @@
E_DEC_OK/E_DEC_TRUNCATED/E_DEC_OVERFLOW
*/
-int decimal2string(decimal_t *from, char *to, int *to_len,
+int decimal2string(const decimal_t *from, char *to, int *to_len,
int fixed_precision, int fixed_decimals,
char filler)
{
@@ -949,7 +949,7 @@
E_DEC_OK
*/
-int decimal2double(decimal_t *from, double *to)
+int decimal2double(const decimal_t *from, double *to)
{
double result= 0.0;
int i, exp= 0;
@@ -1041,7 +1041,7 @@
return ull2dec(from, to);
}
-int decimal2ulonglong(decimal_t *from, ulonglong *to)
+int decimal2ulonglong(const decimal_t *from, ulonglong *to)
{
dec1 *buf=from->buf;
ulonglong x=0;
@@ -1070,7 +1070,7 @@
return E_DEC_OK;
}
-int decimal2longlong(decimal_t *from, longlong *to)
+int decimal2longlong(const decimal_t *from, longlong *to)
{
dec1 *buf=from->buf;
longlong x=0;
@@ -1189,7 +1189,7 @@
7E F2 04 37 2D FB 2D
*/
-int decimal2bin(decimal_t *from, uchar *to, int precision, int frac)
+int decimal2bin(const decimal_t *from, uchar *to, int precision, int frac)
{
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
int error=E_DEC_OK, intg=precision-frac,
@@ -1479,7 +1479,7 @@
*/
int
-decimal_round(decimal_t *from, decimal_t *to, int scale,
+decimal_round(const decimal_t *from, decimal_t *to, int scale,
decimal_round_mode mode)
{
int frac0=scale>0 ? ROUND_UP(scale) : scale/DIG_PER_DEC1,
=== modified file 'unittest/mysys/Makefile.am'
--- unittest/mysys/Makefile.am 2010-11-30 21:11:03 +0000
+++ unittest/mysys/Makefile.am 2011-04-29 09:52:28 +0000
@@ -25,4 +25,4 @@
EXTRA_DIST = CMakeLists.txt
noinst_PROGRAMS = bitmap-t base64-t my_atomic-t lf-t waiting_threads-t \
- my_vsnprintf-t
+ my_vsnprintf-t ma_dyncol-t
=== added file 'unittest/mysys/ma_dyncol-t.c'
--- unittest/mysys/ma_dyncol-t.c 1970-01-01 00:00:00 +0000
+++ unittest/mysys/ma_dyncol-t.c 2011-04-29 09:52:28 +0000
@@ -0,0 +1,767 @@
+#include <my_global.h>
+#include <ma_dyncol.h>
+#include <tap.h>
+
+
+
+void test_value_single_null()
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_NULL;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_NULL);
+err:
+ ok(rc, "%s", "NULL");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_uint(ulonglong num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_UINT;
+ val.ulong_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_UINT) && (res.ulong_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %llu", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_sint(longlong num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_INT;
+ val.long_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_INT) && (res.long_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %lld", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_single_double(double num, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DOUBLE;
+ val.double_value= num;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= (res.type == DYN_COL_DOUBLE) && (res.double_value == num);
+ num= res.ulong_value;
+err:
+ ok(rc, "%s - %lf", name, num);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_decimal(const char *num)
+{
+ char *end= (((char*)num) + strlen(num));
+ char buff[80];
+ int rc= FALSE;
+ int length= 80;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+
+ /* init values */
+ dynamic_column_prepare_decimal(&val); // special procedure for decimal!!!
+ if (string2decimal(num, &val.decimal_value, &end) != E_DEC_OK)
+ goto err;
+ dynamic_column_value_init(&res);
+
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DECIMAL) &&
+ (decimal_cmp(&res.decimal_value, &val.decimal_value) == 0));
+ decimal2string(&res.decimal_value, buff, &length, 0, 0, ' ');
+err:
+ ok(rc, "%s - %s", num, buff);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+static CHARSET_INFO *charset_list[]=
+{
+#ifdef HAVE_CHARSET_big5
+ &my_charset_big5_chinese_ci,
+ &my_charset_big5_bin,
+#endif
+#ifdef HAVE_CHARSET_euckr
+ &my_charset_euckr_korean_ci,
+ &my_charset_euckr_bin,
+#endif
+#ifdef HAVE_CHARSET_gb2312
+ &my_charset_gb2312_chinese_ci,
+ &my_charset_gb2312_bin,
+#endif
+#ifdef HAVE_CHARSET_gbk
+ &my_charset_gbk_chinese_ci,
+ &my_charset_gbk_bin,
+#endif
+#ifdef HAVE_CHARSET_latin1
+ &my_charset_latin1,
+ &my_charset_latin1_bin,
+#endif
+#ifdef HAVE_CHARSET_sjis
+ &my_charset_sjis_japanese_ci,
+ &my_charset_sjis_bin,
+#endif
+#ifdef HAVE_CHARSET_tis620
+ &my_charset_tis620_thai_ci,
+ &my_charset_tis620_bin,
+#endif
+#ifdef HAVE_CHARSET_ujis
+ &my_charset_ujis_japanese_ci,
+ &my_charset_ujis_bin,
+#endif
+#ifdef HAVE_CHARSET_utf8
+ &my_charset_utf8_general_ci,
+#ifdef HAVE_HAVE_UCA_COLLATIONS
+ &my_charset_utf8_unicode_ci,
+#endif
+ &my_charset_utf8_bin,
+#endif
+};
+
+
+void test_value_single_string(const char *string, size_t len,
+ CHARSET_INFO *cs)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+
+ /* init values */
+ val.type= DYN_COL_STRING;
+ val.string_value.str= (char*)string;
+ val.string_value.length= len;
+ val.charset= cs;
+ dynamic_column_value_init(&res);
+
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_STRING) &&
+ (res.string_value.length == len) &&
+ (memcmp(res.string_value.str, string, len) == 0) &&
+ (res.charset->number == cs->number));
+err:
+ ok(rc, "'%s' - '%s' %u %u-%s", string,
+ res.string_value.str, (uint)res.string_value.length,
+ (uint)res.charset->number, res.charset->name);
+ /* cleanup */
+ val.string_value.str= NULL; // we did not allocated it
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_date(uint year, uint month, uint day, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DATE;
+ val.time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ val.time_value.year= year;
+ val.time_value.month= month;
+ val.time_value.day= day;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DATE) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
+ (res.time_value.year == year) &&
+ (res.time_value.month == month) &&
+ (res.time_value.day == day));
+err:
+ ok(rc, "%s - %04u-%02u-%02u", name, year, month, day);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_value_single_time(uint neg, uint hour, uint minute, uint second,
+ uint mic, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_TIME;
+ val.time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ val.time_value.neg= neg;
+ val.time_value.hour= hour;
+ val.time_value.minute= minute;
+ val.time_value.second= second;
+ val.time_value.second_part= mic;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_TIME) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
+ (res.time_value.neg == (int)neg) &&
+ (res.time_value.hour == hour) &&
+ (res.time_value.minute == minute) &&
+ (res.time_value.second == second) &&
+ (res.time_value.second_part == mic));
+err:
+ ok(rc, "%s - %c%02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
+ hour, minute, second, mic);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_single_datetime(uint neg, uint year, uint month, uint day,
+ uint hour, uint minute, uint second,
+ uint mic, const char *name)
+{
+ int rc= FALSE;
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val.type= DYN_COL_DATETIME;
+ val.time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ val.time_value.neg= neg;
+ val.time_value.year= year;
+ val.time_value.month= month;
+ val.time_value.day= day;
+ val.time_value.hour= hour;
+ val.time_value.minute= minute;
+ val.time_value.second= second;
+ val.time_value.second_part= mic;
+ dynamic_column_value_init(&res);
+ /* create column */
+ if (dynamic_column_create(&str, 1, &val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ if (dynamic_column_get(&str, 1, &res))
+ goto err;
+ rc= ((res.type == DYN_COL_DATETIME) &&
+ (res.time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
+ (res.time_value.neg == (int)neg) &&
+ (res.time_value.year == year) &&
+ (res.time_value.month == month) &&
+ (res.time_value.day == day) &&
+ (res.time_value.hour == hour) &&
+ (res.time_value.minute == minute) &&
+ (res.time_value.second == second) &&
+ (res.time_value.second_part == mic));
+err:
+ ok(rc, "%s - %c %04u-%02u-%02u %02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
+ year, month, day, hour, minute, second, mic);
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_multi(ulonglong num0,
+ longlong num1,
+ double num2,
+ const char *num3,
+ const char *string4, size_t len4, CHARSET_INFO *cs4,
+ uint year5, uint month5, uint day5,
+ uint neg6, uint hour6, uint minute6,
+ uint second6, uint mic6,
+ uint neg7, uint year7, uint month7, uint day7,
+ uint hour7, uint minute7, uint second7,
+ uint mic7,
+ uint *column_numbers,
+ const char *name)
+{
+ char *end3= (((char*)num3) + strlen(num3));
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN_VALUE val[9], res[9];
+ DYNAMIC_COLUMN str;
+ /* init values */
+ val[0].type= DYN_COL_UINT;
+ val[0].ulong_value= num0;
+ val[1].type= DYN_COL_INT;
+ val[1].long_value= num1;
+ val[2].type= DYN_COL_DOUBLE;
+ val[2].double_value= num2;
+ dynamic_column_prepare_decimal(val + 3); // special procedure for decimal!!!
+ if (string2decimal(num3, &val[3].decimal_value, &end3) != E_DEC_OK)
+ goto err;
+ val[4].type= DYN_COL_STRING;
+ val[4].string_value.str= (char*)string4;
+ val[4].string_value.length= len4;
+ val[4].charset= cs4;
+ val[5].type= DYN_COL_DATE;
+ val[5].time_value.time_type= MYSQL_TIMESTAMP_DATE;
+ val[5].time_value.year= year5;
+ val[5].time_value.month= month5;
+ val[5].time_value.day= day5;
+ val[6].type= DYN_COL_TIME;
+ val[6].time_value.time_type= MYSQL_TIMESTAMP_TIME;
+ val[6].time_value.neg= neg6;
+ val[6].time_value.hour= hour6;
+ val[6].time_value.minute= minute6;
+ val[6].time_value.second= second6;
+ val[6].time_value.second_part= mic6;
+ val[7].type= DYN_COL_DATETIME;
+ val[7].time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
+ val[7].time_value.neg= neg7;
+ val[7].time_value.year= year7;
+ val[7].time_value.month= month7;
+ val[7].time_value.day= day7;
+ val[7].time_value.hour= hour7;
+ val[7].time_value.minute= minute7;
+ val[7].time_value.second= second7;
+ val[7].time_value.second_part= mic7;
+ val[8].type= DYN_COL_NULL;
+ for (i= 0; i < 9; i++)
+ dynamic_column_value_init(res + i);
+ /* create column */
+ if (dynamic_column_create_many(&str, 9, column_numbers, val))
+ goto err;
+ dynstr_append(&str, "\1"); str.length--; //check for overflow
+ /* read column */
+ for (i= 0; i < 9; i++)
+ if (dynamic_column_get(&str, column_numbers[i], res + i))
+ goto err;
+ rc= ((res[0].type == DYN_COL_UINT) &&
+ (res[0].ulong_value == num0) &&
+ (res[1].type == DYN_COL_INT) &&
+ (res[1].long_value == num1) &&
+ (res[2].type == DYN_COL_DOUBLE) &&
+ (res[2].double_value == num2) &&
+ (res[3].type == DYN_COL_DECIMAL) &&
+ (decimal_cmp(&res[3].decimal_value, &val[3].decimal_value) == 0) &&
+ (res[4].type == DYN_COL_STRING) &&
+ (res[4].string_value.length == len4) &&
+ (memcmp(res[4].string_value.str, string4, len4) == 0) &&
+ (res[4].charset->number == cs4->number) &&
+ (res[5].type == DYN_COL_DATE) &&
+ (res[5].time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
+ (res[5].time_value.year == year5) &&
+ (res[5].time_value.month == month5) &&
+ (res[5].time_value.day == day5) &&
+ (res[6].type == DYN_COL_TIME) &&
+ (res[6].time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
+ (res[6].time_value.neg == (int)neg6) &&
+ (res[6].time_value.hour == hour6) &&
+ (res[6].time_value.minute == minute6) &&
+ (res[6].time_value.second == second6) &&
+ (res[6].time_value.second_part == mic6) &&
+ (res[7].type == DYN_COL_DATETIME) &&
+ (res[7].time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
+ (res[7].time_value.neg == (int)neg7) &&
+ (res[7].time_value.year == year7) &&
+ (res[7].time_value.month == month7) &&
+ (res[7].time_value.day == day7) &&
+ (res[7].time_value.hour == hour7) &&
+ (res[7].time_value.minute == minute7) &&
+ (res[7].time_value.second == second7) &&
+ (res[7].time_value.second_part == mic7) &&
+ (res[8].type == DYN_COL_NULL));
+err:
+ ok(rc, "%s", name);
+ /* cleanup */
+ val[4].string_value.str= NULL; // we did not allocated it
+ dynamic_column_column_free(&str);
+}
+
+
+void test_value_multi_same_num()
+{
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN_VALUE val[5];
+ uint column_numbers[]= {3,4,5,3,6}; // same column numbers
+ DYNAMIC_COLUMN str;
+ /* init values */
+ for (i= 0; i < 5; i++)
+ val[i].type= DYN_COL_NULL;
+ /* create column */
+ if (!dynamic_column_create_many(&str, 5, column_numbers, val))
+ goto err;
+ rc= TRUE;
+err:
+ ok(rc, "%s", "same column numbers check");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+
+void test_update_multi(uint *column_numbers, uint *column_values,
+ my_bool *null_values, int only_add, int all)
+{
+ int rc= FALSE;
+ int i, j;
+ DYNAMIC_COLUMN str;
+ DYNAMIC_COLUMN_VALUE val;
+
+ val.type= DYN_COL_UINT;
+ val.ulong_value= column_values[0];
+ if (dynamic_column_create(&str, column_numbers[0], &val))
+ goto err;
+ for (i= 1; i < all; i++)
+ {
+ val.type= (null_values[i] ? DYN_COL_NULL : DYN_COL_UINT);
+ val.ulong_value= column_values[i];
+ if (dynamic_column_update(&str, column_numbers[i], &val))
+ goto err;
+
+ /* check value(s) */
+ for (j= i; j >= (i < only_add ? 0 : i); j--)
+ {
+ if (dynamic_column_get(&str, column_numbers[j], &val))
+ goto err;
+ if (null_values[j])
+ {
+ if (val.type != DYN_COL_NULL ||
+ dynamic_column_exists(&str, column_numbers[j]) == ER_DYNCOL_YES)
+ goto err;
+ }
+ else
+ {
+ if (val.type != DYN_COL_UINT ||
+ val.ulong_value != column_values[j] ||
+ dynamic_column_exists(&str, column_numbers[j]) == ER_DYNCOL_NO)
+ goto err;
+ }
+ }
+ if (i < only_add)
+ {
+ DYNAMIC_ARRAY num;
+ if (dynamic_column_list(&str, &num))
+ goto err;
+ /* cross check arrays */
+ if ((int)num.elements != i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ for(j= 0; j < i + 1; j++)
+ {
+ int k;
+ for(k= 0;
+ k < i + 1 && column_numbers[j] !=
+ *dynamic_element(&num, k, uint*);
+ k++);
+ if (k >= i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ for(k= 0;
+ k < i + 1 && column_numbers[k] !=
+ *dynamic_element(&num, j, uint*);
+ k++);
+ if (k >= i + 1)
+ {
+ delete_dynamic(&num);
+ goto err;
+ }
+ }
+ delete_dynamic(&num);
+ }
+ }
+
+ rc= TRUE;
+err:
+ ok(rc, "%s", "add/delete/update");
+ /* cleanup */
+ dynamic_column_column_free(&str);
+}
+
+void test_empty_string()
+{
+ DYNAMIC_COLUMN_VALUE val, res;
+ DYNAMIC_COLUMN str;
+ DYNAMIC_ARRAY array_of_uint;
+ int rc;
+ /* empty string */
+ bzero(&str, sizeof(str));
+
+ rc= dynamic_column_get(&str, 1, &res);
+ ok( (rc == ER_DYNCOL_OK) && (res.type == DYN_COL_NULL), "%s", "empty get");
+
+ rc= dynamic_column_delete(&str, 1);
+ ok( (rc == ER_DYNCOL_OK), "%s", "empty delete");
+
+ rc= dynamic_column_exists(&str, 1);
+ ok( (rc == ER_DYNCOL_NO), "%s", "empty exists");
+
+ rc= dynamic_column_list(&str, &array_of_uint);
+ ok( (rc == ER_DYNCOL_OK) && (array_of_uint.elements == 0),
+ "%s", "empty list");
+
+ val.type= DYN_COL_UINT;
+ val.ulong_value= 1212;
+ rc= dynamic_column_update(&str, 1, &val);
+ if (rc == ER_DYNCOL_OK)
+ rc= dynamic_column_get(&str, 1, &res);
+ ok( (rc == ER_DYNCOL_OK) &&
+ (res.type == DYN_COL_UINT) && (res.ulong_value == val.ulong_value),
+ "%s", "empty update");
+}
+
+
+void test_update_many(uint *column_numbers, uint *column_values,
+ uint column_count,
+ uint *update_numbers, uint *update_values,
+ my_bool *update_nulls, uint update_count,
+ uint *result_numbers, uint *result_values,
+ uint result_count)
+{
+ int rc= FALSE;
+ uint i;
+ DYNAMIC_COLUMN str1;
+ DYNAMIC_COLUMN str2;
+ DYNAMIC_COLUMN_VALUE *val, *upd, *res;
+
+ val= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ column_count);
+ upd= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ update_count);
+ res= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
+ result_count);
+
+
+ for (i= 0; i < column_count; i++)
+ {
+ val[i].type= DYN_COL_UINT;
+ val[i].ulong_value= column_values[i];
+ }
+ for (i= 0; i < update_count; i++)
+ {
+ if (update_nulls[i])
+ upd[i].type= DYN_COL_NULL;
+ else
+ {
+ upd[i].type= DYN_COL_UINT;
+ upd[i].ulong_value= update_values[i];
+ }
+ }
+ for (i= 0; i < result_count; i++)
+ {
+ res[i].type= DYN_COL_UINT;
+ res[i].ulong_value= result_values[i];
+ }
+ if (dynamic_column_create_many(&str1, column_count, column_numbers, val))
+ goto err;
+ if (dynamic_column_update_many(&str1, update_count, update_numbers, upd))
+ goto err;
+ if (dynamic_column_create_many(&str2, result_count, result_numbers, res))
+ goto err;
+ if (str1.length == str2.length &&
+ memcmp(str1.str, str2.str, str1.length) ==0)
+ rc= TRUE;
+
+err:
+ ok(rc, "%s", "update_many");
+ /* cleanup */
+ dynamic_column_column_free(&str1);
+ dynamic_column_column_free(&str2);
+}
+
+int main(int argc __attribute__((unused)), char **argv)
+{
+ uint i;
+ char *big_string= (char *)malloc(1024*1024);
+
+ MY_INIT(argv[0]);
+ plan(59);
+
+ if (!big_string)
+ exit(1);
+ for (i= 0; i < 1024*1024; i++)
+ big_string[i]= ('0' + (i % 10));
+ test_value_single_null();
+ test_value_single_uint(0, "0");
+ test_value_single_uint(0xffffffffffffffff, "0xffffffffffffffff");
+ test_value_single_uint(0xaaaaaaaaaaaaaaaa, "0xaaaaaaaaaaaaaaaa");
+ test_value_single_uint(0x5555555555555555, "0x5555555555555555");
+ test_value_single_uint(27652, "27652");
+ test_value_single_sint(0, "0");
+ test_value_single_sint(1, "1");
+ test_value_single_sint(-1, "-1");
+ test_value_single_sint((longlong)0x7fffffffffffffff,
+ "0x7fffffffffffffff");
+ test_value_single_sint((longlong)0xaaaaaaaaaaaaaaaa,
+ "0xaaaaaaaaaaaaaaaa");
+ test_value_single_sint((longlong)0x5555555555555555,
+ "0x5555555555555555");
+ test_value_single_sint((longlong)0x8000000000000000,
+ "0x8000000000000000");
+ test_value_single_double(0.0, "0.0");
+ test_value_single_double(1.0, "1.0");
+ test_value_single_double(-1.0, "-1.0");
+ test_value_single_double(1.0e100, "1.0e100");
+ test_value_single_double(1.0e-100, "1.0e-100");
+ test_value_single_double(9999999999999999999999999999999999999.0,
+ "9999999999999999999999999999999999999.0");
+ test_value_single_double(-9999999999999999999999999999999999999.0,
+ "-9999999999999999999999999999999999999.0");
+ test_value_single_decimal("0");
+ test_value_single_decimal("1");
+ test_value_single_decimal("-1");
+ test_value_single_decimal("9999999999999999999999999999999");
+ test_value_single_decimal("-9999999999999999999999999999999");
+ test_value_single_decimal("0.9999999999999999999999999999999");
+ test_value_single_decimal("-0.9999999999999999999999999999999");
+ test_value_single_string("", 0, charset_list[0]);
+ test_value_single_string("", 1, charset_list[0]);
+ test_value_single_string("1234567890", 11, charset_list[0]);
+ test_value_single_string("nulls\0\0\0\0\0", 10, charset_list[0]);
+ sprintf(big_string, "%x", 0x7a);
+ test_value_single_string(big_string, 0x7a, charset_list[0]);
+ sprintf(big_string, "%x", 0x80);
+ test_value_single_string(big_string, 0x80, charset_list[0]);
+ sprintf(big_string, "%x", 0x7ffa);
+ test_value_single_string(big_string, 0x7ffa, charset_list[0]);
+ sprintf(big_string, "%x", 0x8000);
+ test_value_single_string(big_string, 0x8000, charset_list[0]);
+ sprintf(big_string, "%x", 1024*1024);
+ test_value_single_string(big_string, 1024*1024, charset_list[0]);
+ free(big_string);
+ test_value_single_date(0, 0, 0, "zero date");
+ test_value_single_date(9999, 12, 31, "max date");
+ test_value_single_date(2011, 3, 26, "some date");
+ test_value_single_time(0, 0, 0, 0, 0, "zero time");
+ test_value_single_time(1, 23, 59, 59, 999999, "min time");
+ test_value_single_time(0, 23, 59, 59, 999999, "max time");
+ test_value_single_time(0, 21, 36, 20, 28, "some time");
+ test_value_single_datetime(0, 0, 0, 0, 0, 0, 0, 0, "zero datetime");
+ test_value_single_datetime(1, 9999, 12, 31, 23, 59, 59, 999999,
+ "min datetime");
+ test_value_single_datetime(0, 9999, 12, 31, 23, 59, 59, 999999,
+ "max datetime");
+ test_value_single_datetime(0, 2011, 3, 26, 21, 53, 12, 3445,
+ "some datetime");
+ {
+ uint column_numbers[]= {100,1,2,3,4,5,6,7,8};
+ test_value_multi(0, 0, 0.0, "0",
+ "", 0, charset_list[0],
+ 0, 0, 0,
+ 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ column_numbers,
+ "zero data");
+ }
+ {
+ uint column_numbers[]= {10,1,12,37,4,57,6,76,87};
+ test_value_multi(0xffffffffffffffff, 0x7fffffffffffffff,
+ 99999999.999e120, "9999999999999999999999999999999",
+ big_string, 1024*1024, charset_list[0],
+ 9999, 12, 31,
+ 0, 23, 59, 59, 999999,
+ 0, 9999, 12, 31, 23, 59, 59, 999999,
+ column_numbers,
+ "much data");
+ }
+ {
+ uint column_numbers[]= {101,12,122,37,24,572,16,726,77};
+ test_value_multi(37878, -3344,
+ 2873.3874, "92743.238984789898",
+ "string", 6, charset_list[0],
+ 2011, 3, 26,
+ 1, 23, 23, 20, 333,
+ 0, 2011, 3, 26, 23, 23, 53, 334,
+ column_numbers,
+ "zero data");
+ }
+ test_value_multi_same_num();
+ {
+ uint column_numbers[]= {1,2,3,4,5,6,7,2, 3, 4};
+ uint column_values[]= {1,2,3,4,5,6,7,0,30,40};
+ my_bool null_values[]= {0,0,0,0,0,0,0,1, 0, 0};
+
+ test_update_multi(column_numbers, column_values, null_values, 7, 10);
+ }
+ {
+ uint column_numbers[]= {4,3,2,1, 1,2,3,4};
+ uint column_values[]= {4,3,2,1, 0,0,0,0};
+ my_bool null_values[]= {0,0,0,0, 1,1,1,1};
+
+ test_update_multi(column_numbers, column_values, null_values, 4, 8);
+ }
+ {
+ uint column_numbers[]= {4,3,2,1, 4,3,2,1};
+ uint column_values[]= {4,3,2,1, 0,0,0,0};
+ my_bool null_values[]= {0,0,0,0, 1,1,1,1};
+
+ test_update_multi(column_numbers, column_values, null_values, 4, 8);
+ }
+ test_empty_string();
+ {
+ uint column_numbers[]= {1, 2, 3};
+ uint column_values[]= {1, 2, 3};
+ uint update_numbers[]= {4, 3, 2, 1};
+ uint update_values[]= {40,30, 0,10};
+ my_bool update_nulls[]={0, 0, 1, 0};
+ uint result_numbers[]= {1, 3, 4};
+ uint result_values[]= {10,30,40};
+ test_update_many(column_numbers, column_values, 3,
+ update_numbers, update_values, update_nulls, 4,
+ result_numbers, result_values, 3);
+ }
+ return 0;
+}