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