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