summaryrefslogtreecommitdiff
path: root/unittest
diff options
context:
space:
mode:
authorMichael Widenius <monty@askmonty.org>2011-05-08 13:24:06 +0300
committerMichael Widenius <monty@askmonty.org>2011-05-08 13:24:06 +0300
commit5ab92b1f850c62718907d166b47553440502043c (patch)
tree447166d5a99f147b27daa6f637b0a23df789a0aa /unittest
parent8ac88c88f0038350064429fda626233260eb6721 (diff)
downloadmariadb-git-5ab92b1f850c62718907d166b47553440502043c.tar.gz
Adding support for Dynamic columns (WL#34):
- COLUMN_CREATE(column_nr, value, [column_nr,value]...) - COLUMN_ADD(blob,column_nr, value, column_nr,value]...) - COLUMN_DELETE(blob, column_nr, column_nr...) - COLUMN_EXISTS(blob, column_nr) - COLUMN_LIST(blob, column_nr) - COLUMN_GET(string, column_nr AS type) Added cast(X as DOUBLE) and cast(x as INT) Better warning and error messages for wrong cast's Created some sub functions to simplify and reuse code. Added a lot of conversation functions with error/warnings for what went wrong. Fixed some issues when casting time to datetime. Added functions to dynamic strings and Strings to allow one to move a string buffer from dynamic strings to String (to save malloc+ copy) Added dynamic columns library to libmysqlclient include/Makefile.am: Added ma_dyncol.h include/decimal.h: Added 'const' to arguments for some functions. include/my_sys.h: Added dynstr_reassociate() include/my_time.h: Added TIME_SUBSECOND_RANGE Added double_to_datetime() Added flag argument to str_to_time() libmysql/CMakeLists.txt: Added mysys/ma_dyncol.c libmysql/Makefile.shared: Added ma_dyncol libmysql/libmysql.c: Added argument to str_to_time() mysql-test/r/bigint.result: Better error messages mysql-test/r/cast.result: Better warning and error messages A lot of new cast() tests mysql-test/r/func_math.result: Better warning messages mysql-test/r/func_str.result: Better warning messages mysql-test/r/func_time.result: Better warning messages mysql-test/r/sp-vars.result: Better warning messages mysql-test/r/strict.result: Better warning messages New test result mysql-test/r/type_newdecimal.result: Better warning messages mysql-test/r/warnings.result: Better warning messages mysql-test/suite/funcs_1/r/innodb_func_view.result: Updated results after better cast warnings mysql-test/suite/funcs_1/r/memory_func_view.result: Updated results after better cast warnings mysql-test/suite/funcs_1/r/myisam_func_view.result: Updated results after better cast warnings mysql-test/suite/optimizer_unfixed_bugs/t/bug43448.test: Added begin...commit to speed up test. mysql-test/suite/parts/inc/part_supported_sql_funcs_delete.inc: Added begin...commit to speed up test. mysql-test/suite/parts/inc/partition_supported_sql_funcs.inc: Added begin...commit to speed up test. mysql-test/suite/parts/r/part_supported_sql_func_innodb.result: Added begin...commit to speed up test. mysql-test/suite/parts/r/part_supported_sql_func_myisam.result: Added begin...commit to speed up test. mysql-test/suite/parts/r/rpl_partition.result: Added begin...commit to speed up test. mysql-test/suite/parts/t/part_supported_sql_func_innodb.test: Removed duplicated --big_test mysql-test/suite/parts/t/rpl_partition.test: Added begin...commit to speed up test. mysql-test/suite/pbxt/r/cast.result: Updated results after better cast warnings mysql-test/suite/pbxt/r/func_str.result: Updated results after better cast warnings mysql-test/suite/pbxt/r/type_newdecimal.result: Updated results after better cast warnings mysql-test/suite/rpl/r/rpl_innodb_bug28430.result: Added begin...commit to speed up test. mysql-test/suite/rpl/t/rpl_innodb_bug28430.test: Added begin...commit to speed up test. mysql-test/suite/vcol/r/vcol_supported_sql_funcs_innodb.result: More warnings mysql-test/suite/vcol/r/vcol_supported_sql_funcs_myisam.result: More warnings mysql-test/t/cast.test: A lot of new cast() tests mysql-test/t/strict.test: Added new test mysys/CMakeLists.txt: Added ma_dyncol.c mysys/Makefile.am: Added ma_dyncol.c mysys/string.c: Added dynstr_reassociate() to move a buffer from dynamic_strings to some other allocator sql-common/my_time.c: Added 'fuzzydate' flag to str_to_time() Added support for microseconds to my_time_to_str() and my_datetime_to_str() Reset second_parts in number_to_datetime() Added double_to_datetime() sql/field.cc: Added double_to_longlong() and truncate_double() to simplify and reuse code sql/field.h: New prototypes sql/item.cc: Changed Item::get_date(MYSQL_TIME *ltime,uint fuzzydate) to be aware of type of argument. (Needed to make it microsecond safe and get better warnings). Updated call to str_to_time_with_warn() sql/item.h: Added struct st_dyncall_create_def used by dynamic columns Added virtual bool dynamic_result() to tell if type of argument may change over calls. sql/item_cmpfunc.cc: Added Item_func_dyncol_exists() sql/item_cmpfunc.h: Added class Item_func_dyncol_exists sql/item_create.cc: Added get_length_and_scale() to simplify other functions Simplified and extended create_func_cast() Added support for cast(X as double(X,Y)) Added functions to create dynamic column functions. sql/item_create.h: Added prototypes sql/item_func.cc: Extended cast functions Item_func_signed() and Item_func_unsigned() to work with dynamic types Added Item_double_typecast() sql/item_func.h: Added class Item_double_typecast() sql/item_strfunc.cc: Added functions for COLUMN_CREATE(), COLUMN_ADD(), COLUMN_GET() and COLUMN_LIST() sql/item_strfunc.h: Added classes for COLUMN_CREATE(), COLUMN_ADD(), COLUMN_GET() and COLUMN_LIST() sql/item_timefunc.cc: Added flag argument to str_to_time_with_warn() Updated Item_char_typecast() to handle result type that may change between calls (for dynamic columns) Added Item_time_typecast::get_date() to ensure that we cast a datetime to time properly. sql/item_timefunc.h: Added get_date() to Item_time_typecast() to allow proper results for casting time to datetime sql/lex.h: Added new SQL function names sql/my_decimal.cc: Added 'const' to some arguments. Better error message in case of errors (we now print out the wrong value) Added my_decimal2int() sql/my_decimal.h: Moved some constants to my_decimal_limits.h Updated prototypes. Made my_decimal2int() a function as it's rather long (no reason to have it inline) Added decimal2my_decimal() function. sql/mysql_priv.h: Prototypes for new functions sql/share/errmsg.txt: New error messages for wrong casts and dynamic columns sql/sql_acl.cc: Fixed indentation sql/sql_base.cc: Added dynamic_column_error_message() sql/sql_string.h: Added reassociate() to move a buffer to be owned by String object. sql/sql_yacc.yy: Added syntax for COLUMN_ functions. sql/time.cc: Updated str_to_datetime_with_warn() flag argument to same type as other functions Added conversion flag to str_to_time_with_warn() (Similar to all datetime functions) Added conversion functions with warnings: double_to_datetime_with_warn() and decimal_to_datetime_with_warn() strings/decimal.c: Added 'const' to arguments for some functions. unittest/mysys/Makefile.am: Added test for dynamic columns code
Diffstat (limited to 'unittest')
-rw-r--r--unittest/mysys/Makefile.am2
-rw-r--r--unittest/mysys/ma_dyncol-t.c795
2 files changed, 796 insertions, 1 deletions
diff --git a/unittest/mysys/Makefile.am b/unittest/mysys/Makefile.am
index 07b9b94ab01..3a93f41afd1 100644
--- a/unittest/mysys/Makefile.am
+++ b/unittest/mysys/Makefile.am
@@ -25,4 +25,4 @@ LDADD = $(top_builddir)/unittest/mytap/libmytap.a \
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
diff --git a/unittest/mysys/ma_dyncol-t.c b/unittest/mysys/ma_dyncol-t.c
new file mode 100644
index 00000000000..0e973b20747
--- /dev/null
+++ b/unittest/mysys/ma_dyncol-t.c
@@ -0,0 +1,795 @@
+/* Copyright (c) 2011, Monty Program Ab
+ Copyright (c) 2011, Oleksandr Byelkin
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <m_string.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(60);
+
+ 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(ULL(0xffffffffffffffff), "0xffffffffffffffff");
+ test_value_single_uint(ULL(0xaaaaaaaaaaaaaaaa), "0xaaaaaaaaaaaaaaaa");
+ test_value_single_uint(ULL(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(LL(0x7fffffffffffffff),
+ "0x7fffffffffffffff");
+ test_value_single_sint(LL(0xaaaaaaaaaaaaaaaa),
+ "0xaaaaaaaaaaaaaaaa");
+ test_value_single_sint(LL(0x5555555555555555),
+ "0x5555555555555555");
+ test_value_single_sint(LL(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]);
+ 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(ULL(0xffffffffffffffff), LL(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");
+ }
+ free(big_string);
+ {
+ 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 exit_status();
+}