mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / sql / sql_analyse.cc
blob13cf9beb029228bdcbdde1217a8dd00b149a600a
1 /*
2 Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
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.
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.
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 St, Fifth Floor, Boston, MA 02110-1301 USA
19 /* Analyse database */
21 /* TODO: - Check if any character fields can be of any date type
22 ** (date, datetime, year, time, timestamp, newdate)
23 ** - Check if any number field should be a timestamp
24 ** - type set is out of optimization yet
27 #ifdef USE_PRAGMA_IMPLEMENTATION
28 #pragma implementation // gcc: Class implementation
29 #endif
31 #define MYSQL_LEX 1
33 #include "mysql_priv.h"
34 #include "procedure.h"
35 #include "sql_analyse.h"
36 #include <m_ctype.h>
38 #define MAX_TREEMEM 8192
39 #define MAX_TREE_ELEMENTS 256
41 int sortcmp2(void* cmp_arg __attribute__((unused)),
42 const String *a,const String *b)
44 return sortcmp(a,b,a->charset());
47 int compare_double2(void* cmp_arg __attribute__((unused)),
48 const double *s, const double *t)
50 return compare_double(s,t);
53 int compare_longlong2(void* cmp_arg __attribute__((unused)),
54 const longlong *s, const longlong *t)
56 return compare_longlong(s,t);
59 int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
60 const ulonglong *s, const ulonglong *t)
62 return compare_ulonglong(s,t);
65 int compare_decimal2(int* len, const char *s, const char *t)
67 return memcmp(s, t, *len);
71 Procedure *
72 proc_analyse_init(THD *thd, ORDER *param, select_result *result,
73 List<Item> &field_list)
75 char *proc_name = (*param->item)->name;
76 analyse *pc = new analyse(result);
77 field_info **f_info;
78 DBUG_ENTER("proc_analyse_init");
80 if (!pc)
81 DBUG_RETURN(0);
83 if (!(param = param->next))
85 pc->max_tree_elements = MAX_TREE_ELEMENTS;
86 pc->max_treemem = MAX_TREEMEM;
88 else if (param->next)
90 // first parameter
91 if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item))
93 DBUG_PRINT("info", ("fix_fields() for the first parameter failed"));
94 goto err;
96 if ((*param->item)->type() != Item::INT_ITEM ||
97 (*param->item)->val_real() < 0)
99 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
100 goto err;
102 pc->max_tree_elements = (uint) (*param->item)->val_int();
103 param = param->next;
104 if (param->next) // no third parameter possible
106 my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE, MYF(0), proc_name);
107 goto err;
109 // second parameter
110 if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item))
112 DBUG_PRINT("info", ("fix_fields() for the second parameter failed"));
113 goto err;
115 if ((*param->item)->type() != Item::INT_ITEM ||
116 (*param->item)->val_real() < 0)
118 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
119 goto err;
121 pc->max_treemem = (uint) (*param->item)->val_int();
123 else if ((*param->item)->type() != Item::INT_ITEM ||
124 (*param->item)->val_real() < 0)
126 my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
127 goto err;
129 // if only one parameter was given, it will be the value of max_tree_elements
130 else
132 pc->max_tree_elements = (uint) (*param->item)->val_int();
133 pc->max_treemem = MAX_TREEMEM;
136 if (!(pc->f_info=
137 (field_info**)sql_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;
143 List_iterator_fast<Item> it(pc->fields);
144 f_info = pc->f_info;
146 Item *item;
147 while ((item = it++))
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;
172 *f_info++= new_field;
175 DBUG_RETURN(pc);
176 err:
177 delete pc;
178 DBUG_RETURN(0);
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!
188 bool test_if_number(NUM_INFO *info, const char *str, uint str_len)
190 const char *begin, *end= str + str_len;
191 DBUG_ENTER("test_if_number");
194 MySQL removes any endspaces of a string, so we must take care only of
195 spaces in front of a string
197 for (; str != end && my_isspace(system_charset_info, *str); str++) ;
198 if (str == end)
199 DBUG_RETURN(0);
201 if (*str == '-')
203 info->negative = 1;
204 if (++str == end || *str == '0') // converting -0 to a number
205 DBUG_RETURN(0); // might lose information
207 else
208 info->negative = 0;
209 begin = str;
210 for (; str != end && my_isdigit(system_charset_info,*str); str++)
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++;
217 if (str == end && info->integers)
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
227 if (*str == '.' || *str == 'e' || *str == 'E')
229 if (info->zerofill) // can't be zerofill anymore
230 DBUG_RETURN(0);
231 if ((str + 1) == end) // number was something like '123[.eE]'
233 char *endpos= (char*) str;
234 int error;
235 info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error);
236 DBUG_RETURN(1);
238 if (*str == 'e' || *str == 'E') // number may be something like '1e+50'
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)
246 info->is_float = 1; // we can't use variable decimals here
247 DBUG_RETURN(1);
249 DBUG_RETURN(0);
251 for (str++; *(end - 1) == '0'; end--) ; // jump over zeros at the end
252 if (str == end) // number was something like '123.000'
254 char *endpos= (char*) str;
255 int error;
256 info->ullval= (ulonglong) my_strtoll10(begin, &endpos, &error);
257 DBUG_RETURN(1);
259 for (; str != end && my_isdigit(system_charset_info,*str); str++)
260 info->decimals++;
261 if (str == end)
263 info->dval = my_atof(begin);
264 DBUG_RETURN(1);
267 DBUG_RETURN(0);
272 Stores the biggest and the smallest value from current 'info'
273 to ev_num_info
274 If info contains an ulonglong number, which is bigger than
275 biggest positive number able to be stored in a longlong variable
276 and is marked as negative, function will return 0, else 1.
279 bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num)
281 if (info->negative)
283 if (((longlong) info->ullval) < 0)
284 return 0; // Impossible to store as a negative number
285 ev_info->llval = -(longlong) max((ulonglong) -ev_info->llval,
286 info->ullval);
287 ev_info->min_dval = (double) -max(-ev_info->min_dval, info->dval);
289 else // ulonglong is as big as bigint in MySQL
291 if ((check_ulonglong(num, info->integers) == DECIMAL_NUM))
292 return 0;
293 ev_info->ullval = (ulonglong) max(ev_info->ullval, info->ullval);
294 ev_info->max_dval = (double) max(ev_info->max_dval, info->dval);
296 return 1;
297 } // get_ev_num_info
300 void free_string(String *s)
302 s->free();
306 void field_str::add()
308 char buff[MAX_FIELD_WIDTH], *ptr;
309 String s(buff, sizeof(buff),&my_charset_bin), *res;
310 ulong length;
312 if (!(res = item->val_str(&s)))
314 nulls++;
315 return;
318 if (!(length = res->length()))
319 empty++;
320 else
322 ptr = (char*) res->ptr();
323 if (*(ptr + (length - 1)) == ' ')
324 must_be_blob = 1;
327 if (can_be_still_num)
329 bzero((char*) &num_info, sizeof(num_info));
330 if (!test_if_number(&num_info, res->ptr(), (uint) length))
331 can_be_still_num = 0;
332 if (!found)
334 bzero((char*) &ev_num_info, sizeof(ev_num_info));
335 was_zero_fill = num_info.zerofill;
337 else if (num_info.zerofill != was_zero_fill && !was_maybe_zerofill)
338 can_be_still_num = 0; // one more check needed, when length is counted
339 if (can_be_still_num)
340 can_be_still_num = get_ev_num_info(&ev_num_info, &num_info, res->ptr());
341 was_maybe_zerofill = num_info.maybe_zerofill;
344 /* Update min and max arguments */
345 if (!found)
347 found = 1;
348 min_arg.copy(*res);
349 max_arg.copy(*res);
350 min_length = max_length = length; sum=length;
352 else if (length)
354 sum += length;
355 if (length < min_length)
356 min_length = length;
357 if (length > max_length)
358 max_length = length;
360 if (sortcmp(res, &min_arg,item->collation.collation) < 0)
361 min_arg.copy(*res);
362 if (sortcmp(res, &max_arg,item->collation.collation) > 0)
363 max_arg.copy(*res);
366 if (room_in_tree)
368 if (res != &s)
369 s.copy(*res);
370 if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
372 s.copy(); // slow, when SAFE_MALLOC is in use
373 if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
375 room_in_tree = 0; // Remove tree, out of RAM ?
376 delete_tree(&tree);
378 else
380 bzero((char*) &s, sizeof(s)); // Let tree handle free of this
381 if ((treemem += length) > pc->max_treemem)
383 room_in_tree = 0; // Remove tree, too big tree
384 delete_tree(&tree);
390 if ((num_info.zerofill && (max_length != min_length)) ||
391 (was_zero_fill && (max_length != min_length)))
392 can_be_still_num = 0; // zerofilled numbers must be of same length
393 } // field_str::add
396 void field_real::add()
398 char buff[MAX_FIELD_WIDTH], *ptr, *end;
399 double num= item->val_real();
400 uint length, zero_count, decs;
401 TREE_ELEMENT *element;
403 if (item->null_value)
405 nulls++;
406 return;
408 if (num == 0.0)
409 empty++;
411 if ((decs = decimals()) == NOT_FIXED_DEC)
413 length= sprintf(buff, "%g", num);
414 if (rint(num) != num)
415 max_notzero_dec_len = 1;
417 else
419 #ifdef HAVE_SNPRINTF
420 buff[sizeof(buff)-1]=0; // Safety
421 snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num);
422 length = (uint) strlen(buff);
423 #else
424 length= sprintf(buff, "%-.*f", (int) decs, num);
425 #endif
427 // We never need to check further than this
428 end = buff + length - 1 - decs + max_notzero_dec_len;
430 zero_count = 0;
431 for (ptr = buff + length - 1; ptr > end && *ptr == '0'; ptr--)
432 zero_count++;
434 if ((decs - zero_count > max_notzero_dec_len))
435 max_notzero_dec_len = decs - zero_count;
438 if (room_in_tree)
440 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
442 room_in_tree = 0; // Remove tree, out of RAM ?
443 delete_tree(&tree);
446 if element->count == 1, this element can be found only once from tree
447 if element->count == 2, or more, this element is already in tree
449 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
451 room_in_tree = 0; // Remove tree, too many elements
452 delete_tree(&tree);
456 if (!found)
458 found = 1;
459 min_arg = max_arg = sum = num;
460 sum_sqr = num * num;
461 min_length = max_length = length;
463 else if (num != 0.0)
465 sum += num;
466 sum_sqr += num * num;
467 if (length < min_length)
468 min_length = length;
469 if (length > max_length)
470 max_length = length;
471 if (compare_double(&num, &min_arg) < 0)
472 min_arg = num;
473 if (compare_double(&num, &max_arg) > 0)
474 max_arg = num;
476 } // field_real::add
479 void field_decimal::add()
481 /*TODO - remove rounding stuff after decimal_div returns proper frac */
482 my_decimal dec_buf, *dec= item->val_decimal(&dec_buf);
483 my_decimal rounded;
484 uint length;
485 TREE_ELEMENT *element;
487 if (item->null_value)
489 nulls++;
490 return;
493 my_decimal_round(E_DEC_FATAL_ERROR, dec, item->decimals, FALSE,&rounded);
494 dec= &rounded;
496 length= my_decimal_string_length(dec);
498 if (decimal_is_zero(dec))
499 empty++;
501 if (room_in_tree)
503 uchar buf[DECIMAL_MAX_FIELD_SIZE];
504 my_decimal2binary(E_DEC_FATAL_ERROR, dec, buf,
505 item->max_length, item->decimals);
506 if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg)))
508 room_in_tree = 0; // Remove tree, out of RAM ?
509 delete_tree(&tree);
512 if element->count == 1, this element can be found only once from tree
513 if element->count == 2, or more, this element is already in tree
515 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
517 room_in_tree = 0; // Remove tree, too many elements
518 delete_tree(&tree);
522 if (!found)
524 found = 1;
525 min_arg = max_arg = sum[0] = *dec;
526 my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec);
527 cur_sum= 0;
528 min_length = max_length = length;
530 else if (!decimal_is_zero(dec))
532 int next_cur_sum= cur_sum ^ 1;
533 my_decimal sqr_buf;
535 my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, dec);
536 my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec);
537 my_decimal_add(E_DEC_FATAL_ERROR,
538 sum_sqr+next_cur_sum, sum_sqr+cur_sum, &sqr_buf);
539 cur_sum= next_cur_sum;
540 if (length < min_length)
541 min_length = length;
542 if (length > max_length)
543 max_length = length;
544 if (my_decimal_cmp(dec, &min_arg) < 0)
546 min_arg= *dec;
548 if (my_decimal_cmp(dec, &max_arg) > 0)
550 max_arg= *dec;
556 void field_longlong::add()
558 char buff[MAX_FIELD_WIDTH];
559 longlong num = item->val_int();
560 uint length = (uint) (longlong10_to_str(num, buff, -10) - buff);
561 TREE_ELEMENT *element;
563 if (item->null_value)
565 nulls++;
566 return;
568 if (num == 0)
569 empty++;
571 if (room_in_tree)
573 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
575 room_in_tree = 0; // Remove tree, out of RAM ?
576 delete_tree(&tree);
579 if element->count == 1, this element can be found only once from tree
580 if element->count == 2, or more, this element is already in tree
582 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
584 room_in_tree = 0; // Remove tree, too many elements
585 delete_tree(&tree);
589 if (!found)
591 found = 1;
592 min_arg = max_arg = sum = num;
593 sum_sqr = num * num;
594 min_length = max_length = length;
596 else if (num != 0)
598 sum += num;
599 sum_sqr += num * num;
600 if (length < min_length)
601 min_length = length;
602 if (length > max_length)
603 max_length = length;
604 if (compare_longlong(&num, &min_arg) < 0)
605 min_arg = num;
606 if (compare_longlong(&num, &max_arg) > 0)
607 max_arg = num;
609 } // field_longlong::add
612 void field_ulonglong::add()
614 char buff[MAX_FIELD_WIDTH];
615 longlong num = item->val_int();
616 uint length = (uint) (longlong10_to_str(num, buff, 10) - buff);
617 TREE_ELEMENT *element;
619 if (item->null_value)
621 nulls++;
622 return;
624 if (num == 0)
625 empty++;
627 if (room_in_tree)
629 if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
631 room_in_tree = 0; // Remove tree, out of RAM ?
632 delete_tree(&tree);
635 if element->count == 1, this element can be found only once from tree
636 if element->count == 2, or more, this element is already in tree
638 else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
640 room_in_tree = 0; // Remove tree, too many elements
641 delete_tree(&tree);
645 if (!found)
647 found = 1;
648 min_arg = max_arg = sum = num;
649 sum_sqr = num * num;
650 min_length = max_length = length;
652 else if (num != 0)
654 sum += num;
655 sum_sqr += num * num;
656 if (length < min_length)
657 min_length = length;
658 if (length > max_length)
659 max_length = length;
660 if (compare_ulonglong((ulonglong*) &num, &min_arg) < 0)
661 min_arg = num;
662 if (compare_ulonglong((ulonglong*) &num, &max_arg) > 0)
663 max_arg = num;
665 } // field_ulonglong::add
668 int analyse::send_row(List<Item> & /* field_list */)
670 field_info **f = f_info;
672 rows++;
674 for (;f != f_end; f++)
676 (*f)->add();
678 return 0;
679 } // analyse::send_row
682 int analyse::end_of_records()
684 field_info **f = f_info;
685 char buff[MAX_FIELD_WIDTH];
686 String *res, s_min(buff, sizeof(buff),&my_charset_bin),
687 s_max(buff, sizeof(buff),&my_charset_bin),
688 ans(buff, sizeof(buff),&my_charset_bin);
690 for (; f != f_end; f++)
692 func_items[0]->set((*f)->item->full_name());
693 if (!(*f)->found)
695 func_items[1]->null_value = 1;
696 func_items[2]->null_value = 1;
698 else
700 func_items[1]->null_value = 0;
701 res = (*f)->get_min_arg(&s_min);
702 func_items[1]->set(res->ptr(), res->length(), res->charset());
703 func_items[2]->null_value = 0;
704 res = (*f)->get_max_arg(&s_max);
705 func_items[2]->set(res->ptr(), res->length(), res->charset());
707 func_items[3]->set((longlong) (*f)->min_length);
708 func_items[4]->set((longlong) (*f)->max_length);
709 func_items[5]->set((longlong) (*f)->empty);
710 func_items[6]->set((longlong) (*f)->nulls);
711 res = (*f)->avg(&s_max, rows);
712 func_items[7]->set(res->ptr(), res->length(), res->charset());
713 func_items[8]->null_value = 0;
714 res = (*f)->std(&s_max, rows);
715 if (!res)
716 func_items[8]->null_value = 1;
717 else
718 func_items[8]->set(res->ptr(), res->length(), res->charset());
720 count the dots, quotas, etc. in (ENUM("a","b","c"...))
721 If tree has been removed, don't suggest ENUM.
722 treemem is used to measure the size of tree for strings,
723 tree_elements is used to count the elements
724 max_treemem tells how long the string starting from ENUM("... and
725 ending to ..") shall at maximum be. If case is about numbers,
726 max_tree_elements will tell the length of the above, now
727 every number is considered as length 1
729 if (((*f)->treemem || (*f)->tree_elements) &&
730 (*f)->tree.elements_in_tree &&
731 (((*f)->treemem ? max_treemem : max_tree_elements) >
732 (((*f)->treemem ? (*f)->treemem : (*f)->tree_elements) +
733 ((*f)->tree.elements_in_tree * 3 - 1 + 6))))
735 char tmp[331]; //331, because one double prec. num. can be this long
736 String tmp_str(tmp, sizeof(tmp),&my_charset_bin);
737 TREE_INFO tree_info;
739 tree_info.str = &tmp_str;
740 tree_info.found = 0;
741 tree_info.item = (*f)->item;
743 tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin);
744 tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
745 left_root_right);
746 tmp_str.append(')');
748 if (!(*f)->nulls)
749 tmp_str.append(STRING_WITH_LEN(" NOT NULL"));
750 output_str_length = tmp_str.length();
751 func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
752 if (result->send_data(result_fields))
753 return -1;
754 continue;
757 ans.length(0);
758 if (!(*f)->treemem && !(*f)->tree_elements)
759 ans.append(STRING_WITH_LEN("CHAR(0)"));
760 else if ((*f)->item->type() == Item::FIELD_ITEM)
762 switch (((Item_field*) (*f)->item)->field->real_type())
764 case MYSQL_TYPE_TIMESTAMP:
765 ans.append(STRING_WITH_LEN("TIMESTAMP"));
766 break;
767 case MYSQL_TYPE_DATETIME:
768 ans.append(STRING_WITH_LEN("DATETIME"));
769 break;
770 case MYSQL_TYPE_DATE:
771 case MYSQL_TYPE_NEWDATE:
772 ans.append(STRING_WITH_LEN("DATE"));
773 break;
774 case MYSQL_TYPE_SET:
775 ans.append(STRING_WITH_LEN("SET"));
776 break;
777 case MYSQL_TYPE_YEAR:
778 ans.append(STRING_WITH_LEN("YEAR"));
779 break;
780 case MYSQL_TYPE_TIME:
781 ans.append(STRING_WITH_LEN("TIME"));
782 break;
783 case MYSQL_TYPE_DECIMAL:
784 ans.append(STRING_WITH_LEN("DECIMAL"));
785 // if item is FIELD_ITEM, it _must_be_ Field_num in this case
786 if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
787 ans.append(STRING_WITH_LEN(" ZEROFILL"));
788 break;
789 default:
790 (*f)->get_opt_type(&ans, rows);
791 break;
794 if (!(*f)->nulls)
795 ans.append(STRING_WITH_LEN(" NOT NULL"));
796 func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
797 if (result->send_data(result_fields))
798 return -1;
800 return 0;
801 } // analyse::end_of_records
804 void field_str::get_opt_type(String *answer, ha_rows total_rows)
806 char buff[MAX_FIELD_WIDTH];
808 if (can_be_still_num)
810 if (num_info.is_float)
811 sprintf(buff, "DOUBLE"); // number was like 1e+50... TODO:
812 else if (num_info.decimals) // DOUBLE(%d,%d) sometime
814 if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX)
815 sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
816 else
817 sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
819 else if (ev_num_info.llval >= -128 &&
820 ev_num_info.ullval <=
821 (ulonglong) (ev_num_info.llval >= 0 ? 255 : 127))
822 sprintf(buff, "TINYINT(%d)", num_info.integers);
823 else if (ev_num_info.llval >= INT_MIN16 &&
824 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
825 UINT_MAX16 : INT_MAX16))
826 sprintf(buff, "SMALLINT(%d)", num_info.integers);
827 else if (ev_num_info.llval >= INT_MIN24 &&
828 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
829 UINT_MAX24 : INT_MAX24))
830 sprintf(buff, "MEDIUMINT(%d)", num_info.integers);
831 else if (ev_num_info.llval >= INT_MIN32 &&
832 ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
833 UINT_MAX32 : INT_MAX32))
834 sprintf(buff, "INT(%d)", num_info.integers);
835 else
836 sprintf(buff, "BIGINT(%d)", num_info.integers);
837 answer->append(buff, (uint) strlen(buff));
838 if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0)
839 answer->append(STRING_WITH_LEN(" UNSIGNED"));
840 if (num_info.zerofill)
841 answer->append(STRING_WITH_LEN(" ZEROFILL"));
843 else if (max_length < 256)
845 if (must_be_blob)
847 if (item->collation.collation == &my_charset_bin)
848 answer->append(STRING_WITH_LEN("TINYBLOB"));
849 else
850 answer->append(STRING_WITH_LEN("TINYTEXT"));
852 else if ((max_length * (total_rows - nulls)) < (sum + total_rows))
854 sprintf(buff, "CHAR(%d)", (int) max_length);
855 answer->append(buff, (uint) strlen(buff));
857 else
859 sprintf(buff, "VARCHAR(%d)", (int) max_length);
860 answer->append(buff, (uint) strlen(buff));
863 else if (max_length < (1L << 16))
865 if (item->collation.collation == &my_charset_bin)
866 answer->append(STRING_WITH_LEN("BLOB"));
867 else
868 answer->append(STRING_WITH_LEN("TEXT"));
870 else if (max_length < (1L << 24))
872 if (item->collation.collation == &my_charset_bin)
873 answer->append(STRING_WITH_LEN("MEDIUMBLOB"));
874 else
875 answer->append(STRING_WITH_LEN("MEDIUMTEXT"));
877 else
879 if (item->collation.collation == &my_charset_bin)
880 answer->append(STRING_WITH_LEN("LONGBLOB"));
881 else
882 answer->append(STRING_WITH_LEN("LONGTEXT"));
884 } // field_str::get_opt_type
887 void field_real::get_opt_type(String *answer,
888 ha_rows total_rows __attribute__((unused)))
890 char buff[MAX_FIELD_WIDTH];
892 if (!max_notzero_dec_len)
894 int len= (int) max_length - ((item->decimals == NOT_FIXED_DEC) ?
895 0 : (item->decimals + 1));
897 if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
898 sprintf(buff, "TINYINT(%d)", len);
899 else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
900 UINT_MAX16 : INT_MAX16))
901 sprintf(buff, "SMALLINT(%d)", len);
902 else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
903 UINT_MAX24 : INT_MAX24))
904 sprintf(buff, "MEDIUMINT(%d)", len);
905 else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
906 UINT_MAX32 : INT_MAX32))
907 sprintf(buff, "INT(%d)", len);
908 else
909 sprintf(buff, "BIGINT(%d)", len);
910 answer->append(buff, (uint) strlen(buff));
911 if (min_arg >= 0)
912 answer->append(STRING_WITH_LEN(" UNSIGNED"));
914 else if (item->decimals == NOT_FIXED_DEC)
916 if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
917 answer->append(STRING_WITH_LEN("FLOAT"));
918 else
919 answer->append(STRING_WITH_LEN("DOUBLE"));
921 else
923 if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
924 sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
925 max_notzero_dec_len);
926 else
927 sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
928 max_notzero_dec_len);
929 answer->append(buff, (uint) strlen(buff));
931 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
932 if (item->type() == Item::FIELD_ITEM &&
933 // a single number shouldn't be zerofill
934 (max_length - (item->decimals + 1)) != 1 &&
935 ((Field_num*) ((Item_field*) item)->field)->zerofill)
936 answer->append(STRING_WITH_LEN(" ZEROFILL"));
937 } // field_real::get_opt_type
940 void field_longlong::get_opt_type(String *answer,
941 ha_rows total_rows __attribute__((unused)))
943 char buff[MAX_FIELD_WIDTH];
945 if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
946 sprintf(buff, "TINYINT(%d)", (int) max_length);
947 else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
948 UINT_MAX16 : INT_MAX16))
949 sprintf(buff, "SMALLINT(%d)", (int) max_length);
950 else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
951 UINT_MAX24 : INT_MAX24))
952 sprintf(buff, "MEDIUMINT(%d)", (int) max_length);
953 else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
954 UINT_MAX32 : INT_MAX32))
955 sprintf(buff, "INT(%d)", (int) max_length);
956 else
957 sprintf(buff, "BIGINT(%d)", (int) max_length);
958 answer->append(buff, (uint) strlen(buff));
959 if (min_arg >= 0)
960 answer->append(STRING_WITH_LEN(" UNSIGNED"));
962 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
963 if ((item->type() == Item::FIELD_ITEM) &&
964 // a single number shouldn't be zerofill
965 max_length != 1 &&
966 ((Field_num*) ((Item_field*) item)->field)->zerofill)
967 answer->append(STRING_WITH_LEN(" ZEROFILL"));
968 } // field_longlong::get_opt_type
971 void field_ulonglong::get_opt_type(String *answer,
972 ha_rows total_rows __attribute__((unused)))
974 char buff[MAX_FIELD_WIDTH];
976 if (max_arg < 256)
977 sprintf(buff, "TINYINT(%d) UNSIGNED", (int) max_length);
978 else if (max_arg <= ((2 * INT_MAX16) + 1))
979 sprintf(buff, "SMALLINT(%d) UNSIGNED", (int) max_length);
980 else if (max_arg <= ((2 * INT_MAX24) + 1))
981 sprintf(buff, "MEDIUMINT(%d) UNSIGNED", (int) max_length);
982 else if (max_arg < (((ulonglong) 1) << 32))
983 sprintf(buff, "INT(%d) UNSIGNED", (int) max_length);
984 else
985 sprintf(buff, "BIGINT(%d) UNSIGNED", (int) max_length);
986 // if item is FIELD_ITEM, it _must_be_ Field_num in this class
987 answer->append(buff, (uint) strlen(buff));
988 if (item->type() == Item::FIELD_ITEM &&
989 // a single number shouldn't be zerofill
990 max_length != 1 &&
991 ((Field_num*) ((Item_field*) item)->field)->zerofill)
992 answer->append(STRING_WITH_LEN(" ZEROFILL"));
993 } //field_ulonglong::get_opt_type
996 void field_decimal::get_opt_type(String *answer,
997 ha_rows total_rows __attribute__((unused)))
999 my_decimal zero;
1000 char buff[MAX_FIELD_WIDTH];
1001 uint length;
1003 my_decimal_set_zero(&zero);
1004 my_bool is_unsigned= (my_decimal_cmp(&zero, &min_arg) >= 0);
1006 length= my_snprintf(buff, sizeof(buff), "DECIMAL(%d, %d)",
1007 (int) (max_length - (item->decimals ? 1 : 0)),
1008 item->decimals);
1009 if (is_unsigned)
1010 length= (uint) (strmov(buff+length, " UNSIGNED")- buff);
1011 answer->append(buff, length);
1015 String *field_decimal::get_min_arg(String *str)
1017 my_decimal2string(E_DEC_FATAL_ERROR, &min_arg, 0, 0, '0', str);
1018 return str;
1022 String *field_decimal::get_max_arg(String *str)
1024 my_decimal2string(E_DEC_FATAL_ERROR, &max_arg, 0, 0, '0', str);
1025 return str;
1029 String *field_decimal::avg(String *s, ha_rows rows)
1031 if (!(rows - nulls))
1033 s->set_real((double) 0.0, 1,my_thd_charset);
1034 return s;
1036 my_decimal num, avg_val, rounded_avg;
1037 int prec_increment= current_thd->variables.div_precincrement;
1039 int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
1040 my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, prec_increment);
1041 /* TODO remove this after decimal_div returns proper frac */
1042 my_decimal_round(E_DEC_FATAL_ERROR, &avg_val,
1043 min(sum[cur_sum].frac + prec_increment, DECIMAL_MAX_SCALE),
1044 FALSE,&rounded_avg);
1045 my_decimal2string(E_DEC_FATAL_ERROR, &rounded_avg, 0, 0, '0', s);
1046 return s;
1050 String *field_decimal::std(String *s, ha_rows rows)
1052 if (!(rows - nulls))
1054 s->set_real((double) 0.0, 1,my_thd_charset);
1055 return s;
1057 my_decimal num, tmp, sum2, sum2d;
1058 double std_sqr;
1059 int prec_increment= current_thd->variables.div_precincrement;
1061 int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
1062 my_decimal_mul(E_DEC_FATAL_ERROR, &sum2, sum+cur_sum, sum+cur_sum);
1063 my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1064 my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &tmp);
1065 my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1066 my_decimal2double(E_DEC_FATAL_ERROR, &tmp, &std_sqr);
1067 s->set_real(((double) std_sqr <= 0.0 ? 0.0 : sqrt(std_sqr)),
1068 min(item->decimals + prec_increment, NOT_FIXED_DEC), my_thd_charset);
1070 return s;
1074 int collect_string(String *element,
1075 element_count count __attribute__((unused)),
1076 TREE_INFO *info)
1078 if (info->found)
1079 info->str->append(',');
1080 else
1081 info->found = 1;
1082 info->str->append('\'');
1083 if (append_escaped(info->str, element))
1084 return 1;
1085 info->str->append('\'');
1086 return 0;
1087 } // collect_string
1090 int collect_real(double *element, element_count count __attribute__((unused)),
1091 TREE_INFO *info)
1093 char buff[MAX_FIELD_WIDTH];
1094 String s(buff, sizeof(buff),current_thd->charset());
1096 if (info->found)
1097 info->str->append(',');
1098 else
1099 info->found = 1;
1100 info->str->append('\'');
1101 s.set_real(*element, info->item->decimals, current_thd->charset());
1102 info->str->append(s);
1103 info->str->append('\'');
1104 return 0;
1105 } // collect_real
1108 int collect_decimal(uchar *element, element_count count,
1109 TREE_INFO *info)
1111 char buff[DECIMAL_MAX_STR_LENGTH];
1112 String s(buff, sizeof(buff),&my_charset_bin);
1114 if (info->found)
1115 info->str->append(',');
1116 else
1117 info->found = 1;
1118 my_decimal dec;
1119 binary2my_decimal(E_DEC_FATAL_ERROR, element, &dec,
1120 info->item->max_length, info->item->decimals);
1122 info->str->append('\'');
1123 my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, '0', &s);
1124 info->str->append(s);
1125 info->str->append('\'');
1126 return 0;
1130 int collect_longlong(longlong *element,
1131 element_count count __attribute__((unused)),
1132 TREE_INFO *info)
1134 char buff[MAX_FIELD_WIDTH];
1135 String s(buff, sizeof(buff),&my_charset_bin);
1137 if (info->found)
1138 info->str->append(',');
1139 else
1140 info->found = 1;
1141 info->str->append('\'');
1142 s.set(*element, current_thd->charset());
1143 info->str->append(s);
1144 info->str->append('\'');
1145 return 0;
1146 } // collect_longlong
1149 int collect_ulonglong(ulonglong *element,
1150 element_count count __attribute__((unused)),
1151 TREE_INFO *info)
1153 char buff[MAX_FIELD_WIDTH];
1154 String s(buff, sizeof(buff),&my_charset_bin);
1156 if (info->found)
1157 info->str->append(',');
1158 else
1159 info->found = 1;
1160 info->str->append('\'');
1161 s.set(*element, current_thd->charset());
1162 info->str->append(s);
1163 info->str->append('\'');
1164 return 0;
1165 } // collect_ulonglong
1168 bool analyse::change_columns(List<Item> &field_list)
1170 field_list.empty();
1172 func_items[0] = new Item_proc_string("Field_name", 255);
1173 func_items[1] = new Item_proc_string("Min_value", 255);
1174 func_items[1]->maybe_null = 1;
1175 func_items[2] = new Item_proc_string("Max_value", 255);
1176 func_items[2]->maybe_null = 1;
1177 func_items[3] = new Item_proc_int("Min_length");
1178 func_items[4] = new Item_proc_int("Max_length");
1179 func_items[5] = new Item_proc_int("Empties_or_zeros");
1180 func_items[6] = new Item_proc_int("Nulls");
1181 func_items[7] = new Item_proc_string("Avg_value_or_avg_length", 255);
1182 func_items[8] = new Item_proc_string("Std", 255);
1183 func_items[8]->maybe_null = 1;
1184 func_items[9] = new Item_proc_string("Optimal_fieldtype",
1185 max(64, output_str_length));
1187 for (uint i = 0; i < array_elements(func_items); i++)
1188 field_list.push_back(func_items[i]);
1189 result_fields = field_list;
1190 return 0;
1191 } // analyse::change_columns
1193 int compare_double(const double *s, const double *t)
1195 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1196 } /* compare_double */
1198 int compare_longlong(const longlong *s, const longlong *t)
1200 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1201 } /* compare_longlong */
1203 int compare_ulonglong(const ulonglong *s, const ulonglong *t)
1205 return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1206 } /* compare_ulonglong */
1209 uint check_ulonglong(const char *str, uint length)
1211 const char *long_str = "2147483647", *ulonglong_str = "18446744073709551615";
1212 const uint long_len = 10, ulonglong_len = 20;
1214 while (*str == '0' && length)
1216 str++; length--;
1218 if (length < long_len)
1219 return NUM;
1221 uint smaller, bigger;
1222 const char *cmp;
1224 if (length == long_len)
1226 cmp = long_str;
1227 smaller = NUM;
1228 bigger = LONG_NUM;
1230 else if (length > ulonglong_len)
1231 return DECIMAL_NUM;
1232 else
1234 cmp = ulonglong_str;
1235 smaller = LONG_NUM;
1236 bigger = DECIMAL_NUM;
1238 while (*cmp && *cmp++ == *str++) ;
1239 return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
1240 } /* check_ulonlong */
1244 Quote special characters in a string.
1246 SYNOPSIS
1247 append_escaped(to_str, from_str)
1248 to_str (in) A pointer to a String.
1249 from_str (to) A pointer to an allocated string
1251 DESCRIPTION
1252 append_escaped() takes a String type variable, where it appends
1253 escaped the second argument. Only characters that require escaping
1254 will be escaped.
1256 RETURN VALUES
1257 0 Success
1258 1 Out of memory
1261 bool append_escaped(String *to_str, String *from_str)
1263 char *from, *end, c;
1265 if (to_str->realloc(to_str->length() + from_str->length()))
1266 return 1;
1268 from= (char*) from_str->ptr();
1269 end= from + from_str->length();
1270 for (; from < end; from++)
1272 c= *from;
1273 switch (c) {
1274 case '\0':
1275 c= '0';
1276 break;
1277 case '\032':
1278 c= 'Z';
1279 break;
1280 case '\\':
1281 case '\'':
1282 break;
1283 default:
1284 goto normal_character;
1286 if (to_str->append('\\'))
1287 return 1;
1289 normal_character:
1290 if (to_str->append(c))
1291 return 1;
1293 return 0;