1 /*
2 Copyright (c) 2000, 2013, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
16
17
18 /* Analyse database */
19
20 /* TODO: - Check if any character fields can be of any date type
21 ** (date, datetime, year, time, timestamp, newdate)
22 ** - Check if any number field should be a timestamp
23 ** - type set is out of optimization yet
24 */
25
26 #ifdef USE_PRAGMA_IMPLEMENTATION
27 #pragma implementation // gcc: Class implementation
28 #endif
29
30 #define MYSQL_LEX 1
31
32 #include "mariadb.h"
33 #include "sql_priv.h"
34 #include "procedure.h"
35 #include "sql_analyse.h"
36 #include <m_ctype.h>
37
38 #define MAX_TREEMEM 8192
39 #define MAX_TREE_ELEMENTS 256
40
sortcmp2(void * cmp_arg,const String * a,const String * b)41 int sortcmp2(void* cmp_arg __attribute__((unused)),
42 const String *a,const String *b)
43 {
44 return sortcmp(a,b,a->charset());
45 }
46
compare_double2(void * cmp_arg,const double * s,const double * t)47 int compare_double2(void* cmp_arg __attribute__((unused)),
48 const double *s, const double *t)
49 {
50 return compare_double(s,t);
51 }
52
compare_longlong2(void * cmp_arg,const longlong * s,const longlong * t)53 int compare_longlong2(void* cmp_arg __attribute__((unused)),
54 const longlong *s, const longlong *t)
55 {
56 return compare_longlong(s,t);
57 }
58
compare_ulonglong2(void * cmp_arg,const ulonglong * s,const ulonglong * t)59 int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
60 const ulonglong *s, const ulonglong *t)
61 {
62 return compare_ulonglong(s,t);
63 }
64
compare_decimal2(int * len,const char * s,const char * t)65 int compare_decimal2(int* len, const char *s, const char *t)
66 {
67 return memcmp(s, t, *len);
68 }
69
70
71 static bool
prepare_param(THD * thd,Item ** item,const char * proc_name,uint pos)72 prepare_param(THD *thd, Item **item, const char *proc_name, uint pos)
73 {
74 if ((*item)->fix_fields_if_needed(thd, item))
75 {
76 DBUG_PRINT("info", ("fix_fields() for the parameter %u failed", pos));
77 return true;
78 }
79 if ((*item)->type_handler()->result_type() != INT_RESULT ||
80 !(*item)->basic_const_item() ||
81 (*item)->val_real() < 0)
82 {
83 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
84 return true;
85 }
86 return false;
87 }
88
89
90 Procedure *
proc_analyse_init(THD * thd,ORDER * param,select_result * result,List<Item> & field_list)91 proc_analyse_init(THD *thd, ORDER *param, select_result *result,
92 List<Item> &field_list)
93 {
94 const char *proc_name = (*param->item)->name.str;
95 analyse *pc = new analyse(result);
96 field_info **f_info;
97 DBUG_ENTER("proc_analyse_init");
98
99 if (!pc)
100 DBUG_RETURN(0);
101
102 if (!(param = param->next))
103 {
104 pc->max_tree_elements = MAX_TREE_ELEMENTS;
105 pc->max_treemem = MAX_TREEMEM;
106 }
107 else if (param->next)
108 {
109 // first parameter
110 if (prepare_param(thd, param->item, proc_name, 0))
111 goto err;
112 pc->max_tree_elements = (uint) (*param->item)->val_int();
113 param = param->next;
114 if (param->next) // no third parameter possible
115 {
116 my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE, MYF(0), proc_name);
117 goto err;
118 }
119 // second parameter
120 if (prepare_param(thd, param->item, proc_name, 1))
121 goto err;
122 pc->max_treemem = (uint) (*param->item)->val_int();
123 }
124 else if (prepare_param(thd, param->item, proc_name, 0))
125 goto err;
126 // if only one parameter was given, it will be the value of max_tree_elements
127 else
128 {
129 pc->max_tree_elements = (uint) (*param->item)->val_int();
130 pc->max_treemem = MAX_TREEMEM;
131 }
132
133 if (!(pc->f_info=
134 (field_info**) thd->alloc(sizeof(field_info*) * field_list.elements)))
135 goto err;
136 pc->f_end = pc->f_info + field_list.elements;
137 pc->fields = field_list;
138
139 {
140 List_iterator_fast<Item> it(pc->fields);
141 f_info = pc->f_info;
142
143 Item *item;
144 while ((item = it++))
145 {
146 field_info *new_field;
147 switch (item->result_type()) {
148 case INT_RESULT:
149 // Check if fieldtype is ulonglong
150 if (item->type() == Item::FIELD_ITEM &&
151 ((Item_field*) item)->field->type() == MYSQL_TYPE_LONGLONG &&
152 ((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag)
153 new_field= new field_ulonglong(item, pc);
154 else
155 new_field= new field_longlong(item, pc);
156 break;
157 case REAL_RESULT:
158 new_field= new field_real(item, pc);
159 break;
160 case DECIMAL_RESULT:
161 new_field= new field_decimal(item, pc);
162 break;
163 case STRING_RESULT:
164 new_field= new field_str(item, pc);
165 break;
166 default:
167 goto err;
168 }
169 *f_info++= new_field;
170 }
171 }
172 DBUG_RETURN(pc);
173 err:
174 delete pc;
175 DBUG_RETURN(0);
176 }
177
178
179 /*
180 Return 1 if number, else return 0
181 store info about found number in info
182 NOTE:It is expected, that elements of 'info' are all zero!
183 */
184
test_if_number(NUM_INFO * info,const char * str,uint str_len)185 bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
186 {
187 const char *begin, *end= str + str_len;
188 DBUG_ENTER("test_if_number");
189
190 /*
191 MySQL removes any endspaces of a string, so we must take care only of
192 spaces in front of a string
193 */
194 for (; str != end && my_isspace(system_charset_info, *str); str++) ;
195 if (str == end)
196 DBUG_RETURN(0);
197
198 if (*str == '-')
199 {
200 info->negative = 1;
201 if (++str == end || *str == '0') // converting -0 to a number
202 DBUG_RETURN(0); // might lose information
203 }
204 else
205 info->negative = 0;
206 begin = str;
207 for (; str != end && my_isdigit(system_charset_info,*str); str++)
208 {
209 if (!info->integers && *str == '0' && (str + 1) != end &&
210 my_isdigit(system_charset_info,*(str + 1)))
211 info->zerofill = 1; // could be a postnumber for example
212 info->integers++;
213 }
214 if (str == end && info->integers)
215 {
216 char *endpos= (char*) end;
217 int error;
218 info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error);
219 if (info->integers == 1)
220 DBUG_RETURN(0); // single number can't be zerofill
221 info->maybe_zerofill = 1;
222 DBUG_RETURN(1); // a zerofill number, or an integer
223 }
224 if (*str == '.' || *str == 'e' || *str == 'E')
225 {
226 if (info->zerofill) // can't be zerofill anymore
227 DBUG_RETURN(0);
228 if ((str + 1) == end) // number was something like '123[.eE]'
229 {
230 char *endpos= (char*) str;
231 int error;
232 info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error);
233 DBUG_RETURN(1);
234 }
235 if (*str == 'e' || *str == 'E') // number may be something like '1e+50'
236 {
237 str++;
238 if (*str != '-' && *str != '+')
239 DBUG_RETURN(0);
240 for (str++; str != end && my_isdigit(system_charset_info,*str); str++) ;
241 if (str == end)
242 {
243 info->is_float = 1; // we can't use variable decimals here
244 DBUG_RETURN(1);
245 }
246 DBUG_RETURN(0);
247 }
248 for (str++; *(end - 1) == '0'; end--) // jump over zeros at the end
249 ;
250 if (str == end) // number was something like '123.000'
251 {
252 char *endpos= (char*) str;
253 int error;
254 info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error);
255 DBUG_RETURN(1);
256 }
257 for (; str != end && my_isdigit(system_charset_info,*str); str++)
258 info->decimals++;
259 if (str == end)
260 {
261 info->dval = my_atof(begin);
262 DBUG_RETURN(1);
263 }
264 }
265 DBUG_RETURN(0);
266 }
267
268
269 /*
270 Stores the biggest and the smallest value from current 'info'
271 to ev_num_info
272 If info contains an ulonglong number, which is bigger than
273 biggest positive number able to be stored in a longlong variable
274 and is marked as negative, function will return 0, else 1.
275 */
276
get_ev_num_info(EV_NUM_INFO * ev_info,NUM_INFO * info,const char * num)277 bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num)
278 {
279 if (info->negative)
280 {
281 if (((longlong) info->ullval) < 0)
282 return 0; // Impossible to store as a negative number
283 ev_info->llval = -(longlong) MY_MAX((ulonglong) -ev_info->llval,
284 info->ullval);
285 ev_info->min_dval = (double) -MY_MAX(-ev_info->min_dval, info->dval);
286 }
287 else // ulonglong is as big as bigint in MySQL
288 {
289 if ((check_ulonglong(num, info->integers) == DECIMAL_NUM))
290 return 0;
291 ev_info->ullval = (ulonglong) MY_MAX(ev_info->ullval, info->ullval);
292 ev_info->max_dval = (double) MY_MAX(ev_info->max_dval, info->dval);
293 }
294 return 1;
295 } // get_ev_num_info
296
297
free_string(void * str,TREE_FREE,void *)298 int free_string(void* str, TREE_FREE, void*)
299 {
300 ((String*)str)->free();
301 return 0;
302 }
303
304
add()305 void field_str::add()
306 {
307 char buff[MAX_FIELD_WIDTH], *ptr;
308 String s(buff, sizeof(buff),&my_charset_bin), *res;
309 ulong length;
310
311 if (!(res = item->val_str(&s)))
312 {
313 nulls++;
314 return;
315 }
316
317 if (!(length = res->length()))
318 empty++;
319 else
320 {
321 ptr = (char*) res->ptr();
322 if (*(ptr + (length - 1)) == ' ')
323 must_be_blob = 1;
324 }
325
326 if (can_be_still_num)
327 {
328 bzero((char*) &num_info, sizeof(num_info));
329 if (!test_if_number(&num_info, res->ptr(), (uint) length))
330 can_be_still_num = 0;
331 if (!found)
332 {
333 bzero((char*) &ev_num_info, sizeof(ev_num_info));
334 was_zero_fill = num_info.zerofill;
335 }
336 else if (num_info.zerofill != was_zero_fill && !was_maybe_zerofill)
337 can_be_still_num = 0; // one more check needed, when length is counted
338 if (can_be_still_num)
339 can_be_still_num = get_ev_num_info(&ev_num_info, &num_info, res->ptr());
340 was_maybe_zerofill = num_info.maybe_zerofill;
341 }
342
343 /* Update min and max arguments */
344 if (!found)
345 {
346 found = 1;
347 min_arg.copy(*res);
348 max_arg.copy(*res);
349 min_length = max_length = length; sum=length;
350 }
351 else if (length)
352 {
353 sum += length;
354 if (length < min_length)
355 min_length = length;
356 if (length > max_length)
357 max_length = length;
358
359 if (sortcmp(res, &min_arg,item->collation.collation) < 0)
360 min_arg.copy(*res);
361 if (sortcmp(res, &max_arg,item->collation.collation) > 0)
362 max_arg.copy(*res);
363 }
364
365 if (room_in_tree)
366 {
367 if (res != &s)
368 s.copy(*res);
369 if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
370 {
371 s.copy(); // slow, when SAFE_MALLOC is in use
372 if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
373 {
374 room_in_tree = 0; // Remove tree, out of RAM ?
375 delete_tree(&tree, 0);
376 }
377 else
378 {
379 bzero((char*) &s, sizeof(s)); // Let tree handle free of this
380 if ((treemem += length) > pc->max_treemem)
381 {
382 room_in_tree = 0; // Remove tree, too big tree
383 delete_tree(&tree, 0);
384 }
385 }
386 }
387 }
388
389 if ((num_info.zerofill && (max_length != min_length)) ||
390 (was_zero_fill && (max_length != min_length)))
391 can_be_still_num = 0; // zerofilled numbers must be of same length
392 } // field_str::add
393
394
add()395 void field_real::add()
396 {
397 char buff[MAX_FIELD_WIDTH], *ptr, *end;
398 double num= item->val_real();
399 uint length, zero_count, decs;
400 TREE_ELEMENT *element;
401
402 if (item->null_value)
403 {
404 nulls++;
405 return;
406 }
407 if (num == 0.0)
408 empty++;
409
410 if ((decs = decimals()) >= FLOATING_POINT_DECIMALS)
411 {
412 length= sprintf(buff, "%g", num);
413 if (rint(num) != num)
414 max_notzero_dec_len = 1;
415 }
416 else
417 {
418 #ifdef HAVE_SNPRINTF
419 buff[sizeof(buff)-1]=0; // Safety
420 snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num);
421 length = (uint) strlen(buff);
422 #else
423 length= sprintf(buff, "%-.*f", (int) decs, num);
424 #endif
425
426 // We never need to check further than this
427 end = buff + length - 1 - decs + max_notzero_dec_len;
428
429 zero_count = 0;
430 for (ptr = buff + length - 1; ptr > end && *ptr == '0'; ptr--)
431 zero_count++;
432
433 if ((decs - zero_count > max_notzero_dec_len))
434 max_notzero_dec_len = decs - zero_count;
435 }
436
437 if (room_in_tree)
438 {
439 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
440 {
441 room_in_tree = 0; // Remove tree, out of RAM ?
442 delete_tree(&tree, 0);
443 }
444 /*
445 if element->count == 1, this element can be found only once from tree
446 if element->count == 2, or more, this element is already in tree
447 */
448 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
449 {
450 room_in_tree = 0; // Remove tree, too many elements
451 delete_tree(&tree, 0);
452 }
453 }
454
455 if (!found)
456 {
457 found = 1;
458 min_arg = max_arg = sum = num;
459 sum_sqr = num * num;
460 min_length = max_length = length;
461 }
462 else if (num != 0.0)
463 {
464 sum += num;
465 sum_sqr += num * num;
466 if (length < min_length)
467 min_length = length;
468 if (length > max_length)
469 max_length = length;
470 if (compare_double(&num, &min_arg) < 0)
471 min_arg = num;
472 if (compare_double(&num, &max_arg) > 0)
473 max_arg = num;
474 }
475 } // field_real::add
476
477
add()478 void field_decimal::add()
479 {
480 /*TODO - remove rounding stuff after decimal_div returns proper frac */
481 VDec vdec(item);
482 uint length;
483 TREE_ELEMENT *element;
484
485 if (vdec.is_null())
486 {
487 nulls++;
488 return;
489 }
490
491 my_decimal dec;
492 vdec.round_to(&dec, item->decimals, HALF_UP);
493
494 length= my_decimal_string_length(&dec);
495
496 if (decimal_is_zero(&dec))
497 empty++;
498
499 if (room_in_tree)
500 {
501 uchar buf[DECIMAL_MAX_FIELD_SIZE];
502 dec.to_binary(buf, item->max_length, item->decimals);
503 if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg)))
504 {
505 room_in_tree = 0; // Remove tree, out of RAM ?
506 delete_tree(&tree, 0);
507 }
508 /*
509 if element->count == 1, this element can be found only once from tree
510 if element->count == 2, or more, this element is already in tree
511 */
512 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
513 {
514 room_in_tree = 0; // Remove tree, too many elements
515 delete_tree(&tree, 0);
516 }
517 }
518
519 if (!found)
520 {
521 found = 1;
522 min_arg = max_arg = sum[0] = dec;
523 my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, &dec, &dec);
524 cur_sum= 0;
525 min_length = max_length = length;
526 }
527 else if (!decimal_is_zero(&dec))
528 {
529 int next_cur_sum= cur_sum ^ 1;
530 my_decimal sqr_buf;
531
532 my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, &dec);
533 my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, &dec, &dec);
534 my_decimal_add(E_DEC_FATAL_ERROR,
535 sum_sqr+next_cur_sum, sum_sqr+cur_sum, &sqr_buf);
536 cur_sum= next_cur_sum;
537 if (length < min_length)
538 min_length = length;
539 if (length > max_length)
540 max_length = length;
541 if (dec.cmp(&min_arg) < 0)
542 {
543 min_arg= dec;
544 }
545 if (dec.cmp(&max_arg) > 0)
546 {
547 max_arg= dec;
548 }
549 }
550 }
551
552
add()553 void field_longlong::add()
554 {
555 char buff[MAX_FIELD_WIDTH];
556 longlong num = item->val_int();
557 uint length = (uint) (longlong10_to_str(num, buff, -10) - buff);
558 TREE_ELEMENT *element;
559
560 if (item->null_value)
561 {
562 nulls++;
563 return;
564 }
565 if (num == 0)
566 empty++;
567
568 if (room_in_tree)
569 {
570 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
571 {
572 room_in_tree = 0; // Remove tree, out of RAM ?
573 delete_tree(&tree, 0);
574 }
575 /*
576 if element->count == 1, this element can be found only once from tree
577 if element->count == 2, or more, this element is already in tree
578 */
579 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
580 {
581 room_in_tree = 0; // Remove tree, too many elements
582 delete_tree(&tree, 0);
583 }
584 }
585
586 if (!found)
587 {
588 found = 1;
589 min_arg = max_arg = sum = num;
590 sum_sqr = num * num;
591 min_length = max_length = length;
592 }
593 else if (num != 0)
594 {
595 sum += num;
596 sum_sqr += num * num;
597 if (length < min_length)
598 min_length = length;
599 if (length > max_length)
600 max_length = length;
601 if (compare_longlong(&num, &min_arg) < 0)
602 min_arg = num;
603 if (compare_longlong(&num, &max_arg) > 0)
604 max_arg = num;
605 }
606 } // field_longlong::add
607
608
add()609 void field_ulonglong::add()
610 {
611 char buff[MAX_FIELD_WIDTH];
612 longlong num = item->val_int();
613 uint length = (uint) (longlong10_to_str(num, buff, 10) - buff);
614 TREE_ELEMENT *element;
615
616 if (item->null_value)
617 {
618 nulls++;
619 return;
620 }
621 if (num == 0)
622 empty++;
623
624 if (room_in_tree)
625 {
626 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
627 {
628 room_in_tree = 0; // Remove tree, out of RAM ?
629 delete_tree(&tree, 0);
630 }
631 /*
632 if element->count == 1, this element can be found only once from tree
633 if element->count == 2, or more, this element is already in tree
634 */
635 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
636 {
637 room_in_tree = 0; // Remove tree, too many elements
638 delete_tree(&tree, 0);
639 }
640 }
641
642 if (!found)
643 {
644 found = 1;
645 min_arg = max_arg = sum = num;
646 sum_sqr = num * num;
647 min_length = max_length = length;
648 }
649 else if (num != 0)
650 {
651 sum += num;
652 sum_sqr += num * num;
653 if (length < min_length)
654 min_length = length;
655 if (length > max_length)
656 max_length = length;
657 if (compare_ulonglong((ulonglong*) &num, &min_arg) < 0)
658 min_arg = num;
659 if (compare_ulonglong((ulonglong*) &num, &max_arg) > 0)
660 max_arg = num;
661 }
662 } // field_ulonglong::add
663
664
send_row(List<Item> &)665 int analyse::send_row(List<Item> & /* field_list */)
666 {
667 field_info **f = f_info;
668
669 rows++;
670
671 for (;f != f_end; f++)
672 {
673 (*f)->add();
674 }
675 return 0;
676 } // analyse::send_row
677
678
end_of_records()679 int analyse::end_of_records()
680 {
681 field_info **f = f_info;
682 char buff[MAX_FIELD_WIDTH];
683 String *res, s_min(buff, sizeof(buff),&my_charset_bin),
684 s_max(buff, sizeof(buff),&my_charset_bin),
685 ans(buff, sizeof(buff),&my_charset_bin);
686
687 for (; f != f_end; f++)
688 {
689 func_items[0]->set((*f)->item->full_name());
690 if (!(*f)->found)
691 {
692 func_items[1]->null_value = 1;
693 func_items[2]->null_value = 1;
694 }
695 else
696 {
697 func_items[1]->null_value = 0;
698 res = (*f)->get_min_arg(&s_min);
699 func_items[1]->set(res->ptr(), res->length(), res->charset());
700 func_items[2]->null_value = 0;
701 res = (*f)->get_max_arg(&s_max);
702 func_items[2]->set(res->ptr(), res->length(), res->charset());
703 }
704 func_items[3]->set((longlong) (*f)->min_length);
705 func_items[4]->set((longlong) (*f)->max_length);
706 func_items[5]->set((longlong) (*f)->empty);
707 func_items[6]->set((longlong) (*f)->nulls);
708 res = (*f)->avg(&s_max, rows);
709 func_items[7]->set(res->ptr(), res->length(), res->charset());
710 func_items[8]->null_value = 0;
711 res = (*f)->std(&s_max, rows);
712 if (!res)
713 func_items[8]->null_value = 1;
714 else
715 func_items[8]->set(res->ptr(), res->length(), res->charset());
716 /*
717 count the dots, quotas, etc. in (ENUM("a","b","c"...))
718 If tree has been removed, don't suggest ENUM.
719 treemem is used to measure the size of tree for strings,
720 tree_elements is used to count the elements
721 max_treemem tells how long the string starting from ENUM("... and
722 ending to ..") shall at maximum be. If case is about numbers,
723 max_tree_elements will tell the length of the above, now
724 every number is considered as length 1
725 */
726 if (((*f)->treemem || (*f)->tree_elements) &&
727 (*f)->tree.elements_in_tree &&
728 (((*f)->treemem ? max_treemem : max_tree_elements) >
729 (((*f)->treemem ? (*f)->treemem : (*f)->tree_elements) +
730 ((*f)->tree.elements_in_tree * 3 - 1 + 6))))
731 {
732 char tmp[331]; //331, because one double prec. num. can be this long
733 String tmp_str(tmp, sizeof(tmp),&my_charset_bin);
734 TREE_INFO tree_info;
735
736 tree_info.str = &tmp_str;
737 tree_info.found = 0;
738 tree_info.item = (*f)->item;
739
740 tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin);
741 tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
742 left_root_right);
743 tmp_str.append(')');
744
745 if (!(*f)->nulls)
746 tmp_str.append(STRING_WITH_LEN(" NOT NULL"));
747 output_str_length = tmp_str.length();
748 func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
749 if (result->send_data(result_fields) > 0)
750 return -1;
751 continue;
752 }
753
754 ans.length(0);
755 if (!(*f)->treemem && !(*f)->tree_elements)
756 ans.append(STRING_WITH_LEN("CHAR(0)"));
757 else if ((*f)->item->type() == Item::FIELD_ITEM)
758 {
759 switch (((Item_field*) (*f)->item)->field->real_type())
760 {
761 case MYSQL_TYPE_TIMESTAMP:
762 ans.append(STRING_WITH_LEN("TIMESTAMP"));
763 break;
764 case MYSQL_TYPE_DATETIME:
765 ans.append(STRING_WITH_LEN("DATETIME"));
766 break;
767 case MYSQL_TYPE_DATE:
768 case MYSQL_TYPE_NEWDATE:
769 ans.append(STRING_WITH_LEN("DATE"));
770 break;
771 case MYSQL_TYPE_SET:
772 ans.append(STRING_WITH_LEN("SET"));
773 break;
774 case MYSQL_TYPE_YEAR:
775 ans.append(STRING_WITH_LEN("YEAR"));
776 break;
777 case MYSQL_TYPE_TIME:
778 ans.append(STRING_WITH_LEN("TIME"));
779 break;
780 case MYSQL_TYPE_DECIMAL:
781 ans.append(STRING_WITH_LEN("DECIMAL"));
782 // if item is FIELD_ITEM, it _must_be_ Field_num in this case
783 if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
784 ans.append(STRING_WITH_LEN(" ZEROFILL"));
785 break;
786 default:
787 (*f)->get_opt_type(&ans, rows);
788 break;
789 }
790 }
791 if (!(*f)->nulls)
792 ans.append(STRING_WITH_LEN(" NOT NULL"));
793 func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
794 if (result->send_data(result_fields) > 0)
795 return -1;
796 }
797 return 0;
798 } // analyse::end_of_records
799
800
get_opt_type(String * answer,ha_rows total_rows)801 void field_str::get_opt_type(String *answer, ha_rows total_rows)
802 {
803 char buff[MAX_FIELD_WIDTH];
804
805 if (can_be_still_num)
806 {
807 if (num_info.is_float)
808 sprintf(buff, "DOUBLE"); // number was like 1e+50... TODO:
809 else if (num_info.decimals) // DOUBLE(%d,%d) sometime
810 {
811 if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX)
812 sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
813 else
814 sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
815 }
816 else if (ev_num_info.llval >= -128 &&
817 ev_num_info.ullval <=
818 (ulonglong) (ev_num_info.llval >= 0 ? 255 : 127))
819 sprintf(buff, "TINYINT(%d)", num_info.integers);
820 else if (ev_num_info.llval >= INT_MIN16 &&
821 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
822 UINT_MAX16 : INT_MAX16))
823 sprintf(buff, "SMALLINT(%d)", num_info.integers);
824 else if (ev_num_info.llval >= INT_MIN24 &&
825 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
826 UINT_MAX24 : INT_MAX24))
827 sprintf(buff, "MEDIUMINT(%d)", num_info.integers);
828 else if (ev_num_info.llval >= INT_MIN32 &&
829 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
830 UINT_MAX32 : INT_MAX32))
831 sprintf(buff, "INT(%d)", num_info.integers);
832 else
833 sprintf(buff, "BIGINT(%d)", num_info.integers);
834 answer->append(buff, (uint) strlen(buff));
835 if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0)
836 answer->append(STRING_WITH_LEN(" UNSIGNED"));
837 if (num_info.zerofill)
838 answer->append(STRING_WITH_LEN(" ZEROFILL"));
839 }
840 else if (max_length < 256)
841 {
842 if (must_be_blob)
843 {
844 if (item->collation.collation == &my_charset_bin)
845 answer->append(STRING_WITH_LEN("TINYBLOB"));
846 else
847 answer->append(STRING_WITH_LEN("TINYTEXT"));
848 }
849 else if ((max_length * (total_rows - nulls)) < (sum + total_rows))
850 {
851 sprintf(buff, "CHAR(%d)", (int) max_length);
852 answer->append(buff, (uint) strlen(buff));
853 }
854 else
855 {
856 sprintf(buff, "VARCHAR(%d)", (int) max_length);
857 answer->append(buff, (uint) strlen(buff));
858 }
859 }
860 else if (max_length < (1L << 16))
861 {
862 if (item->collation.collation == &my_charset_bin)
863 answer->append(STRING_WITH_LEN("BLOB"));
864 else
865 answer->append(STRING_WITH_LEN("TEXT"));
866 }
867 else if (max_length < (1L << 24))
868 {
869 if (item->collation.collation == &my_charset_bin)
870 answer->append(STRING_WITH_LEN("MEDIUMBLOB"));
871 else
872 answer->append(STRING_WITH_LEN("MEDIUMTEXT"));
873 }
874 else
875 {
876 if (item->collation.collation == &my_charset_bin)
877 answer->append(STRING_WITH_LEN("LONGBLOB"));
878 else
879 answer->append(STRING_WITH_LEN("LONGTEXT"));
880 }
881 } // field_str::get_opt_type
882
883
get_opt_type(String * answer,ha_rows total_rows)884 void field_real::get_opt_type(String *answer,
885 ha_rows total_rows __attribute__((unused)))
886 {
887 char buff[MAX_FIELD_WIDTH];
888
889 if (!max_notzero_dec_len)
890 {
891 int len= (int) max_length - ((item->decimals >= FLOATING_POINT_DECIMALS) ?
892 0 : (item->decimals + 1));
893
894 if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
895 sprintf(buff, "TINYINT(%d)", len);
896 else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
897 UINT_MAX16 : INT_MAX16))
898 sprintf(buff, "SMALLINT(%d)", len);
899 else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
900 UINT_MAX24 : INT_MAX24))
901 sprintf(buff, "MEDIUMINT(%d)", len);
902 else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
903 UINT_MAX32 : INT_MAX32))
904 sprintf(buff, "INT(%d)", len);
905 else
906 sprintf(buff, "BIGINT(%d)", len);
907 answer->append(buff, (uint) strlen(buff));
908 if (min_arg >= 0)
909 answer->append(STRING_WITH_LEN(" UNSIGNED"));
910 }
911 else if (item->decimals >= FLOATING_POINT_DECIMALS)
912 {
913 if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
914 answer->append(STRING_WITH_LEN("FLOAT"));
915 else
916 answer->append(STRING_WITH_LEN("DOUBLE"));
917 }
918 else
919 {
920 if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
921 sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
922 max_notzero_dec_len);
923 else
924 sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
925 max_notzero_dec_len);
926 answer->append(buff, (uint) strlen(buff));
927 }
928 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
929 if (item->type() == Item::FIELD_ITEM &&
930 // a single number shouldn't be zerofill
931 (max_length - (item->decimals + 1)) != 1 &&
932 ((Field_num*) ((Item_field*) item)->field)->zerofill)
933 answer->append(STRING_WITH_LEN(" ZEROFILL"));
934 } // field_real::get_opt_type
935
936
get_opt_type(String * answer,ha_rows total_rows)937 void field_longlong::get_opt_type(String *answer,
938 ha_rows total_rows __attribute__((unused)))
939 {
940 char buff[MAX_FIELD_WIDTH];
941
942 if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
943 sprintf(buff, "TINYINT(%d)", (int) max_length);
944 else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
945 UINT_MAX16 : INT_MAX16))
946 sprintf(buff, "SMALLINT(%d)", (int) max_length);
947 else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
948 UINT_MAX24 : INT_MAX24))
949 sprintf(buff, "MEDIUMINT(%d)", (int) max_length);
950 else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
951 UINT_MAX32 : INT_MAX32))
952 sprintf(buff, "INT(%d)", (int) max_length);
953 else
954 sprintf(buff, "BIGINT(%d)", (int) max_length);
955 answer->append(buff, (uint) strlen(buff));
956 if (min_arg >= 0)
957 answer->append(STRING_WITH_LEN(" UNSIGNED"));
958
959 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
960 if ((item->type() == Item::FIELD_ITEM) &&
961 // a single number shouldn't be zerofill
962 max_length != 1 &&
963 ((Field_num*) ((Item_field*) item)->field)->zerofill)
964 answer->append(STRING_WITH_LEN(" ZEROFILL"));
965 } // field_longlong::get_opt_type
966
967
get_opt_type(String * answer,ha_rows total_rows)968 void field_ulonglong::get_opt_type(String *answer,
969 ha_rows total_rows __attribute__((unused)))
970 {
971 char buff[MAX_FIELD_WIDTH];
972
973 if (max_arg < 256)
974 sprintf(buff, "TINYINT(%d) UNSIGNED", (int) max_length);
975 else if (max_arg <= ((2 * INT_MAX16) + 1))
976 sprintf(buff, "SMALLINT(%d) UNSIGNED", (int) max_length);
977 else if (max_arg <= ((2 * INT_MAX24) + 1))
978 sprintf(buff, "MEDIUMINT(%d) UNSIGNED", (int) max_length);
979 else if (max_arg < (((ulonglong) 1) << 32))
980 sprintf(buff, "INT(%d) UNSIGNED", (int) max_length);
981 else
982 sprintf(buff, "BIGINT(%d) UNSIGNED", (int) max_length);
983 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
984 answer->append(buff, (uint) strlen(buff));
985 if (item->type() == Item::FIELD_ITEM &&
986 // a single number shouldn't be zerofill
987 max_length != 1 &&
988 ((Field_num*) ((Item_field*) item)->field)->zerofill)
989 answer->append(STRING_WITH_LEN(" ZEROFILL"));
990 } //field_ulonglong::get_opt_type
991
992
get_opt_type(String * answer,ha_rows total_rows)993 void field_decimal::get_opt_type(String *answer,
994 ha_rows total_rows __attribute__((unused)))
995 {
996 my_decimal zero;
997 char buff[MAX_FIELD_WIDTH];
998 uint length;
999
1000 my_decimal_set_zero(&zero);
1001 my_bool is_unsigned= (zero.cmp(&min_arg) >= 0);
1002
1003 length= sprintf(buff, "DECIMAL(%d, %d)",
1004 (int) (max_length - (item->decimals ? 1 : 0)),
1005 item->decimals);
1006 if (is_unsigned)
1007 length= (uint) (strmov(buff+length, " UNSIGNED")- buff);
1008 answer->append(buff, length);
1009 }
1010
1011
get_min_arg(String * str)1012 String *field_decimal::get_min_arg(String *str)
1013 {
1014 min_arg.to_string_native(str, 0, 0, '0');
1015 return str;
1016 }
1017
1018
get_max_arg(String * str)1019 String *field_decimal::get_max_arg(String *str)
1020 {
1021 max_arg.to_string_native(str, 0, 0, '0');
1022 return str;
1023 }
1024
1025
avg(String * s,ha_rows rows)1026 String *field_decimal::avg(String *s, ha_rows rows)
1027 {
1028 if (!(rows - nulls))
1029 {
1030 s->set_real((double) 0.0, 1,my_thd_charset);
1031 return s;
1032 }
1033 my_decimal num, avg_val, rounded_avg;
1034 int prec_increment= current_thd->variables.div_precincrement;
1035
1036 int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
1037 my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, prec_increment);
1038 /* TODO remove this after decimal_div returns proper frac */
1039 avg_val.round_to(&rounded_avg,
1040 MY_MIN(sum[cur_sum].frac + prec_increment, DECIMAL_MAX_SCALE),
1041 HALF_UP);
1042 rounded_avg.to_string_native(s, 0, 0, '0');
1043 return s;
1044 }
1045
1046
std(String * s,ha_rows rows)1047 String *field_decimal::std(String *s, ha_rows rows)
1048 {
1049 if (!(rows - nulls))
1050 {
1051 s->set_real((double) 0.0, 1,my_thd_charset);
1052 return s;
1053 }
1054 my_decimal num, tmp, sum2, sum2d;
1055 int prec_increment= current_thd->variables.div_precincrement;
1056
1057 int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
1058 my_decimal_mul(E_DEC_FATAL_ERROR, &sum2, sum+cur_sum, sum+cur_sum);
1059 my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1060 my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &tmp);
1061 my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1062 double std_sqr= tmp.to_double();
1063 s->set_real(((double) std_sqr <= 0.0 ? 0.0 : sqrt(std_sqr)),
1064 MY_MIN(item->decimals + prec_increment, NOT_FIXED_DEC), my_thd_charset);
1065
1066 return s;
1067 }
1068
1069
collect_string(String * element,element_count count,TREE_INFO * info)1070 int collect_string(String *element,
1071 element_count count __attribute__((unused)),
1072 TREE_INFO *info)
1073 {
1074 if (info->found)
1075 info->str->append(',');
1076 else
1077 info->found = 1;
1078 info->str->append('\'');
1079 if (info->str->append_for_single_quote(element))
1080 return 1;
1081 info->str->append('\'');
1082 return 0;
1083 } // collect_string
1084
1085
collect_real(double * element,element_count count,TREE_INFO * info)1086 int collect_real(double *element, element_count count __attribute__((unused)),
1087 TREE_INFO *info)
1088 {
1089 char buff[MAX_FIELD_WIDTH];
1090 String s(buff, sizeof(buff),current_thd->charset());
1091
1092 if (info->found)
1093 info->str->append(',');
1094 else
1095 info->found = 1;
1096 info->str->append('\'');
1097 s.set_real(*element, info->item->decimals, current_thd->charset());
1098 info->str->append(s);
1099 info->str->append('\'');
1100 return 0;
1101 } // collect_real
1102
1103
collect_decimal(uchar * element,element_count count,TREE_INFO * info)1104 int collect_decimal(uchar *element, element_count count,
1105 TREE_INFO *info)
1106 {
1107 char buff[DECIMAL_MAX_STR_LENGTH];
1108 String s(buff, sizeof(buff),&my_charset_bin);
1109
1110 if (info->found)
1111 info->str->append(',');
1112 else
1113 info->found = 1;
1114 my_decimal dec(element, info->item->max_length, info->item->decimals);
1115 info->str->append('\'');
1116 dec.to_string_native(&s, 0, 0, '0');
1117 info->str->append(s);
1118 info->str->append('\'');
1119 return 0;
1120 }
1121
1122
collect_longlong(longlong * element,element_count count,TREE_INFO * info)1123 int collect_longlong(longlong *element,
1124 element_count count __attribute__((unused)),
1125 TREE_INFO *info)
1126 {
1127 char buff[MAX_FIELD_WIDTH];
1128 String s(buff, sizeof(buff),&my_charset_bin);
1129
1130 if (info->found)
1131 info->str->append(',');
1132 else
1133 info->found = 1;
1134 info->str->append('\'');
1135 s.set(*element, current_thd->charset());
1136 info->str->append(s);
1137 info->str->append('\'');
1138 return 0;
1139 } // collect_longlong
1140
1141
collect_ulonglong(ulonglong * element,element_count count,TREE_INFO * info)1142 int collect_ulonglong(ulonglong *element,
1143 element_count count __attribute__((unused)),
1144 TREE_INFO *info)
1145 {
1146 char buff[MAX_FIELD_WIDTH];
1147 String s(buff, sizeof(buff),&my_charset_bin);
1148
1149 if (info->found)
1150 info->str->append(',');
1151 else
1152 info->found = 1;
1153 info->str->append('\'');
1154 s.set(*element, current_thd->charset());
1155 info->str->append(s);
1156 info->str->append('\'');
1157 return 0;
1158 } // collect_ulonglong
1159
1160
change_columns(THD * thd,List<Item> & field_list)1161 bool analyse::change_columns(THD *thd, List<Item> &field_list)
1162 {
1163 MEM_ROOT *mem_root= thd->mem_root;
1164 field_list.empty();
1165
1166 func_items[0]= new (mem_root) Item_proc_string(thd, "Field_name", 255);
1167 func_items[1]= new (mem_root) Item_proc_string(thd, "Min_value", 255);
1168 func_items[1]->maybe_null = 1;
1169 func_items[2]= new (mem_root) Item_proc_string(thd, "Max_value", 255);
1170 func_items[2]->maybe_null = 1;
1171 func_items[3]= new (mem_root) Item_proc_int(thd, "Min_length");
1172 func_items[4]= new (mem_root) Item_proc_int(thd, "Max_length");
1173 func_items[5]= new (mem_root) Item_proc_int(thd, "Empties_or_zeros");
1174 func_items[6]= new (mem_root) Item_proc_int(thd, "Nulls");
1175 func_items[7]= new (mem_root) Item_proc_string(thd, "Avg_value_or_avg_length", 255);
1176 func_items[8]= new (mem_root) Item_proc_string(thd, "Std", 255);
1177 func_items[8]->maybe_null = 1;
1178 func_items[9]= new (mem_root) Item_proc_string(thd, "Optimal_fieldtype",
1179 MY_MAX(64,
1180 output_str_length));
1181
1182 for (uint i = 0; i < array_elements(func_items); i++)
1183 field_list.push_back(func_items[i], thd->mem_root);
1184 result_fields = field_list;
1185 return 0;
1186 } // analyse::change_columns
1187
compare_double(const double * s,const double * t)1188 int compare_double(const double *s, const double *t)
1189 {
1190 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1191 } /* compare_double */
1192
compare_longlong(const longlong * s,const longlong * t)1193 int compare_longlong(const longlong *s, const longlong *t)
1194 {
1195 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1196 } /* compare_longlong */
1197
compare_ulonglong(const ulonglong * s,const ulonglong * t)1198 int compare_ulonglong(const ulonglong *s, const ulonglong *t)
1199 {
1200 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1201 } /* compare_ulonglong */
1202
1203
check_ulonglong(const char * str,uint length)1204 uint check_ulonglong(const char *str, uint length)
1205 {
1206 const char *long_str = "2147483647", *ulonglong_str = "18446744073709551615";
1207 const uint long_len = 10, ulonglong_len = 20;
1208
1209 while (*str == '0' && length)
1210 {
1211 str++; length--;
1212 }
1213 if (length < long_len)
1214 return NUM;
1215
1216 uint smaller, bigger;
1217 const char *cmp;
1218
1219 if (length == long_len)
1220 {
1221 cmp = long_str;
1222 smaller = NUM;
1223 bigger = LONG_NUM;
1224 }
1225 else if (length > ulonglong_len)
1226 return DECIMAL_NUM;
1227 else
1228 {
1229 cmp = ulonglong_str;
1230 smaller = LONG_NUM;
1231 bigger = DECIMAL_NUM;
1232 }
1233 while (*cmp && *cmp++ == *str++) ;
1234 return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
1235 } /* check_ulonlong */
1236