Commit 7327cd97 authored by unknown's avatar unknown

MDEV-377 Name support for dynamic columns

MDEV-127 Optimization of memory allocation
MDEV-483 Make column_check function which cheсks dynamic columns integrit
JSON conversion function
parent 4db207d5
...@@ -102,6 +102,13 @@ dynamic_column_create_many(DYNAMIC_COLUMN *str, ...@@ -102,6 +102,13 @@ dynamic_column_create_many(DYNAMIC_COLUMN *str,
uint *column_numbers, uint *column_numbers,
DYNAMIC_COLUMN_VALUE *values); DYNAMIC_COLUMN_VALUE *values);
enum enum_dyncol_func_result
dynamic_column_create_many_fmt(DYNAMIC_COLUMN *str,
uint column_count,
uchar *column_keys,
DYNAMIC_COLUMN_VALUE *values,
my_bool names);
enum enum_dyncol_func_result enum enum_dyncol_func_result
dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr, dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
DYNAMIC_COLUMN_VALUE *value); DYNAMIC_COLUMN_VALUE *value);
...@@ -110,16 +117,30 @@ dynamic_column_update_many(DYNAMIC_COLUMN *str, ...@@ -110,16 +117,30 @@ dynamic_column_update_many(DYNAMIC_COLUMN *str,
uint add_column_count, uint add_column_count,
uint *column_numbers, uint *column_numbers,
DYNAMIC_COLUMN_VALUE *values); DYNAMIC_COLUMN_VALUE *values);
enum enum_dyncol_func_result
dynamic_column_update_many_fmt(DYNAMIC_COLUMN *str,
uint add_column_count,
void *column_keys,
DYNAMIC_COLUMN_VALUE *values,
my_bool string_keys);
enum enum_dyncol_func_result enum enum_dyncol_func_result
dynamic_column_delete(DYNAMIC_COLUMN *org, uint column_nr); dynamic_column_delete(DYNAMIC_COLUMN *org, uint column_nr);
enum enum_dyncol_func_result enum enum_dyncol_func_result
dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr); dynamic_column_exists(DYNAMIC_COLUMN *org, uint column_nr);
enum enum_dyncol_func_result
dynamic_column_exists_str(DYNAMIC_COLUMN *str, LEX_STRING *name);
enum enum_dyncol_func_result
dynamic_column_exists_fmt(DYNAMIC_COLUMN *str, void *key, my_bool string_keys);
/* List of not NULL columns */ /* List of not NULL columns */
enum enum_dyncol_func_result enum enum_dyncol_func_result
dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint); dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
enum enum_dyncol_func_result
dynamic_column_list_str(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_lexstr);
enum enum_dyncol_func_result
dynamic_column_list_fmt(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array, my_bool string_keys);
/* /*
if the column do not exists it is NULL if the column do not exists it is NULL
...@@ -127,6 +148,17 @@ dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint); ...@@ -127,6 +148,17 @@ dynamic_column_list(DYNAMIC_COLUMN *org, DYNAMIC_ARRAY *array_of_uint);
enum enum_dyncol_func_result enum enum_dyncol_func_result
dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr, dynamic_column_get(DYNAMIC_COLUMN *org, uint column_nr,
DYNAMIC_COLUMN_VALUE *store_it_here); DYNAMIC_COLUMN_VALUE *store_it_here);
enum enum_dyncol_func_result
dynamic_column_get_str(DYNAMIC_COLUMN *str, LEX_STRING *name,
DYNAMIC_COLUMN_VALUE *store_it_here);
my_bool dynamic_column_has_names(DYNAMIC_COLUMN *str);
enum enum_dyncol_func_result
dynamic_column_check(DYNAMIC_COLUMN *str);
enum enum_dyncol_func_result
dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
#define dynamic_column_initialize(A) memset((A), 0, sizeof(*(A))) #define dynamic_column_initialize(A) memset((A), 0, sizeof(*(A)))
#define dynamic_column_column_free(V) dynstr_free(V) #define dynamic_column_column_free(V) dynstr_free(V)
......
...@@ -793,12 +793,18 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append, ...@@ -793,12 +793,18 @@ my_bool dynstr_append_mem(DYNAMIC_STRING *str, const char *append,
size_t length); size_t length);
extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, extern my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append,
...); ...);
extern my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
const char *append, size_t len);
extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str); extern my_bool dynstr_set(DYNAMIC_STRING *str, const char *init_str);
extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size); extern my_bool dynstr_realloc(DYNAMIC_STRING *str, size_t additional_size);
extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n); extern my_bool dynstr_trunc(DYNAMIC_STRING *str, size_t n);
extern void dynstr_free(DYNAMIC_STRING *str); extern void dynstr_free(DYNAMIC_STRING *str);
extern void dynstr_reassociate(DYNAMIC_STRING *str, char **res, size_t *length, extern void dynstr_reassociate(DYNAMIC_STRING *str, char **res, size_t *length,
size_t *alloc_length); size_t *alloc_length);
extern uint32 copy_and_convert_extended(char *to, uint32 to_length,
CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs, uint *errors);
#ifdef HAVE_MLOCK #ifdef HAVE_MLOCK
extern void *my_malloc_lock(size_t length,myf flags); extern void *my_malloc_lock(size_t length,myf flags);
extern void my_free_lock(void *ptr); extern void my_free_lock(void *ptr);
......
...@@ -1088,7 +1088,7 @@ column_list(column_add(column_create(1, 1), 1, null)) ...@@ -1088,7 +1088,7 @@ column_list(column_add(column_create(1, 1), 1, null))
select column_list(column_add(column_create(1, 1), 1, "")); select column_list(column_add(column_create(1, 1), 1, ""));
column_list(column_add(column_create(1, 1), 1, "")) column_list(column_add(column_create(1, 1), 1, ""))
1 `1`
select hex(column_add("", 1, 1)); select hex(column_add("", 1, 1));
hex(column_add("", 1, 1)) hex(column_add("", 1, 1))
00010001000002 00010001000002
...@@ -1133,10 +1133,10 @@ column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4) ...@@ -1133,10 +1133,10 @@ column_exists(column_create(1, 1212 as integer, 2, 1212 as integer), 4)
# column list # column list
select column_list(column_create(1, 1212 as integer, 2, 1212 as integer)); 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)) column_list(column_create(1, 1212 as integer, 2, 1212 as integer))
1,2 `1`,`2`
select column_list(column_create(1, 1212 as integer)); select column_list(column_create(1, 1212 as integer));
column_list(column_create(1, 1212 as integer)) column_list(column_create(1, 1212 as integer))
1 `1`
select column_list(column_create(1, NULL as integer)); select column_list(column_create(1, NULL as integer));
column_list(column_create(1, NULL as integer)) column_list(column_create(1, NULL as integer))
...@@ -1218,35 +1218,35 @@ sum(column_get(str, 1 as int)) ...@@ -1218,35 +1218,35 @@ sum(column_get(str, 1 as int))
11 11
select id, column_list(str) from t1 where id= 5; select id, column_list(str) from t1 where id= 5;
id column_list(str) id column_list(str)
5 1,2,3,10 5 `1`,`2`,`3`,`10`
update t1 set str=column_delete(str, 3, 4, 2) where id= 5; update t1 set str=column_delete(str, 3, 4, 2) where id= 5;
select id, length(str), column_list(str), column_get(str, 1 as int), column_get(str, 2 as char), column_get(str, 3 as int) from t1; select id, length(str), column_list(str), column_get(str, 1 as int), column_get(str, 2 as char), column_get(str, 3 as int) from t1;
id length(str) column_list(str) column_get(str, 1 as int) column_get(str, 2 as char) column_get(str, 3 as int) id length(str) column_list(str) column_get(str, 1 as int) column_get(str, 2 as char) column_get(str, 3 as int)
1 12 1,2 1 a NULL 1 12 `1`,`2` 1 a NULL
2 12 1,2 2 a NULL 2 12 `1`,`2` 2 a NULL
3 12 2,3 NULL c 100 3 12 `2`,`3` NULL c 100
4 16 1,2,3 5 c 100 4 16 `1`,`2`,`3` 5 c 100
5 15 1,10 6 NULL NULL 5 15 `1`,`10` 6 NULL NULL
6 21 2,3,10 NULL c 100 6 21 `2`,`3`,`10` NULL c 100
update t1 set str=column_add(str, 4, 45 as char, 2, 'c') where id= 5; update t1 set str=column_add(str, 4, 45 as char, 2, 'c') where id= 5;
select id, length(str), column_list(str), column_get(str, 1 as int), column_get(str, 2 as char), column_get(str, 3 as int) from t1 where id = 5; select id, length(str), column_list(str), column_get(str, 1 as int), column_get(str, 2 as char), column_get(str, 3 as int) from t1 where id = 5;
id length(str) column_list(str) column_get(str, 1 as int) column_get(str, 2 as char) column_get(str, 3 as int) id length(str) column_list(str) column_get(str, 1 as int) column_get(str, 2 as char) column_get(str, 3 as int)
5 26 1,2,4,10 6 c NULL 5 26 `1`,`2`,`4`,`10` 6 c NULL
select id, length(str), column_list(str), column_exists(str, 4) from t1; select id, length(str), column_list(str), column_exists(str, 4) from t1;
id length(str) column_list(str) column_exists(str, 4) id length(str) column_list(str) column_exists(str, 4)
1 12 1,2 0 1 12 `1`,`2` 0
2 12 1,2 0 2 12 `1`,`2` 0
3 12 2,3 0 3 12 `2`,`3` 0
4 16 1,2,3 0 4 16 `1`,`2`,`3` 0
5 26 1,2,4,10 1 5 26 `1`,`2`,`4`,`10` 1
6 21 2,3,10 0 6 21 `2`,`3`,`10` 0
select sum(column_get(str, 1 as int)), column_list(str) from t1 group by 2; select sum(column_get(str, 1 as int)), column_list(str) from t1 group by 2;
sum(column_get(str, 1 as int)) column_list(str) sum(column_get(str, 1 as int)) column_list(str)
3 1,2 3 `1`,`2`
5 1,2,3 5 `1`,`2`,`3`
6 1,2,4,10 6 `1`,`2`,`4`,`10`
NULL 2,3 NULL `2`,`3`
NULL 2,3,10 NULL `2`,`3`,`10`
select id, hex(str) from t1; select id, hex(str) from t1;
id hex(str) id hex(str)
1 00020001000002000B020861 1 00020001000002000B020861
...@@ -1282,11 +1282,11 @@ id ...@@ -1282,11 +1282,11 @@ id
5 5
select id, column_list(str), length(str) from t1 where id=5; select id, column_list(str), length(str) from t1 where id=5;
id column_list(str) length(str) id column_list(str) length(str)
5 1,2,4,5,10 100048 5 `1`,`2`,`4`,`5`,`10` 100048
update t1 set str=column_delete(str, 5) where id=5; update t1 set str=column_delete(str, 5) where id=5;
select id, column_list(str), length(str) from t1 where id=5; select id, column_list(str), length(str) from t1 where id=5;
id column_list(str) length(str) id column_list(str) length(str)
5 1,2,4,10 34 5 `1`,`2`,`4`,`10` 34
drop table t1; drop table t1;
# #
# LP#778905: Assertion `value->year <= 9999' failed in # LP#778905: Assertion `value->year <= 9999' failed in
...@@ -1306,7 +1306,7 @@ INSERT INTO t1 SET f1 = COLUMN_CREATE( 2 , 'cde' ); ...@@ -1306,7 +1306,7 @@ INSERT INTO t1 SET f1 = COLUMN_CREATE( 2 , 'cde' );
SELECT HEX(COLUMN_ADD(f1, 1, 'abc')), COLUMN_LIST(f1) FROM t1; SELECT HEX(COLUMN_ADD(f1, 1, 'abc')), COLUMN_LIST(f1) FROM t1;
HEX(COLUMN_ADD(f1, 1, 'abc')) COLUMN_LIST(f1) HEX(COLUMN_ADD(f1, 1, 'abc')) COLUMN_LIST(f1)
NULL NULL NULL NULL
0002000100030200230861626308636465 2 0002000100030200230861626308636465 `2`
SELECT COLUMN_ADD(f1, 1, 'abc'), COLUMN_LIST(f1) FROM t1; SELECT COLUMN_ADD(f1, 1, 'abc'), COLUMN_LIST(f1) FROM t1;
DROP TABLE t1; DROP TABLE t1;
# #
...@@ -1335,3 +1335,245 @@ hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal)) ...@@ -1335,3 +1335,245 @@ hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))
select hex(COLUMN_CREATE(0, 0.0 as decimal)); select hex(COLUMN_CREATE(0, 0.0 as decimal));
hex(COLUMN_CREATE(0, 0.0 as decimal)) hex(COLUMN_CREATE(0, 0.0 as decimal))
000100000004 000100000004
#
# test of symbolic names
#
# creation test (names)
set names utf8;
select hex(column_create("адын", 1212));
hex(column_create("адын", 1212))
040100080008000000D0B0D0B4D18BD0BD7809
select hex(column_create("1212", 1212));
hex(column_create("1212", 1212))
040100040004000000313231327809
select hex(column_create(1212, 2, "www", 3));
hex(column_create(1212, 2, "www", 3))
04020007000300000004030008777777313231320604
select hex(column_create("1212", 2, "www", 3));
hex(column_create("1212", 2, "www", 3))
04020007000300000004030008777777313231320604
select hex(column_create("1212", 2, 3, 3));
hex(column_create("1212", 2, 3, 3))
0402000500010000000401000833313231320604
select hex(column_create("1212", 2, "адын", 1, 3, 3));
hex(column_create("1212", 2, "адын", 1, 3, 3))
0403000D000100000004010008080500103331323132D0B0D0B4D18BD0BD060402
set names default;
# fetching column test (names)
set names utf8;
select column_get(column_create("адын", 1212), "адын" as int);
column_get(column_create("адын", 1212), "адын" as int)
1212
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int)
1
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int)
2
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int)
3
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int)
3
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int)
NULL
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int);
column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int)
NULL
set names default;
# column existance test (names)
set names utf8;
select column_exists(column_create("адын", 1212), "адын");
column_exists(column_create("адын", 1212), "адын")
1
select column_exists(column_create("адын", 1212), "aады");
column_exists(column_create("адын", 1212), "aады")
0
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын");
column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын")
1
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212);
column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212)
1
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3");
column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3")
1
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3);
column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3)
1
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4);
column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4)
0
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4");
column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4")
0
set names default;
# column changing test (names)
select hex(column_add(column_create(1, "AAA"), "b", "BBB"));
hex(column_add(column_create(1, "AAA"), "b", "BBB"))
0402000200010000030101002331620841414108424242
select hex(column_add(column_create("1", "AAA"), "b", "BBB"));
hex(column_add(column_create("1", "AAA"), "b", "BBB"))
0402000200010000030101002331620841414108424242
select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char);
column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char)
AAA
select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char);
column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char)
BBB
select hex(column_add(column_create("a", "AAA"), 1, "BBB"));
hex(column_add(column_create("a", "AAA"), 1, "BBB"))
0402000200010000030101002331610842424208414141
select hex(column_add(column_create("a", "AAA"), "1", "BBB"));
hex(column_add(column_create("a", "AAA"), "1", "BBB"))
0402000200010000030101002331610842424208414141
select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer));
hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer))
04020002000100000001010010616278097809
select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer));
hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer))
040100010001000000617809
select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer));
hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer))
0400000000
select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer));
hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer))
040100010001000000617809
select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer));
hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer))
040200020001000000010100086162167809
select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer);
column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer)
11
select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer);
column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer)
1212
select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer));
hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer))
040200020001000000010100106162780916
select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer));
hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer))
040200020001000000010100106162780916
select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer));
hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer))
040200020001000000010100086162167809
select hex(column_add(column_create("a", 1), "a", null));
hex(column_add(column_create("a", 1), "a", null))
0400000000
select column_list(column_add(column_create("a", 1), "a", null));
column_list(column_add(column_create("a", 1), "a", null))
select column_list(column_add(column_create("a", 1), "a", ""));
column_list(column_add(column_create("a", 1), "a", ""))
`a`
select hex(column_add("", "a", 1));
hex(column_add("", "a", 1))
0401000100010000006102
# column delete (names)
select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a"));
hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a"))
040100010001000000627809
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b"))
0402000200010000000101000861630206
select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer));
hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer))
0403000300010000000101000801020010616263020406
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c"))
0402000200010000000101000861620204
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d"))
0403000300010000000101000801020010616263020406
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a"))
0401000100010000006306
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c"))
0401000100010000006102
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c"))
0400000000
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e"));
hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e"))
0400000000
select hex(column_delete(column_create("a", 1), "a"));
hex(column_delete(column_create("a", 1), "a"))
0400000000
select hex(column_delete("", "a"));
hex(column_delete("", "a"))
#
# MDEV-458 DNAMES: Server crashes on using an unquoted string
# as a dynamic column name
#
select COLUMN_CREATE(color, "black");
ERROR 42S22: Unknown column 'color' in 'field list'
#
# MDEV-489 Assertion `offset < 0x1f' failed in
# type_and_offset_store on COLUMN_ADD
#
CREATE TABLE t1 (f1 tinyblob);
INSERT INTO t1 VALUES (COLUMN_CREATE('col1', REPEAT('a',30)));
UPDATE t1 SET f1 = COLUMN_ADD( f1, REPEAT('b',211), 'val2' );
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
UPDATE t1 SET f1 = COLUMN_ADD( f1, REPEAT('c',211), 'val3' );
ERROR HY000: Encountered illegal format of dynamic column string
drop table t1;
#
# MDEV-490/MDEV-491 null as arguments
#
SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR );
COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR )
NULL
SELECT COLUMN_GET( NULL, 'col' as char );
COLUMN_GET( NULL, 'col' as char )
NULL
SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL);
COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL)
NULL
SELECT COLUMN_EXISTS( NULL, 'col');
COLUMN_EXISTS( NULL, 'col')
NULL
SELECT COLUMN_CREATE( NULL, 'val' );
COLUMN_CREATE( NULL, 'val' )
NULL
SELECT COLUMN_ADD( NULL, 'val', 'col');
COLUMN_ADD( NULL, 'val', 'col')
NULL
#
# MDEV-488: Assertion `column_name->length < 255' failed on a
# column name with length 255 (precisely)
#
SELECT hex(COLUMN_CREATE(REPEAT('a',255),1));
hex(COLUMN_CREATE(REPEAT('a',255),1))
040100FF00FF00000061616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616102
SELECT hex(COLUMN_CREATE(REPEAT('a',256),1));
ERROR 22007: Illegal value used as argument of dynamic column function
#
# JSON conversion
#
select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date));
column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001"
[{"int":-1212},{"date":"2011-04-05"},{"time":"00:45:49.000001"},{"uint":12334},{"double":"1.23444e+50"},{"string":"gdgd\\dhdjh\"dhdhd"},{"decimal":23.344},{"datetime":"2011-04-05 00:45:49.000001"}]
select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date));
column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date))
[{"1":-1212},{"2":12334},{"3":23.344},{"4":"1.23444e+50"},{"5":"gdgd\\dhdjh\"dhdhd"},{"6":"00:45:49.000001"},{"7":"2011-04-05 00:45:49.000001"},{"8":"2011-04-05"}]
#
# CHECK test
#
SELECT COLUMN_CHECK(COLUMN_CREATE(1,'a'));
COLUMN_CHECK(COLUMN_CREATE(1,'a'))
1
SELECT COLUMN_CHECK('abracadabra');
COLUMN_CHECK('abracadabra')
0
SELECT COLUMN_CHECK('');
COLUMN_CHECK('')
1
SELECT COLUMN_CHECK(NULL);
COLUMN_CHECK(NULL)
NULL
...@@ -550,3 +550,125 @@ select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0)))); ...@@ -550,3 +550,125 @@ select hex(COLUMN_CREATE(0, COLUMN_GET(@a, 9 AS DECIMAL(19,0))));
select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal))); select hex(COLUMN_CREATE(0, COLUMN_GET(COLUMN_CREATE(0, 0.0 as decimal), 0 as decimal)));
select hex(COLUMN_CREATE(0, 0.0 as decimal)); select hex(COLUMN_CREATE(0, 0.0 as decimal));
--echo #
--echo # test of symbolic names
--echo #
--echo # creation test (names)
set names utf8;
select hex(column_create("адын", 1212));
select hex(column_create("1212", 1212));
select hex(column_create(1212, 2, "www", 3));
select hex(column_create("1212", 2, "www", 3));
select hex(column_create("1212", 2, 3, 3));
select hex(column_create("1212", 2, "адын", 1, 3, 3));
set names default;
--echo # fetching column test (names)
set names utf8;
select column_get(column_create("адын", 1212), "адын" as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "адын" as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 1212 as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "3" as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 3 as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), 4 as int);
select column_get(column_create("1212", 2, "адын", 1, 3, 3), "4" as int);
set names default;
--echo # column existance test (names)
set names utf8;
select column_exists(column_create("адын", 1212), "адын");
select column_exists(column_create("адын", 1212), "aады");
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "адын");
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 1212);
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "3");
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 3);
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), 4);
select column_exists(column_create("1212", 2, "адын", 1, 3, 3), "4");
set names default;
--echo # column changing test (names)
select hex(column_add(column_create(1, "AAA"), "b", "BBB"));
select hex(column_add(column_create("1", "AAA"), "b", "BBB"));
select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), 1 as char);
select column_get(column_add(column_create(1, "AAA"), "b", "BBB"), "b" as char);
select hex(column_add(column_create("a", "AAA"), 1, "BBB"));
select hex(column_add(column_create("a", "AAA"), "1", "BBB"));
select hex(column_add(column_create("a", 1212 as integer), "b", "1212" as integer));
select hex(column_add(column_create("a", 1212 as integer), "a", "1212" as integer));
select hex(column_add(column_create("a", 1212 as integer), "a", NULL as integer));
select hex(column_add(column_create("a", 1212 as integer), "b", NULL as integer));
select hex(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer));
select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "a" as integer);
select column_get(column_add(column_create("a", 1212 as integer), "b", 1212 as integer, "a", 11 as integer), "b" as integer);
select hex(column_add(column_create("a", 1212 as integer), "a", 1212 as integer, "b", 11 as integer));
select hex(column_add(column_create("a", NULL as integer), "a", 1212 as integer, "b", 11 as integer));
select hex(column_add(column_create("a", 1212 as integer, "b", 1212 as integer), "a", 11 as integer));
select hex(column_add(column_create("a", 1), "a", null));
select column_list(column_add(column_create("a", 1), "a", null));
select column_list(column_add(column_create("a", 1), "a", ""));
select hex(column_add("", "a", 1));
-- echo # column delete (names)
select hex(column_delete(column_create("a", 1212 as integer, "b", 1212 as integer), "a"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b"));
select hex(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "c"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "d"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "a"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "b", "c"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c"));
select hex(column_delete(column_create("a", 1 as integer, "b", 2 as integer, "c", 3 as integer), "a", "b", "c", "e"));
select hex(column_delete(column_create("a", 1), "a"));
select hex(column_delete("", "a"));
--echo #
--echo # MDEV-458 DNAMES: Server crashes on using an unquoted string
--echo # as a dynamic column name
--echo #
--error ER_BAD_FIELD_ERROR
select COLUMN_CREATE(color, "black");
--echo #
--echo # MDEV-489 Assertion `offset < 0x1f' failed in
--echo # type_and_offset_store on COLUMN_ADD
--echo #
CREATE TABLE t1 (f1 tinyblob);
INSERT INTO t1 VALUES (COLUMN_CREATE('col1', REPEAT('a',30)));
UPDATE t1 SET f1 = COLUMN_ADD( f1, REPEAT('b',211), 'val2' );
--error ER_DYN_COL_WRONG_FORMAT
UPDATE t1 SET f1 = COLUMN_ADD( f1, REPEAT('c',211), 'val3' );
drop table t1;
--echo #
--echo # MDEV-490/MDEV-491 null as arguments
--echo #
SELECT COLUMN_GET( COLUMN_CREATE( 'col', 'val' ), NULL AS CHAR );
SELECT COLUMN_GET( NULL, 'col' as char );
SELECT COLUMN_EXISTS( COLUMN_CREATE( 'col', 'val' ), NULL);
SELECT COLUMN_EXISTS( NULL, 'col');
SELECT COLUMN_CREATE( NULL, 'val' );
SELECT COLUMN_ADD( NULL, 'val', 'col');
--echo #
--echo # MDEV-488: Assertion `column_name->length < 255' failed on a
--echo # column name with length 255 (precisely)
--echo #
SELECT hex(COLUMN_CREATE(REPEAT('a',255),1));
--error ER_DYN_COL_DATA
SELECT hex(COLUMN_CREATE(REPEAT('a',256),1));
--echo #
--echo # JSON conversion
--echo #
select column_json(column_create("int", -1212 as int, "uint", 12334 as unsigned int, "decimal", "23.344" as decimal, "double", 1.23444e50 as double, "string", 'gdgd\\dhdjh"dhdhd' as char, "time", "0:45:49.000001" AS time, "datetime", "2011-04-05 0:45:49.000001" AS datetime, "date", "2011-04-05" AS date));
select column_json(column_create(1, -1212 as int, 2, 12334 as unsigned int, 3, "23.344" as decimal, 4, 1.23444e50 as double, 5, 'gdgd\\dhdjh"dhdhd' as char, 6, "0:45:49.000001" AS time, 7, "2011-04-05 0:45:49.000001" AS datetime, 8, "2011-04-05" AS date));
--echo #
--echo # CHECK test
--echo #
SELECT COLUMN_CHECK(COLUMN_CREATE(1,'a'));
SELECT COLUMN_CHECK('abracadabra');
SELECT COLUMN_CHECK('');
SELECT COLUMN_CHECK(NULL);
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -175,6 +175,34 @@ my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...) ...@@ -175,6 +175,34 @@ my_bool dynstr_append_os_quoted(DYNAMIC_STRING *str, const char *append, ...)
return ret; return ret;
} }
my_bool dynstr_append_quoted(DYNAMIC_STRING *str,
const char *append, size_t len)
{
uint additional= (str->alloc_increment ? str->alloc_increment : 10);
uint lim= additional;
uint i;
if (dynstr_realloc(str, len + additional + 2))
return TRUE;
str->str[str->length++]= '"';
for (i= 0; i < len; i++)
{
register char c= append[i];
if (c == '"' || c == '\\')
{
if (!lim)
{
if (dynstr_realloc(str, additional))
return TRUE;
lim= additional;
}
lim--;
str->str[str->length++]= '\\';
}
str->str[str->length++]= c;
}
str->str[str->length++]= '"';
return FALSE;
}
void dynstr_free(DYNAMIC_STRING *str) void dynstr_free(DYNAMIC_STRING *str)
{ {
...@@ -193,3 +221,77 @@ void dynstr_reassociate(DYNAMIC_STRING *str, char **ptr, size_t *length, ...@@ -193,3 +221,77 @@ void dynstr_reassociate(DYNAMIC_STRING *str, char **ptr, size_t *length,
*alloc_length= str->max_length; *alloc_length= str->max_length;
str->str=0; str->str=0;
} }
/*
copy a string from one character set to another
SYNOPSIS
copy_and_convert()
to Store result here
to_cs Character set of result string
from Copy from here
from_length Length of from string
from_cs From character set
NOTES
'to' must be big enough as form_length * to_cs->mbmaxlen
RETURN
length of bytes copied to 'to'
*/
uint32
copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs,
uint *errors)
{
int cnvres;
my_wc_t wc;
const uchar *from_end= (const uchar*) from+from_length;
char *to_start= to;
uchar *to_end= (uchar*) to+to_length;
my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
uint error_count= 0;
while (1)
{
if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
from_end)) > 0)
from+= cnvres;
else if (cnvres == MY_CS_ILSEQ)
{
error_count++;
from++;
wc= '?';
}
else if (cnvres > MY_CS_TOOSMALL)
{
/*
A correct multibyte sequence detected
But it doesn't have Unicode mapping.
*/
error_count++;
from+= (-cnvres);
wc= '?';
}
else
break; // Not enough characters
outp:
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
to+= cnvres;
else if (cnvres == MY_CS_ILUNI && wc != '?')
{
error_count++;
wc= '?';
goto outp;
}
else
break;
}
*errors= error_count;
return (uint32) (to - to_start);
}
...@@ -523,7 +523,7 @@ public: ...@@ -523,7 +523,7 @@ public:
struct st_dyncall_create_def struct st_dyncall_create_def
{ {
Item *num, *value; Item *key, *value;
CHARSET_INFO *cs; CHARSET_INFO *cs;
uint len, frac; uint len, frac;
DYNAMIC_COLUMN_TYPE type; DYNAMIC_COLUMN_TYPE type;
......
...@@ -6048,24 +6048,87 @@ Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item) ...@@ -6048,24 +6048,87 @@ Item* Item_equal::get_first(JOIN_TAB *context, Item *field_item)
return NULL; return NULL;
} }
longlong Item_func_dyncol_check::val_int()
longlong Item_func_dyncol_exists::val_int()
{ {
char buff[STRING_BUFFER_USUAL_SIZE]; char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff, sizeof(buff), &my_charset_bin); String tmp(buff, sizeof(buff), &my_charset_bin);
DYNAMIC_COLUMN col; DYNAMIC_COLUMN col;
String *str; String *str;
ulonglong num;
enum enum_dyncol_func_result rc; enum enum_dyncol_func_result rc;
str= args[0]->val_str(&tmp);
if (args[0]->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_check(&col);
if (rc < 0 && rc != ER_DYNCOL_FORMAT)
{
dynamic_column_error_message(rc);
goto null;
}
null_value= FALSE;
return rc == ER_DYNCOL_OK;
null:
null_value= TRUE;
return 0;
}
longlong Item_func_dyncol_exists::val_int()
{
char buff[STRING_BUFFER_USUAL_SIZE], nmstrbuf[11];
String tmp(buff, sizeof(buff), &my_charset_bin),
nmbuf(nmstrbuf, sizeof(nmstrbuf), system_charset_info);
DYNAMIC_COLUMN col;
String *str;
LEX_STRING buf, *name= NULL;
ulonglong num= 0;
enum enum_dyncol_func_result rc;
if (args[1]->result_type() == INT_RESULT)
num= args[1]->val_int(); num= args[1]->val_int();
else
{
String *nm= args[1]->val_str(&nmbuf);
if (!nm || args[1]->null_value)
{
null_value= 1;
return 1;
}
if (my_charset_same(nm->charset(), &my_charset_utf8_general_ci))
{
buf.str= (char *) nm->ptr();
buf.length= nm->length();
}
else
{
uint strlen;
uint dummy_errors;
buf.str= (char *)sql_alloc((strlen= nm->length() *
my_charset_utf8_general_ci.mbmaxlen + 1));
if (buf.str)
{
buf.length=
copy_and_convert(buf.str, strlen, &my_charset_utf8_general_ci,
nm->ptr(), nm->length(), nm->charset(),
&dummy_errors);
}
else
buf.length= 0;
}
name= &buf;
}
str= args[0]->val_str(&tmp); str= args[0]->val_str(&tmp);
if (args[0]->null_value || args[1]->null_value || num > UINT_MAX16) if (args[0]->null_value || args[1]->null_value || num > UINT_MAX16)
goto null; goto null;
col.length= str->length(); col.length= str->length();
/* We do not change the string, so could do this trick */ /* We do not change the string, so could do this trick */
col.str= (char *)str->ptr(); col.str= (char *)str->ptr();
rc= dynamic_column_exists(&col, (uint) num); rc= ((name == NULL) ?
dynamic_column_exists(&col, (uint) num) :
dynamic_column_exists_str(&col, name));
if (rc < 0) if (rc < 0)
{ {
dynamic_column_error_message(rc); dynamic_column_error_message(rc);
......
...@@ -1861,6 +1861,14 @@ public: ...@@ -1861,6 +1861,14 @@ public:
Item *neg_transformer(THD *thd); Item *neg_transformer(THD *thd);
}; };
class Item_func_dyncol_check :public Item_bool_func
{
public:
Item_func_dyncol_check(Item *str) :Item_bool_func(str) {}
longlong val_int();
const char *func_name() const { return "column_check"; }
};
class Item_func_dyncol_exists :public Item_bool_func class Item_func_dyncol_exists :public Item_bool_func
{ {
public: public:
......
...@@ -5704,7 +5704,7 @@ static List<Item> *create_func_dyncol_prepare(THD *thd, ...@@ -5704,7 +5704,7 @@ static List<Item> *create_func_dyncol_prepare(THD *thd,
for (uint i= 0; (def= li++) ;) for (uint i= 0; (def= li++) ;)
{ {
dfs[0][i++]= *def; dfs[0][i++]= *def;
args->push_back(def->num); args->push_back(def->key);
args->push_back(def->value); args->push_back(def->value);
} }
return args; return args;
...@@ -5720,6 +5720,10 @@ Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list) ...@@ -5720,6 +5720,10 @@ Item *create_func_dyncol_create(THD *thd, List<DYNCALL_CREATE_DEF> &list)
return new (thd->mem_root) Item_func_dyncol_create(*args, dfs); return new (thd->mem_root) Item_func_dyncol_create(*args, dfs);
} }
Item *create_func_dyncol_json(THD *thd, Item *str)
{
return new (thd->mem_root) Item_func_dyncol_json(str);
}
Item *create_func_dyncol_add(THD *thd, Item *str, Item *create_func_dyncol_add(THD *thd, Item *str,
List<DYNCALL_CREATE_DEF> &list) List<DYNCALL_CREATE_DEF> &list)
...@@ -5740,7 +5744,7 @@ Item *create_func_dyncol_add(THD *thd, Item *str, ...@@ -5740,7 +5744,7 @@ Item *create_func_dyncol_add(THD *thd, Item *str,
Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums) Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
{ {
DYNCALL_CREATE_DEF *dfs; DYNCALL_CREATE_DEF *dfs;
Item *num; Item *key;
List_iterator_fast<Item> it(nums); List_iterator_fast<Item> it(nums);
List<Item> *args= new (thd->mem_root) List<Item>; List<Item> *args= new (thd->mem_root) List<Item>;
...@@ -5750,12 +5754,12 @@ Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums) ...@@ -5750,12 +5754,12 @@ Item *create_func_dyncol_delete(THD *thd, Item *str, List<Item> &nums)
if (!args || !dfs) if (!args || !dfs)
return NULL; return NULL;
for (uint i= 0; (num= it++); i++) for (uint i= 0; (key= it++); i++)
{ {
dfs[i].num= num; dfs[i].key= key;
dfs[i].value= new Item_null(); dfs[i].value= new Item_null();
dfs[i].type= DYN_COL_INT; dfs[i].type= DYN_COL_INT;
args->push_back(dfs[i].num); args->push_back(dfs[i].key);
args->push_back(dfs[i].value); args->push_back(dfs[i].value);
} }
......
...@@ -180,5 +180,6 @@ Item *create_func_dyncol_get(THD *thd, Item *num, Item *str, ...@@ -180,5 +180,6 @@ Item *create_func_dyncol_get(THD *thd, Item *num, Item *str,
Cast_target cast_type, Cast_target cast_type,
const char *c_len, const char *c_dec, const char *c_len, const char *c_dec,
CHARSET_INFO *cs); CHARSET_INFO *cs);
Item *create_func_dyncol_json(THD *thd, Item *str);
#endif #endif
...@@ -3760,7 +3760,8 @@ String *Item_func_uuid::val_str(String *str) ...@@ -3760,7 +3760,8 @@ String *Item_func_uuid::val_str(String *str)
Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args, Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args,
DYNCALL_CREATE_DEF *dfs) DYNCALL_CREATE_DEF *dfs)
: Item_str_func(args), defs(dfs), vals(0), nums(0) : Item_str_func(args), defs(dfs), vals(0), keys(NULL), names(FALSE),
force_names(FALSE)
{ {
DBUG_ASSERT((args.elements & 0x1) == 0); // even number of arguments DBUG_ASSERT((args.elements & 0x1) == 0); // even number of arguments
} }
...@@ -3768,13 +3769,26 @@ Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args, ...@@ -3768,13 +3769,26 @@ Item_func_dyncol_create::Item_func_dyncol_create(List<Item> &args,
bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref) bool Item_func_dyncol_create::fix_fields(THD *thd, Item **ref)
{ {
uint i;
bool res= Item_func::fix_fields(thd, ref); // no need Item_str_func here bool res= Item_func::fix_fields(thd, ref); // no need Item_str_func here
if (!res)
{
vals= (DYNAMIC_COLUMN_VALUE *) alloc_root(thd->mem_root, vals= (DYNAMIC_COLUMN_VALUE *) alloc_root(thd->mem_root,
sizeof(DYNAMIC_COLUMN_VALUE) * sizeof(DYNAMIC_COLUMN_VALUE) *
(arg_count / 2)); (arg_count / 2));
nums= (uint *) alloc_root(thd->mem_root, for (i= 0; i + 1 < arg_count && args[i]->result_type() == INT_RESULT; i+= 2);
sizeof(uint) * (arg_count / 2)); if (i + 1 < arg_count)
return res || vals == 0 || nums == 0; {
names= TRUE;
}
keys= (uchar *) alloc_root(thd->mem_root,
(sizeof(LEX_STRING) > sizeof(uint) ?
sizeof(LEX_STRING) :
sizeof(uint)) *
(arg_count / 2));
}
return res || vals == 0 || keys == 0;
} }
...@@ -3785,13 +3799,14 @@ void Item_func_dyncol_create::fix_length_and_dec() ...@@ -3785,13 +3799,14 @@ void Item_func_dyncol_create::fix_length_and_dec()
decimals= 0; decimals= 0;
} }
void Item_func_dyncol_create::prepare_arguments() bool Item_func_dyncol_create::prepare_arguments(bool force_names_arg)
{ {
char buff[STRING_BUFFER_USUAL_SIZE]; char buff[STRING_BUFFER_USUAL_SIZE];
String *res, tmp(buff, sizeof(buff), &my_charset_bin); String *res, tmp(buff, sizeof(buff), &my_charset_bin);
uint column_count= (arg_count / 2); uint column_count= (arg_count / 2);
uint i; uint i;
my_decimal dtmp, *dres; my_decimal dtmp, *dres;
force_names= force_names_arg;
/* get values */ /* get values */
for (i= 0; i < column_count; i++) for (i= 0; i < column_count; i++)
...@@ -3850,7 +3865,54 @@ void Item_func_dyncol_create::prepare_arguments() ...@@ -3850,7 +3865,54 @@ void Item_func_dyncol_create::prepare_arguments()
break; break;
} }
} }
nums[i]= (uint) args[i * 2]->val_int(); if (names || force_names)
{
res= args[i * 2]->val_str(&tmp);
if (res)
{
// guaranty UTF-8 string for names
if (my_charset_same(res->charset(), &my_charset_utf8_general_ci))
{
((LEX_STRING *)keys)[i].length= res->length();
if (!(((LEX_STRING *)keys)[i].str=
(char *)sql_memdup(res->ptr(), res->length())))
((LEX_STRING *)keys)[i].length= 0;
}
else
{
uint strlen;
uint dummy_errors;
char *str=
(char *)sql_alloc((strlen= res->length() *
my_charset_utf8_general_ci.mbmaxlen + 1));
if (str)
{
((LEX_STRING *)keys)[i].length=
copy_and_convert(str, strlen, &my_charset_utf8_general_ci,
res->ptr(), res->length(), res->charset(),
&dummy_errors);
((LEX_STRING *)keys)[i].str= str;
}
else
((LEX_STRING *)keys)[i].length= 0;
}
}
else
{
((LEX_STRING *)keys)[i].length= 0;
((LEX_STRING *)keys)[i].str= NULL;
}
}
else
((uint *)keys)[i]= (uint) args[i * 2]->val_int();
if (args[i * 2]->null_value)
{
/* to make cleanup possible */
for (; i < column_count; i++)
vals[i].type= DYN_COL_NULL;
return 1;
}
vals[i].type= type; vals[i].type= type;
switch (type) { switch (type) {
case DYN_COL_NULL: case DYN_COL_NULL:
...@@ -3918,6 +3980,7 @@ void Item_func_dyncol_create::prepare_arguments() ...@@ -3918,6 +3980,7 @@ void Item_func_dyncol_create::prepare_arguments()
vals[i].type= DYN_COL_NULL; vals[i].type= DYN_COL_NULL;
} }
} }
return FALSE;
} }
void Item_func_dyncol_create::cleanup_arguments() void Item_func_dyncol_create::cleanup_arguments()
...@@ -3930,6 +3993,7 @@ void Item_func_dyncol_create::cleanup_arguments() ...@@ -3930,6 +3993,7 @@ void Item_func_dyncol_create::cleanup_arguments()
if (vals[i].type == DYN_COL_STRING) if (vals[i].type == DYN_COL_STRING)
my_free(vals[i].x.string.value.str); my_free(vals[i].x.string.value.str);
} }
force_names= FALSE;
} }
String *Item_func_dyncol_create::val_str(String *str) String *Item_func_dyncol_create::val_str(String *str)
...@@ -3940,9 +4004,15 @@ String *Item_func_dyncol_create::val_str(String *str) ...@@ -3940,9 +4004,15 @@ String *Item_func_dyncol_create::val_str(String *str)
enum enum_dyncol_func_result rc; enum enum_dyncol_func_result rc;
DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments DBUG_ASSERT((arg_count & 0x1) == 0); // even number of arguments
prepare_arguments(); if (prepare_arguments(FALSE))
{
if ((rc= dynamic_column_create_many(&col, column_count, nums, vals))) res= NULL;
null_value= 1;
}
else
{
if ((rc= dynamic_column_create_many_fmt(&col, column_count, keys,
vals, names || force_names)))
{ {
dynamic_column_error_message(rc); dynamic_column_error_message(rc);
dynamic_column_column_free(&col); dynamic_column_column_free(&col);
...@@ -3960,6 +4030,7 @@ String *Item_func_dyncol_create::val_str(String *str) ...@@ -3960,6 +4030,7 @@ String *Item_func_dyncol_create::val_str(String *str)
res= &str_value; res= &str_value;
null_value= FALSE; null_value= FALSE;
} }
}
/* cleanup */ /* cleanup */
cleanup_arguments(); cleanup_arguments();
...@@ -4026,6 +4097,40 @@ void Item_func_dyncol_create::print(String *str, ...@@ -4026,6 +4097,40 @@ void Item_func_dyncol_create::print(String *str,
str->append(')'); str->append(')');
} }
String *Item_func_dyncol_json::val_str(String *str)
{
DYNAMIC_STRING json, col;
String *res;
enum enum_dyncol_func_result rc;
res= args[0]->val_str(str);
if (args[0]->null_value)
goto null;
col.str= (char *)res->ptr();
col.length= res->length();
if ((rc= dynamic_column_json(&col, &json)))
{
dynamic_column_error_message(rc);
goto null;
}
bzero(&col, sizeof(col));
{
/* Move result from DYNAMIC_COLUMN to str */
char *ptr;
size_t length, alloc_length;
dynstr_reassociate(&json, &ptr, &length, &alloc_length);
str->reassociate(ptr, (uint32) length, (uint32) alloc_length,
&my_charset_utf8_general_ci);
null_value= FALSE;
}
return str;
null:
bzero(&col, sizeof(col));
null_value= TRUE;
return NULL;
}
String *Item_func_dyncol_add::val_str(String *str) String *Item_func_dyncol_add::val_str(String *str)
{ {
...@@ -4037,17 +4142,19 @@ String *Item_func_dyncol_add::val_str(String *str) ...@@ -4037,17 +4142,19 @@ String *Item_func_dyncol_add::val_str(String *str)
/* We store the packed data last */ /* We store the packed data last */
res= args[arg_count - 1]->val_str(str); res= args[arg_count - 1]->val_str(str);
if (args[arg_count - 1]->null_value) if (args[arg_count - 1]->null_value ||
goto null;
init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE, init_dynamic_string(&col, NULL, res->length() + STRING_BUFFER_USUAL_SIZE,
STRING_BUFFER_USUAL_SIZE); STRING_BUFFER_USUAL_SIZE))
goto null;
col.length= res->length(); col.length= res->length();
memcpy(col.str, res->ptr(), col.length); memcpy(col.str, res->ptr(), col.length);
prepare_arguments(); if (prepare_arguments(dynamic_column_has_names(&col)))
goto null;
if ((rc= dynamic_column_update_many(&col, column_count, nums, vals))) if ((rc= dynamic_column_update_many_fmt(&col, column_count, keys,
vals, names || force_names)))
{ {
dynamic_column_error_message(rc); dynamic_column_error_message(rc);
dynamic_column_column_free(&col); dynamic_column_column_free(&col);
...@@ -4066,7 +4173,6 @@ String *Item_func_dyncol_add::val_str(String *str) ...@@ -4066,7 +4173,6 @@ String *Item_func_dyncol_add::val_str(String *str)
} }
/* cleanup */ /* cleanup */
dynamic_column_column_free(&col);
cleanup_arguments(); cleanup_arguments();
return str; return str;
...@@ -4100,10 +4206,48 @@ bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp) ...@@ -4100,10 +4206,48 @@ bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp)
{ {
DYNAMIC_COLUMN dyn_str; DYNAMIC_COLUMN dyn_str;
String *res; String *res;
longlong num; longlong num= 0;
LEX_STRING buf, *name= NULL;
char nmstrbuf[11];
String nmbuf(nmstrbuf, sizeof(nmstrbuf), system_charset_info);
enum enum_dyncol_func_result rc; enum enum_dyncol_func_result rc;
if (args[1]->result_type() == INT_RESULT)
num= args[1]->val_int(); num= args[1]->val_int();
else
{
String *nm= args[1]->val_str(&nmbuf);
if (!nm || args[1]->null_value)
{
null_value= 1;
return 1;
}
if (my_charset_same(nm->charset(), &my_charset_utf8_general_ci))
{
buf.str= (char *) nm->ptr();
buf.length= nm->length();
}
else
{
uint strlen;
uint dummy_errors;
buf.str= (char *)sql_alloc((strlen= nm->length() *
my_charset_utf8_general_ci.mbmaxlen + 1));
if (buf.str)
{
buf.length=
copy_and_convert(buf.str, strlen, &my_charset_utf8_general_ci,
nm->ptr(), nm->length(), nm->charset(),
&dummy_errors);
}
else
buf.length= 0;
}
name= &buf;
}
if (args[1]->null_value || num < 0 || num > INT_MAX) if (args[1]->null_value || num < 0 || num > INT_MAX)
{ {
null_value= 1; null_value= 1;
...@@ -4119,7 +4263,9 @@ bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp) ...@@ -4119,7 +4263,9 @@ bool Item_dyncol_get::get_dyn_value(DYNAMIC_COLUMN_VALUE *val, String *tmp)
dyn_str.str= (char*) res->ptr(); dyn_str.str= (char*) res->ptr();
dyn_str.length= res->length(); dyn_str.length= res->length();
if ((rc= dynamic_column_get(&dyn_str, (uint) num, val))) if ((rc= ((name == NULL) ?
dynamic_column_get(&dyn_str, (uint) num, val) :
dynamic_column_get_str(&dyn_str, name, val))))
{ {
dynamic_column_error_message(rc); dynamic_column_error_message(rc);
null_value= 1; null_value= 1;
...@@ -4468,6 +4614,8 @@ null: ...@@ -4468,6 +4614,8 @@ null:
return 1; return 1;
} }
void
append_identifier(THD *thd, String *packet, const char *name, uint length);
void Item_dyncol_get::print(String *str, enum_query_type query_type) void Item_dyncol_get::print(String *str, enum_query_type query_type)
{ {
...@@ -4492,26 +4640,30 @@ String *Item_func_dyncol_list::val_str(String *str) ...@@ -4492,26 +4640,30 @@ String *Item_func_dyncol_list::val_str(String *str)
col.length= res->length(); col.length= res->length();
/* We do not change the string, so could do this trick */ /* We do not change the string, so could do this trick */
col.str= (char *)res->ptr(); col.str= (char *)res->ptr();
if ((rc= dynamic_column_list(&col, &arr))) if ((rc= dynamic_column_list_str(&col, &arr)))
{ {
dynamic_column_error_message(rc); dynamic_column_error_message(rc);
for (i= 0; i < arr.elements; i++)
my_free(dynamic_element(&arr, i, LEX_STRING*)->str);
delete_dynamic(&arr); delete_dynamic(&arr);
goto null; goto null;
} }
/* /*
We support elements from 0 - 65536, so max size for one element is We estimate average name length as 10
6 (including ,).
*/ */
if (str->alloc(arr.elements * 6)) if (str->alloc(arr.elements * 13))
goto null; goto null;
str->length(0); str->length(0);
str->set_charset(&my_charset_utf8_general_ci);
for (i= 0; i < arr.elements; i++) for (i= 0; i < arr.elements; i++)
{ {
str->qs_append(*dynamic_element(&arr, i, uint*)); LEX_STRING *name= dynamic_element(&arr, i, LEX_STRING *);
append_identifier(current_thd, str, name->str, name->length);
if (i < arr.elements - 1) if (i < arr.elements - 1)
str->qs_append(','); str->qs_append(',');
my_free(name->str);
} }
null_value= FALSE; null_value= FALSE;
......
...@@ -1001,8 +1001,9 @@ class Item_func_dyncol_create: public Item_str_func ...@@ -1001,8 +1001,9 @@ class Item_func_dyncol_create: public Item_str_func
protected: protected:
DYNCALL_CREATE_DEF *defs; DYNCALL_CREATE_DEF *defs;
DYNAMIC_COLUMN_VALUE *vals; DYNAMIC_COLUMN_VALUE *vals;
uint *nums; uchar *keys;
void prepare_arguments(); bool names, force_names;
bool prepare_arguments(bool force_names);
void cleanup_arguments(); void cleanup_arguments();
void print_arguments(String *str, enum_query_type query_type); void print_arguments(String *str, enum_query_type query_type);
public: public:
...@@ -1026,6 +1027,19 @@ public: ...@@ -1026,6 +1027,19 @@ public:
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
}; };
class Item_func_dyncol_json: public Item_str_func
{
public:
Item_func_dyncol_json(Item *str) :Item_str_func(str) {}
const char *func_name() const{ return "column_json"; }
String *val_str(String *);
void fix_length_and_dec()
{
maybe_null= TRUE;
collation.set(&my_charset_bin);
decimals= 0;
}
};
/* /*
The following functions is always called from an Item_cast function The following functions is always called from an Item_cast function
......
...@@ -123,10 +123,12 @@ static SYMBOL symbols[] = { ...@@ -123,10 +123,12 @@ static SYMBOL symbols[] = {
{ "COLUMN_NAME", SYM(COLUMN_NAME_SYM)}, { "COLUMN_NAME", SYM(COLUMN_NAME_SYM)},
{ "COLUMNS", SYM(COLUMNS)}, { "COLUMNS", SYM(COLUMNS)},
{ "COLUMN_ADD", SYM(COLUMN_ADD_SYM)}, { "COLUMN_ADD", SYM(COLUMN_ADD_SYM)},
{ "COLUMN_CHECK", SYM(COLUMN_CHECK_SYM)},
{ "COLUMN_CREATE", SYM(COLUMN_CREATE_SYM)}, { "COLUMN_CREATE", SYM(COLUMN_CREATE_SYM)},
{ "COLUMN_DELETE", SYM(COLUMN_DELETE_SYM)}, { "COLUMN_DELETE", SYM(COLUMN_DELETE_SYM)},
{ "COLUMN_EXISTS", SYM(COLUMN_EXISTS_SYM)}, { "COLUMN_EXISTS", SYM(COLUMN_EXISTS_SYM)},
{ "COLUMN_GET", SYM(COLUMN_GET_SYM)}, { "COLUMN_GET", SYM(COLUMN_GET_SYM)},
{ "COLUMN_JSON", SYM(COLUMN_JSON_SYM)},
{ "COLUMN_LIST", SYM(COLUMN_LIST_SYM)}, { "COLUMN_LIST", SYM(COLUMN_LIST_SYM)},
{ "COMMENT", SYM(COMMENT_SYM)}, { "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)}, { "COMMIT", SYM(COMMIT_SYM)},
......
...@@ -750,79 +750,6 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length) ...@@ -750,79 +750,6 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
Help functions Help functions
****************************************************************************/ ****************************************************************************/
/*
copy a string from one character set to another
SYNOPSIS
copy_and_convert()
to Store result here
to_cs Character set of result string
from Copy from here
from_length Length of from string
from_cs From character set
NOTES
'to' must be big enough as form_length * to_cs->mbmaxlen
RETURN
length of bytes copied to 'to'
*/
static uint32
copy_and_convert_extended(char *to, uint32 to_length, CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
CHARSET_INFO *from_cs,
uint *errors)
{
int cnvres;
my_wc_t wc;
const uchar *from_end= (const uchar*) from+from_length;
char *to_start= to;
uchar *to_end= (uchar*) to+to_length;
my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
uint error_count= 0;
while (1)
{
if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
from_end)) > 0)
from+= cnvres;
else if (cnvres == MY_CS_ILSEQ)
{
error_count++;
from++;
wc= '?';
}
else if (cnvres > MY_CS_TOOSMALL)
{
/*
A correct multibyte sequence detected
But it doesn't have Unicode mapping.
*/
error_count++;
from+= (-cnvres);
wc= '?';
}
else
break; // Not enough characters
outp:
if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
to+= cnvres;
else if (cnvres == MY_CS_ILUNI && wc != '?')
{
error_count++;
wc= '?';
goto outp;
}
else
break;
}
*errors= error_count;
return (uint32) (to - to_start);
}
/* /*
......
...@@ -882,10 +882,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -882,10 +882,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COLLATION_SYM /* SQL-2003-N */ %token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS %token COLUMNS
%token COLUMN_ADD_SYM %token COLUMN_ADD_SYM
%token COLUMN_CHECK_SYM
%token COLUMN_CREATE_SYM %token COLUMN_CREATE_SYM
%token COLUMN_DELETE_SYM %token COLUMN_DELETE_SYM
%token COLUMN_EXISTS_SYM %token COLUMN_EXISTS_SYM
%token COLUMN_GET_SYM %token COLUMN_GET_SYM
%token COLUMN_JSON_SYM
%token COLUMN_LIST_SYM %token COLUMN_LIST_SYM
%token COLUMN_SYM /* SQL-2003-R */ %token COLUMN_SYM /* SQL-2003-R */
%token COLUMN_NAME_SYM /* SQL-2003-N */ %token COLUMN_NAME_SYM /* SQL-2003-N */
...@@ -8245,7 +8247,7 @@ dyncall_create_element: ...@@ -8245,7 +8247,7 @@ dyncall_create_element:
alloc_root(YYTHD->mem_root, sizeof(DYNCALL_CREATE_DEF)); alloc_root(YYTHD->mem_root, sizeof(DYNCALL_CREATE_DEF));
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
$$->num= $1; $$->key= $1;
$$->value= $3; $$->value= $3;
$$->type= (DYNAMIC_COLUMN_TYPE)$4; $$->type= (DYNAMIC_COLUMN_TYPE)$4;
$$->cs= lex->charset; $$->cs= lex->charset;
...@@ -8798,6 +8800,13 @@ function_call_nonkeyword: ...@@ -8798,6 +8800,13 @@ function_call_nonkeyword:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
|
COLUMN_CHECK_SYM '(' expr ')'
{
$$= new (YYTHD->mem_root) Item_func_dyncol_check($3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| |
COLUMN_EXISTS_SYM '(' expr ',' expr ')' COLUMN_EXISTS_SYM '(' expr ',' expr ')'
{ {
...@@ -8819,6 +8828,13 @@ function_call_nonkeyword: ...@@ -8819,6 +8828,13 @@ function_call_nonkeyword:
if ($$ == NULL) if ($$ == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
} }
|
COLUMN_JSON_SYM '(' expr ')'
{
$$= create_func_dyncol_json(YYTHD, $3);
if ($$ == NULL)
MYSQL_YYABORT;
}
| |
COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')' COLUMN_GET_SYM '(' expr ',' expr AS cast_type ')'
{ {
...@@ -12908,10 +12924,12 @@ keyword: ...@@ -12908,10 +12924,12 @@ keyword:
| CHECKPOINT_SYM {} | CHECKPOINT_SYM {}
| CLOSE_SYM {} | CLOSE_SYM {}
| COLUMN_ADD_SYM {} | COLUMN_ADD_SYM {}
| COLUMN_CHECK_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_JSON_SYM {}
| COLUMN_LIST_SYM {} | COLUMN_LIST_SYM {}
| COMMENT_SYM {} | COMMENT_SYM {}
| COMMIT_SYM {} | COMMIT_SYM {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment