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