1 /* Copyright (c) 2011, Monty Program Ab
2    Copyright (c) 2011, Oleksandr Byelkin
3 
4    Redistribution and use in source and binary forms, with or without
5    modification, are permitted provided that the following conditions are
6    met:
7 
8    1. Redistributions of source code must retain the above copyright
9    notice, this list of conditions and the following disclaimer.
10 
11    2. Redistributions in binary form must the following disclaimer in
12      the documentation and/or other materials provided with the
13      distribution.
14 
15    THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
16    EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18    PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
19    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22    USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25    OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26    SUCH DAMAGE.
27 */
28 
29 #include <my_global.h>
30 #include <my_sys.h>
31 #include <m_string.h>
32 #include <ma_dyncol.h>
33 #include <tap.h>
34 
test_value_single_null()35 void test_value_single_null()
36 {
37   int rc= FALSE;
38   uint ids[1]= {1};
39   DYNAMIC_COLUMN_VALUE val, res;
40   DYNAMIC_COLUMN str;
41   /* init values */
42   val.type= DYN_COL_NULL;
43   mariadb_dyncol_value_init(&res);
44   /* create column */
45   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
46     goto err;
47   dynstr_append(&str, "\1"); str.length--; //check for overflow
48   /* read column */
49   if (mariadb_dyncol_get_num(&str, 1, &res))
50     goto err;
51   rc= (res.type == DYN_COL_NULL);
52 err:
53   ok(rc, "%s", "NULL");
54   /* cleanup */
55   mariadb_dyncol_free(&str);
56 }
57 
test_value_single_uint(ulonglong num,const char * name)58 void test_value_single_uint(ulonglong num, const char *name)
59 {
60   int rc= FALSE;
61   uint ids[1]= {1};
62   DYNAMIC_COLUMN_VALUE val, res;
63   DYNAMIC_COLUMN str;
64   /* init values */
65   val.type= DYN_COL_UINT;
66   val.x.ulong_value= num;
67   mariadb_dyncol_value_init(&res);
68   /* create column */
69   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
70     goto err;
71   dynstr_append(&str, "\1"); str.length--; //check for overflow
72   /* read column */
73   if (mariadb_dyncol_get_num(&str, 1, &res))
74     goto err;
75   rc= (res.type == DYN_COL_UINT) && (res.x.ulong_value == num);
76   num= res.x.ulong_value;
77 err:
78   ok(rc, "%s - %llu", name, num);
79   /* cleanup */
80   mariadb_dyncol_free(&str);
81 }
82 
test_value_single_sint(longlong num,const char * name)83 void test_value_single_sint(longlong num, const char *name)
84 {
85   int rc= FALSE;
86   uint ids[1]= {1};
87   DYNAMIC_COLUMN_VALUE val, res;
88   DYNAMIC_COLUMN str;
89   /* init values */
90   val.type= DYN_COL_INT;
91   val.x.long_value= num;
92   mariadb_dyncol_value_init(&res);
93   /* create column */
94   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
95     goto err;
96   dynstr_append(&str, "\1"); str.length--; //check for overflow
97   /* read column */
98   if (mariadb_dyncol_get_num(&str, 1, &res))
99     goto err;
100   rc= (res.type == DYN_COL_INT) && (res.x.long_value == num);
101   num= res.x.ulong_value;
102 err:
103   ok(rc, "%s - %lld", name, num);
104   /* cleanup */
105   mariadb_dyncol_free(&str);
106 }
107 
108 
test_value_single_double(double num,const char * name)109 void test_value_single_double(double num, const char *name)
110 {
111   int rc= FALSE;
112   uint ids[1]= {1};
113   DYNAMIC_COLUMN_VALUE val, res;
114   DYNAMIC_COLUMN str;
115   /* init values */
116   val.type= DYN_COL_DOUBLE;
117   val.x.double_value= num;
118   mariadb_dyncol_value_init(&res);
119   /* create column */
120   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
121     goto err;
122   dynstr_append(&str, "\1"); str.length--; //check for overflow
123   /* read column */
124   if (mariadb_dyncol_get_num(&str, 1, &res))
125     goto err;
126   rc= (res.type == DYN_COL_DOUBLE) && (res.x.double_value == num);
127   num= res.x.double_value;
128 err:
129   ok(rc, "%s - %lf", name, num);
130   /* cleanup */
131   mariadb_dyncol_free(&str);
132 }
133 
test_value_single_decimal(const char * num)134 void test_value_single_decimal(const char *num)
135 {
136   char *end= (((char*)num) + strlen(num));
137   char buff[80];
138   int rc= FALSE;
139   int length= 80;
140   uint ids[1]= {1};
141   DYNAMIC_COLUMN_VALUE val, res;
142   DYNAMIC_COLUMN str;
143 
144   /* init values */
145   mariadb_dyncol_prepare_decimal(&val); // special procedure for decimal!!!
146   if (string2decimal(num, &val.x.decimal.value, &end) != E_DEC_OK)
147     goto err;
148   mariadb_dyncol_value_init(&res);
149 
150   /* create column */
151   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
152     goto err;
153   dynstr_append(&str, "\1"); str.length--; //check for overflow
154   /* read column */
155   if (mariadb_dyncol_get_num(&str, 1, &res))
156     goto err;
157   rc= ((res.type == DYN_COL_DECIMAL) &&
158        (decimal_cmp(&res.x.decimal.value, &val.x.decimal.value) == 0));
159   decimal2string(&res.x.decimal.value, buff, &length, 0, 0, ' ');
160 err:
161   ok(rc, "%s - %s", num, buff);
162   /* cleanup */
163   mariadb_dyncol_free(&str);
164 }
165 
166 static CHARSET_INFO *charset_list[]=
167 {
168 #ifdef HAVE_CHARSET_big5
169   &my_charset_big5_chinese_ci,
170   &my_charset_big5_bin,
171 #endif
172 #ifdef HAVE_CHARSET_euckr
173   &my_charset_euckr_korean_ci,
174   &my_charset_euckr_bin,
175 #endif
176 #ifdef HAVE_CHARSET_gb2312
177   &my_charset_gb2312_chinese_ci,
178   &my_charset_gb2312_bin,
179 #endif
180 #ifdef HAVE_CHARSET_gbk
181   &my_charset_gbk_chinese_ci,
182   &my_charset_gbk_bin,
183 #endif
184 #ifdef HAVE_CHARSET_latin1
185   &my_charset_latin1,
186   &my_charset_latin1_bin,
187 #endif
188 #ifdef HAVE_CHARSET_sjis
189   &my_charset_sjis_japanese_ci,
190   &my_charset_sjis_bin,
191 #endif
192 #ifdef HAVE_CHARSET_tis620
193   &my_charset_tis620_thai_ci,
194   &my_charset_tis620_bin,
195 #endif
196 #ifdef HAVE_CHARSET_ujis
197   &my_charset_ujis_japanese_ci,
198   &my_charset_ujis_bin,
199 #endif
200 #ifdef HAVE_CHARSET_utf8mb3
201   &my_charset_utf8mb3_general_ci,
202 #ifdef HAVE_UCA_COLLATIONS
203   &my_charset_utf8mb3_unicode_ci,
204 #endif
205   &my_charset_utf8mb3_bin,
206 #endif
207 };
208 
209 
test_value_single_string(const char * string,size_t len,CHARSET_INFO * cs)210 void test_value_single_string(const char *string, size_t len,
211                               CHARSET_INFO *cs)
212 {
213   int rc= FALSE;
214   uint ids[1]= {1};
215   DYNAMIC_COLUMN_VALUE val, res;
216   DYNAMIC_COLUMN str;
217 
218   /* init values */
219   val.type= DYN_COL_STRING;
220   val.x.string.value.str= (char*)string;
221   val.x.string.value.length= len;
222   val.x.string.charset= cs;
223   mariadb_dyncol_value_init(&res);
224 
225   /* create column */
226   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
227     goto err;
228   dynstr_append(&str, "\1"); str.length--; //check for overflow
229   /* read column */
230   if (mariadb_dyncol_get_num(&str, 1, &res))
231     goto err;
232   rc= ((res.type == DYN_COL_STRING) &&
233        (res.x.string.value.length == len) &&
234        (memcmp(res.x.string.value.str, string, len) == 0) &&
235        (res.x.string.charset->number == cs->number));
236 err:
237   ok(rc, "'%s' - '%s' %u %u-%s", string,
238      res.x.string.value.str, (uint)res.x.string.value.length,
239      (uint)res.x.string.charset->number, res.x.string.charset->name);
240   /* cleanup */
241   val.x.string.value.str= NULL; // we did not allocated it
242   mariadb_dyncol_free(&str);
243 }
244 
test_value_single_date(uint year,uint month,uint day,const char * name)245 void test_value_single_date(uint year, uint month, uint day, const char *name)
246 {
247   int rc= FALSE;
248   uint ids[1]= {1};
249   DYNAMIC_COLUMN_VALUE val, res;
250   DYNAMIC_COLUMN str;
251   /* init values */
252   val.type= DYN_COL_DATE;
253   val.x.time_value.time_type= MYSQL_TIMESTAMP_DATE;
254   val.x.time_value.year= year;
255   val.x.time_value.month= month;
256   val.x.time_value.day= day;
257   mariadb_dyncol_value_init(&res);
258   /* create column */
259   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
260     goto err;
261   dynstr_append(&str, "\1"); str.length--; //check for overflow
262   /* read column */
263   if (mariadb_dyncol_get_num(&str, 1, &res))
264     goto err;
265   rc= ((res.type == DYN_COL_DATE) &&
266        (res.x.time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
267        (res.x.time_value.year == year) &&
268        (res.x.time_value.month == month) &&
269        (res.x.time_value.day == day));
270 err:
271   ok(rc, "%s - %04u-%02u-%02u", name, year, month, day);
272   /* cleanup */
273   mariadb_dyncol_free(&str);
274 }
275 
test_value_single_time(uint neg,uint hour,uint minute,uint second,uint mic,const char * name)276 void test_value_single_time(uint neg, uint hour, uint minute, uint second,
277                             uint mic, const char *name)
278 {
279   int rc= FALSE;
280   uint ids[1]= {1};
281   DYNAMIC_COLUMN_VALUE val, res;
282   DYNAMIC_COLUMN str;
283   /* init values */
284   val.type= DYN_COL_TIME;
285   val.x.time_value.time_type= MYSQL_TIMESTAMP_TIME;
286   val.x.time_value.neg= neg;
287   val.x.time_value.hour= hour;
288   val.x.time_value.minute= minute;
289   val.x.time_value.second= second;
290   val.x.time_value.second_part= mic;
291   mariadb_dyncol_value_init(&res);
292   /* create column */
293   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
294     goto err;
295   dynstr_append(&str, "\1"); str.length--; //check for overflow
296   /* read column */
297   if (mariadb_dyncol_get_num(&str, 1, &res))
298     goto err;
299   rc= ((res.type == DYN_COL_TIME) &&
300        (res.x.time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
301        (res.x.time_value.neg == (int)neg) &&
302        (res.x.time_value.hour == hour) &&
303        (res.x.time_value.minute == minute) &&
304        (res.x.time_value.second == second) &&
305        (res.x.time_value.second_part == mic));
306 err:
307   ok(rc, "%s - %c%02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
308      hour, minute, second, mic);
309   /* cleanup */
310   mariadb_dyncol_free(&str);
311 }
312 
313 
test_value_single_datetime(uint neg,uint year,uint month,uint day,uint hour,uint minute,uint second,uint mic,const char * name)314 void test_value_single_datetime(uint neg, uint year, uint month, uint day,
315                                 uint hour, uint minute, uint second,
316                                 uint mic, const char *name)
317 {
318   int rc= FALSE;
319   uint ids[1]= {1};
320   DYNAMIC_COLUMN_VALUE val, res;
321   DYNAMIC_COLUMN str;
322   /* init values */
323   val.type= DYN_COL_DATETIME;
324   val.x.time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
325   val.x.time_value.neg= neg;
326   val.x.time_value.year= year;
327   val.x.time_value.month= month;
328   val.x.time_value.day= day;
329   val.x.time_value.hour= hour;
330   val.x.time_value.minute= minute;
331   val.x.time_value.second= second;
332   val.x.time_value.second_part= mic;
333   mariadb_dyncol_value_init(&res);
334   /* create column */
335   if (mariadb_dyncol_create_many_num(&str, 1, ids, &val, 1))
336     goto err;
337   dynstr_append(&str, "\1"); str.length--; //check for overflow
338   /* read column */
339   if (mariadb_dyncol_get_num(&str, 1, &res))
340     goto err;
341   rc= ((res.type == DYN_COL_DATETIME) &&
342        (res.x.time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
343        (res.x.time_value.neg == (int)neg) &&
344        (res.x.time_value.year == year) &&
345        (res.x.time_value.month == month) &&
346        (res.x.time_value.day == day) &&
347        (res.x.time_value.hour == hour) &&
348        (res.x.time_value.minute == minute) &&
349        (res.x.time_value.second == second) &&
350        (res.x.time_value.second_part == mic));
351 err:
352   ok(rc, "%s - %c %04u-%02u-%02u %02u:%02u:%02u.%06u", name, (neg ? '-' : '+'),
353      year, month, day, hour, minute, second, mic);
354   /* cleanup */
355   mariadb_dyncol_free(&str);
356 }
357 
358 
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)359 void test_value_multi(ulonglong num0,
360                       longlong num1,
361                       double num2,
362                       const char *num3,
363                       const char *string4, size_t len4, CHARSET_INFO *cs4,
364                       uint year5, uint month5, uint day5,
365                       uint neg6, uint hour6, uint minute6,
366                       uint second6, uint mic6,
367                       uint neg7, uint year7, uint month7, uint day7,
368                       uint hour7, uint minute7, uint second7,
369                       uint mic7,
370                       uint *column_numbers,
371                       const char *name)
372 {
373   char *end3= (((char*)num3) + strlen(num3));
374   int rc= FALSE;
375   uint i;
376   DYNAMIC_COLUMN_VALUE val[9], res[9];
377   DYNAMIC_COLUMN str;
378   /* init values */
379   val[0].type= DYN_COL_UINT;
380   val[0].x.ulong_value= num0;
381   val[1].type= DYN_COL_INT;
382   val[1].x.long_value= num1;
383   val[2].type= DYN_COL_DOUBLE;
384   val[2].x.double_value= num2;
385   mariadb_dyncol_prepare_decimal(val + 3); // special procedure for decimal!!!
386   if (string2decimal(num3, &val[3].x.decimal.value, &end3) != E_DEC_OK)
387     goto err;
388   val[4].type= DYN_COL_STRING;
389   val[4].x.string.value.str= (char*)string4;
390   val[4].x.string.value.length= len4;
391   val[4].x.string.charset= cs4;
392   val[5].type= DYN_COL_DATE;
393   val[5].x.time_value.time_type= MYSQL_TIMESTAMP_DATE;
394   val[5].x.time_value.year= year5;
395   val[5].x.time_value.month= month5;
396   val[5].x.time_value.day= day5;
397   val[6].type= DYN_COL_TIME;
398   val[6].x.time_value.time_type= MYSQL_TIMESTAMP_TIME;
399   val[6].x.time_value.neg= neg6;
400   val[6].x.time_value.hour= hour6;
401   val[6].x.time_value.minute= minute6;
402   val[6].x.time_value.second= second6;
403   val[6].x.time_value.second_part= mic6;
404   val[7].type= DYN_COL_DATETIME;
405   val[7].x.time_value.time_type= MYSQL_TIMESTAMP_DATETIME;
406   val[7].x.time_value.neg= neg7;
407   val[7].x.time_value.year= year7;
408   val[7].x.time_value.month= month7;
409   val[7].x.time_value.day= day7;
410   val[7].x.time_value.hour= hour7;
411   val[7].x.time_value.minute= minute7;
412   val[7].x.time_value.second= second7;
413   val[7].x.time_value.second_part= mic7;
414   val[8].type= DYN_COL_NULL;
415   for (i= 0; i < 9; i++)
416     mariadb_dyncol_value_init(res + i);
417   /* create column */
418   if (mariadb_dyncol_create_many_num(&str, 9, column_numbers, val, 1))
419     goto err;
420   dynstr_append(&str, "\1"); str.length--; //check for overflow
421   /* read column */
422   for (i= 0; i < 9; i++)
423     if (mariadb_dyncol_get_num(&str, column_numbers[i], res + i))
424       goto err;
425   rc= ((res[0].type == DYN_COL_UINT) &&
426        (res[0].x.ulong_value == num0) &&
427        (res[1].type == DYN_COL_INT) &&
428        (res[1].x.long_value == num1) &&
429        (res[2].type == DYN_COL_DOUBLE) &&
430        (res[2].x.double_value == num2) &&
431        (res[3].type == DYN_COL_DECIMAL) &&
432        (decimal_cmp(&res[3].x.decimal.value, &val[3].x.decimal.value) == 0) &&
433        (res[4].type == DYN_COL_STRING) &&
434        (res[4].x.string.value.length == len4) &&
435        (memcmp(res[4].x.string.value.str, string4, len4) == 0) &&
436        (res[4].x.string.charset->number == cs4->number) &&
437        (res[5].type == DYN_COL_DATE) &&
438        (res[5].x.time_value.time_type == MYSQL_TIMESTAMP_DATE) &&
439        (res[5].x.time_value.year == year5) &&
440        (res[5].x.time_value.month == month5) &&
441        (res[5].x.time_value.day == day5) &&
442        (res[6].type == DYN_COL_TIME) &&
443        (res[6].x.time_value.time_type == MYSQL_TIMESTAMP_TIME) &&
444        (res[6].x.time_value.neg == (int)neg6) &&
445        (res[6].x.time_value.hour == hour6) &&
446        (res[6].x.time_value.minute == minute6) &&
447        (res[6].x.time_value.second == second6) &&
448        (res[6].x.time_value.second_part == mic6) &&
449        (res[7].type == DYN_COL_DATETIME) &&
450        (res[7].x.time_value.time_type == MYSQL_TIMESTAMP_DATETIME) &&
451        (res[7].x.time_value.neg == (int)neg7) &&
452        (res[7].x.time_value.year == year7) &&
453        (res[7].x.time_value.month == month7) &&
454        (res[7].x.time_value.day == day7) &&
455        (res[7].x.time_value.hour == hour7) &&
456        (res[7].x.time_value.minute == minute7) &&
457        (res[7].x.time_value.second == second7) &&
458        (res[7].x.time_value.second_part == mic7) &&
459        (res[8].type == DYN_COL_NULL));
460 err:
461   ok(rc, "%s", name);
462   /* cleanup */
463   val[4].x.string.value.str= NULL; // we did not allocated it
464   mariadb_dyncol_free(&str);
465 }
466 
467 
test_value_multi_same_num()468 void test_value_multi_same_num()
469 {
470   int rc= FALSE;
471   uint i;
472   DYNAMIC_COLUMN_VALUE val[5];
473   uint column_numbers[]= {3,4,5,3,6}; // same column numbers
474   DYNAMIC_COLUMN str;
475   /* init values */
476   for (i= 0; i < 5; i++)
477     val[i].type= DYN_COL_NULL;
478   /* create column */
479   if (!mariadb_dyncol_create_many_num(&str, 5, column_numbers, val, 1))
480     goto err;
481   rc= TRUE;
482 err:
483   ok(rc, "%s", "same column numbers check");
484   /* cleanup */
485   mariadb_dyncol_free(&str);
486 }
487 
488 
test_update_multi(uint * column_numbers,uint * column_values,my_bool * null_values,int only_add,int all)489 void test_update_multi(uint *column_numbers, uint *column_values,
490                        my_bool *null_values, int only_add, int all)
491 {
492   int rc= FALSE;
493   int i, j;
494   DYNAMIC_COLUMN str;
495   DYNAMIC_COLUMN_VALUE val;
496 
497   val.type= DYN_COL_UINT;
498   val.x.ulong_value= column_values[0];
499   if (mariadb_dyncol_create_many_num(&str, 1, column_numbers, &val, 1))
500     goto err;
501   for (i= 1; i < all; i++)
502   {
503     val.type= (null_values[i] ? DYN_COL_NULL : DYN_COL_UINT);
504     val.x.ulong_value= column_values[i];
505     if (mariadb_dyncol_update_many_num(&str, 1, column_numbers +i, &val))
506       goto err;
507 
508     /* check value(s) */
509     for (j= i; j >= (i < only_add ? 0 : i); j--)
510     {
511       if (mariadb_dyncol_get_num(&str, column_numbers[j], &val))
512         goto err;
513       if (null_values[j])
514       {
515         if (val.type != DYN_COL_NULL ||
516             mariadb_dyncol_exists_num(&str, column_numbers[j]) == ER_DYNCOL_YES)
517           goto err;
518       }
519       else
520       {
521         if (val.type != DYN_COL_UINT ||
522             val.x.ulong_value != column_values[j] ||
523             mariadb_dyncol_exists_num(&str, column_numbers[j]) == ER_DYNCOL_NO)
524           goto err;
525       }
526     }
527     if (i < only_add)
528     {
529       uint elements, *num;
530       if (mariadb_dyncol_list_num(&str, &elements, &num))
531       {
532         my_free(num);
533         goto err;
534       }
535       /* cross check arrays */
536       if ((int)elements != i + 1)
537       {
538         my_free(num);
539         goto err;
540       }
541       for(j= 0; j < i + 1; j++)
542       {
543         int k;
544         for(k= 0;
545             k < i + 1 && column_numbers[j] != num[k];
546             k++);
547         if (k >= i + 1)
548         {
549           my_free(num);
550           goto err;
551         }
552         for(k= 0;
553             k < i + 1 && column_numbers[k] != num[j];
554             k++);
555         if (k >= i + 1)
556         {
557           my_free(num);
558           goto err;
559         }
560       }
561       my_free(num);
562     }
563   }
564 
565   rc= TRUE;
566 err:
567   ok(rc, "%s", "add/delete/update");
568   /* cleanup */
569   mariadb_dyncol_free(&str);
570 }
571 
test_empty_string()572 void test_empty_string()
573 {
574   DYNAMIC_COLUMN_VALUE val, res;
575   DYNAMIC_COLUMN str;
576   uint *array_of_uint;
577   uint number_of_uint;
578   int rc;
579   uint ids[1]= {1};
580   DYNAMIC_COLUMN_VALUE vals[1];
581   /* empty string */
582   bzero(&str, sizeof(str));
583 
584   rc= mariadb_dyncol_get_num(&str, 1, &res);
585   ok( (rc == ER_DYNCOL_OK) && (res.type == DYN_COL_NULL), "%s", "empty get");
586 
587   vals[0].type= DYN_COL_NULL;
588   rc= mariadb_dyncol_update_many_num(&str, 1, ids, vals);
589   ok( (rc == ER_DYNCOL_OK) && (str.str == 0), "%s", "empty delete");
590 
591   rc= mariadb_dyncol_exists_num(&str, 1);
592   ok( (rc == ER_DYNCOL_NO), "%s", "empty exists");
593 
594   rc= mariadb_dyncol_list_num(&str, &number_of_uint, &array_of_uint);
595   ok( (rc == ER_DYNCOL_OK) && (number_of_uint == 0) && (str.str == 0),
596       "%s", "empty list");
597 
598   val.type= DYN_COL_UINT;
599   val.x.ulong_value= 1212;
600   rc= mariadb_dyncol_update_many_num(&str, 1, ids, &val);
601   if (rc == ER_DYNCOL_OK)
602     rc= mariadb_dyncol_get_num(&str, 1, &res);
603   ok( (rc == ER_DYNCOL_OK) && (str.str != 0) &&
604       (res.type == DYN_COL_UINT) && (res.x.ulong_value == val.x.ulong_value),
605       "%s", "empty update");
606   mariadb_dyncol_free(&str);
607 }
608 
test_mdev_4994()609 static void test_mdev_4994()
610 {
611   DYNAMIC_COLUMN dyncol;
612   LEX_STRING key= {0,0};
613   DYNAMIC_COLUMN_VALUE val;
614   int rc;
615 
616   val.type= DYN_COL_NULL;
617 
618   mariadb_dyncol_init(&dyncol);
619   rc= mariadb_dyncol_create_many_named(&dyncol, 1, &key, &val, 0);  /* crash */
620   ok( (rc == ER_DYNCOL_OK), "%s", "test_mdev_4994");
621   mariadb_dyncol_free(&dyncol);
622 }
623 
test_mdev_4995()624 static void test_mdev_4995()
625 {
626   DYNAMIC_COLUMN dyncol;
627   uint column_count= 5;
628   int rc;
629 
630   mariadb_dyncol_init(&dyncol);
631   rc= mariadb_dyncol_column_count(&dyncol,&column_count);
632 
633   ok( (rc == ER_DYNCOL_OK), "%s", "test_mdev_4995");
634 }
635 
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)636 void test_update_many(uint *column_numbers, uint *column_values,
637                       uint column_count,
638                       uint *update_numbers, uint *update_values,
639                       my_bool *update_nulls, uint update_count,
640                       uint *result_numbers, uint *result_values,
641                       uint result_count)
642 {
643   int rc= FALSE;
644   uint i;
645   DYNAMIC_COLUMN str1;
646   DYNAMIC_COLUMN str2;
647   DYNAMIC_COLUMN_VALUE *val, *upd, *res;
648 
649   val= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
650                                       column_count);
651   upd= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
652                                       update_count);
653   res= (DYNAMIC_COLUMN_VALUE *)malloc(sizeof(DYNAMIC_COLUMN_VALUE) *
654                                       result_count);
655 
656 
657   for (i= 0; i < column_count; i++)
658   {
659     val[i].type= DYN_COL_UINT;
660     val[i].x.ulong_value= column_values[i];
661   }
662   for (i= 0; i < update_count; i++)
663   {
664     if (update_nulls[i])
665       upd[i].type= DYN_COL_NULL;
666     else
667     {
668       upd[i].type= DYN_COL_UINT;
669       upd[i].x.ulong_value= update_values[i];
670     }
671   }
672   for (i= 0; i < result_count; i++)
673   {
674     res[i].type= DYN_COL_UINT;
675     res[i].x.ulong_value= result_values[i];
676   }
677   if (mariadb_dyncol_create_many_num(&str1, column_count, column_numbers, val, 1))
678     goto err;
679   if (mariadb_dyncol_update_many_num(&str1, update_count, update_numbers, upd))
680     goto err;
681   if (mariadb_dyncol_create_many_num(&str2, result_count, result_numbers, res, 1))
682     goto err;
683   if (str1.length == str2.length &&
684       memcmp(str1.str, str2.str, str1.length) ==0)
685     rc= TRUE;
686 
687 err:
688   ok(rc, "%s", "update_many");
689   /* cleanup */
690   free(val);
691   free(upd);
692   free(res);
693   mariadb_dyncol_free(&str1);
694   mariadb_dyncol_free(&str2);
695 }
696 
test_mdev_9773()697 static void test_mdev_9773()
698 {
699   int rc;
700   uint i;
701   uint num_keys[5]= {1,2,3,4,5};
702   char const *strval[]= {"Val1", "Val2", "Val3", "Val4", "Val5"};
703   DYNAMIC_COLUMN_VALUE vals[5];
704   DYNAMIC_COLUMN dynstr;
705   uint unpack_columns= 0;
706   MYSQL_LEX_STRING *unpack_keys= 0;
707   DYNAMIC_COLUMN_VALUE *unpack_vals= 0;
708 
709   for (i = 0; i < 5; i++)
710   {
711     vals[i].type= DYN_COL_STRING;
712     vals[i].x.string.value.str= (char *)strval[i];
713     vals[i].x.string.value.length= strlen(strval[i]);
714     vals[i].x.string.charset= &my_charset_latin1;
715   }
716 
717   mariadb_dyncol_init(&dynstr);
718 
719   /* create numeric */
720   rc= mariadb_dyncol_create_many_num(&dynstr, 5, num_keys, vals, 1);
721 
722   if (rc == ER_DYNCOL_OK)
723     rc= mariadb_dyncol_unpack(&dynstr, &unpack_columns, &unpack_keys,
724                               &unpack_vals);
725   ok (rc == ER_DYNCOL_OK && unpack_columns == 5, "5 fields unpacked");
726   for (i = 0; i < unpack_columns; i++)
727   {
728     ok(memcmp(unpack_vals[i].x.string.value.str,
729                vals[i].x.string.value.str, vals[i].x.string.value.length) == 0,
730        "unpack %u", i);
731   }
732 
733   my_free(unpack_keys);
734   my_free(unpack_vals);
735   mariadb_dyncol_free(&dynstr);
736 }
737 
main(int argc,char ** argv)738 int main(int argc __attribute__((unused)), char **argv)
739 {
740   uint i;
741   char *big_string= (char *)malloc(1024*1024);
742 
743   MY_INIT(argv[0]);
744   plan(68);
745 
746   if (!big_string)
747     exit(1);
748   for (i= 0; i < 1024*1024; i++)
749     big_string[i]= ('0' + (i % 10));
750   test_value_single_null();
751   test_value_single_uint(0, "0");
752   test_value_single_uint(0xffffffffffffffffULL, "0xffffffffffffffff");
753   test_value_single_uint(0xaaaaaaaaaaaaaaaaULL, "0xaaaaaaaaaaaaaaaa");
754   test_value_single_uint(0x5555555555555555ULL, "0x5555555555555555");
755   test_value_single_uint(27652, "27652");
756   test_value_single_sint(0, "0");
757   test_value_single_sint(1, "1");
758   test_value_single_sint(-1, "-1");
759   test_value_single_sint(0x7fffffffffffffffLL, "0x7fffffffffffffff");
760   test_value_single_sint(0xaaaaaaaaaaaaaaaaLL, "0xaaaaaaaaaaaaaaaa");
761   test_value_single_sint(0x5555555555555555LL, "0x5555555555555555");
762   test_value_single_sint(0x8000000000000000LL, "0x8000000000000000");
763   test_value_single_double(0.0, "0.0");
764   test_value_single_double(1.0, "1.0");
765   test_value_single_double(-1.0, "-1.0");
766   test_value_single_double(1.0e100, "1.0e100");
767   test_value_single_double(1.0e-100, "1.0e-100");
768   test_value_single_double(9999999999999999999999999999999999999.0,
769                            "9999999999999999999999999999999999999.0");
770   test_value_single_double(-9999999999999999999999999999999999999.0,
771                            "-9999999999999999999999999999999999999.0");
772   test_value_single_decimal("0");
773   test_value_single_decimal("1");
774   test_value_single_decimal("-1");
775   test_value_single_decimal("9999999999999999999999999999999");
776   test_value_single_decimal("-9999999999999999999999999999999");
777   test_value_single_decimal("0.9999999999999999999999999999999");
778   test_value_single_decimal("-0.9999999999999999999999999999999");
779   test_value_single_string("", 0, charset_list[0]);
780   test_value_single_string("", 1, charset_list[0]);
781   test_value_single_string("1234567890", 11, charset_list[0]);
782   test_value_single_string("nulls\0\0\0\0\0", 10, charset_list[0]);
783   sprintf(big_string, "%x", 0x7a);
784   test_value_single_string(big_string, 0x7a, charset_list[0]);
785   sprintf(big_string, "%x", 0x80);
786   test_value_single_string(big_string, 0x80, charset_list[0]);
787   sprintf(big_string, "%x", 0x7ffa);
788   test_value_single_string(big_string, 0x7ffa, charset_list[0]);
789   sprintf(big_string, "%x", 0x8000);
790   test_value_single_string(big_string, 0x8000, charset_list[0]);
791   sprintf(big_string, "%x", 1024*1024);
792   test_value_single_string(big_string, 1024*1024, charset_list[0]);
793   test_value_single_date(0, 0, 0, "zero date");
794   test_value_single_date(9999, 12, 31, "max date");
795   test_value_single_date(2011, 3, 26, "some date");
796   test_value_single_time(0, 0, 0, 0, 0, "zero time");
797   test_value_single_time(1, 23, 59, 59, 999999, "min time");
798   test_value_single_time(0, 23, 59, 59, 999999, "max time");
799   test_value_single_time(0, 21, 36, 20, 28, "some time");
800   test_value_single_datetime(0, 0, 0, 0, 0, 0, 0, 0, "zero datetime");
801   test_value_single_datetime(1, 9999, 12, 31, 23, 59, 59, 999999,
802                              "min datetime");
803   test_value_single_datetime(0, 9999, 12, 31, 23, 59, 59, 999999,
804                              "max datetime");
805   test_value_single_datetime(0, 2011, 3, 26, 21, 53, 12, 3445,
806                              "some datetime");
807   {
808     uint column_numbers[]= {100,1,2,3,4,5,6,7,8};
809     test_value_multi(0, 0, 0.0, "0",
810                      "", 0, charset_list[0],
811                      0, 0, 0,
812                      0, 0, 0, 0, 0,
813                      0, 0, 0, 0, 0, 0, 0, 0,
814                      column_numbers,
815                      "zero data");
816   }
817   {
818     uint column_numbers[]= {10,1,12,37,4,57,6,76,87};
819     test_value_multi(0xffffffffffffffffULL, 0x7fffffffffffffffLL,
820                      99999999.999e120, "9999999999999999999999999999999",
821                      big_string, 1024*1024, charset_list[0],
822                      9999, 12, 31,
823                      0, 23, 59, 59, 999999,
824                      0, 9999, 12, 31, 23, 59, 59, 999999,
825                      column_numbers,
826                      "much data");
827   }
828   free(big_string);
829   {
830     uint column_numbers[]= {101,12,122,37,24,572,16,726,77};
831     test_value_multi(37878, -3344,
832                      2873.3874, "92743.238984789898",
833                      "string", 6, charset_list[0],
834                      2011, 3, 26,
835                      1, 23, 23, 20, 333,
836                      0, 2011, 3, 26, 23, 23, 53, 334,
837                      column_numbers,
838                      "zero data");
839   }
840   test_value_multi_same_num();
841   {
842     uint column_numbers[]= {1,2,3,4,5,6,7,2, 3, 4};
843     uint column_values[]=  {1,2,3,4,5,6,7,0,30,40};
844     my_bool null_values[]= {0,0,0,0,0,0,0,1, 0, 0};
845 
846     test_update_multi(column_numbers, column_values, null_values, 7, 10);
847   }
848   {
849     uint column_numbers[]= {4,3,2,1, 1,2,3,4};
850     uint column_values[]=  {4,3,2,1, 0,0,0,0};
851     my_bool null_values[]= {0,0,0,0, 1,1,1,1};
852 
853     test_update_multi(column_numbers, column_values, null_values, 4, 8);
854   }
855   {
856     uint column_numbers[]= {4,3,2,1, 4,3,2,1};
857     uint column_values[]=  {4,3,2,1, 0,0,0,0};
858     my_bool null_values[]= {0,0,0,0, 1,1,1,1};
859 
860     test_update_multi(column_numbers, column_values, null_values, 4, 8);
861   }
862   test_empty_string();
863   {
864     uint column_numbers[]= {1, 2, 3};
865     uint column_values[]=  {1, 2, 3};
866     uint update_numbers[]= {4, 3, 2, 1};
867     uint update_values[]=  {40,30, 0,10};
868     my_bool update_nulls[]={0, 0, 1, 0};
869     uint result_numbers[]= {1, 3, 4};
870     uint result_values[]=  {10,30,40};
871     test_update_many(column_numbers, column_values, 3,
872                      update_numbers, update_values, update_nulls, 4,
873                      result_numbers, result_values, 3);
874   }
875   test_mdev_4994();
876   test_mdev_4995();
877   test_mdev_9773();
878 
879   my_end(0);
880   return exit_status();
881 }
882