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 
add()254 void field_str::add()
255 {
256   char buff[MAX_FIELD_WIDTH], *ptr;
257   String s(buff, sizeof(buff),&my_charset_bin), *res;
258   size_t length;
259 
260   if (!(res= item->str_result(&s)))
261   {
262     nulls++;
263     return;
264   }
265 
266   if (!(length = res->length()))
267     empty++;
268   else
269   {
270     ptr = (char*) res->ptr();
271     if (*(ptr + (length - 1)) == ' ')
272       must_be_blob = 1;
273   }
274 
275   if (can_be_still_num)
276   {
277     memset(&num_info, 0, sizeof(num_info));
278     if (!test_if_number(&num_info, res->ptr(), (uint) length))
279       can_be_still_num = 0;
280     if (!found)
281     {
282       memset(&ev_num_info, 0, sizeof(ev_num_info));
283       was_zero_fill = num_info.zerofill;
284     }
285     else if (num_info.zerofill != was_zero_fill && !was_maybe_zerofill)
286       can_be_still_num = 0;  // one more check needed, when length is counted
287     if (can_be_still_num)
288       can_be_still_num = get_ev_num_info(&ev_num_info, &num_info, res->ptr());
289     was_maybe_zerofill = num_info.maybe_zerofill;
290   }
291 
292   /* Update min and max arguments */
293   if (!found)
294   {
295     found = 1;
296     min_arg.copy(*res);
297     max_arg.copy(*res);
298     min_length = max_length = length; sum=length;
299   }
300   else if (length)
301   {
302     sum += length;
303     if (length < min_length)
304       min_length = length;
305     if (length > max_length)
306       max_length = length;
307 
308     if (sortcmp(res, &min_arg,item->collation.collation) < 0)
309       min_arg.copy(*res);
310     if (sortcmp(res, &max_arg,item->collation.collation) > 0)
311       max_arg.copy(*res);
312   }
313 
314   if (room_in_tree)
315   {
316     if (res != &s)
317       s.copy(*res);
318     if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
319     {
320       s.copy();        // slow, when SAFE_MALLOC is in use
321       if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
322       {
323 	room_in_tree = 0;      // Remove tree, out of RAM ?
324 	delete_tree(&tree);
325       }
326       else
327       {
328         ::new (&s) String; // Let tree handle free of this
329 	if ((treemem += length) > pc->max_treemem)
330 	{
331 	  room_in_tree = 0;	 // Remove tree, too big tree
332 	  delete_tree(&tree);
333 	}
334       }
335     }
336   }
337 
338   if ((num_info.zerofill && (max_length != min_length)) ||
339       (was_zero_fill && (max_length != min_length)))
340     can_be_still_num = 0; // zerofilled numbers must be of same length
341 } // field_str::add
342 
343 
add()344 void field_real::add()
345 {
346   char buff[MAX_FIELD_WIDTH], *ptr, *end;
347   double num= item->val_result();
348   size_t length;
349   uint zero_count, decs;
350   TREE_ELEMENT *element;
351 
352   if (item->null_value)
353   {
354     nulls++;
355     return;
356   }
357   if (num == 0.0)
358     empty++;
359 
360   if ((decs = decimals()) == NOT_FIXED_DEC)
361   {
362     length= sprintf(buff, "%g", num);
363     if (rint(num) != num)
364       max_notzero_dec_len = 1;
365   }
366   else
367   {
368     buff[sizeof(buff)-1]=0;			// Safety
369     my_snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num);
370     length= strlen(buff);
371 
372     // We never need to check further than this
373     end = buff + length - 1 - decs + max_notzero_dec_len;
374 
375     zero_count = 0;
376     for (ptr = buff + length - 1; ptr > end && *ptr == '0'; ptr--)
377       zero_count++;
378 
379     if ((decs - zero_count > max_notzero_dec_len))
380       max_notzero_dec_len = decs - zero_count;
381   }
382 
383   if (room_in_tree)
384   {
385     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
386     {
387       room_in_tree = 0;    // Remove tree, out of RAM ?
388       delete_tree(&tree);
389     }
390     /*
391       if element->count == 1, this element can be found only once from tree
392       if element->count == 2, or more, this element is already in tree
393     */
394     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
395     {
396       room_in_tree = 0;  // Remove tree, too many elements
397       delete_tree(&tree);
398     }
399   }
400 
401   if (!found)
402   {
403     found = 1;
404     min_arg = max_arg = sum = num;
405     sum_sqr = num * num;
406     min_length = max_length = length;
407   }
408   else if (num != 0.0)
409   {
410     sum += num;
411     sum_sqr += num * num;
412     if (length < min_length)
413       min_length = length;
414     if (length > max_length)
415       max_length = length;
416     if (compare_double(&num, &min_arg) < 0)
417       min_arg = num;
418     if (compare_double(&num, &max_arg) > 0)
419       max_arg = num;
420   }
421 } // field_real::add
422 
423 
add()424 void field_decimal::add()
425 {
426   /*TODO - remove rounding stuff after decimal_div returns proper frac */
427   my_decimal dec_buf, *dec= item->val_decimal_result(&dec_buf);
428   my_decimal rounded;
429   uint length;
430   TREE_ELEMENT *element;
431 
432   if (item->null_value)
433   {
434     nulls++;
435     return;
436   }
437 
438   my_decimal_round(E_DEC_FATAL_ERROR, dec, item->decimals, FALSE,&rounded);
439   dec= &rounded;
440 
441   length= my_decimal_string_length(dec);
442 
443   if (decimal_is_zero(dec))
444     empty++;
445 
446   if (room_in_tree)
447   {
448     uchar buf[DECIMAL_MAX_FIELD_SIZE];
449     my_decimal2binary(E_DEC_FATAL_ERROR, dec, buf,
450                       item->max_length, item->decimals);
451     if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg)))
452     {
453       room_in_tree = 0;    // Remove tree, out of RAM ?
454       delete_tree(&tree);
455     }
456     /*
457       if element->count == 1, this element can be found only once from tree
458       if element->count == 2, or more, this element is already in tree
459     */
460     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
461     {
462       room_in_tree = 0;  // Remove tree, too many elements
463       delete_tree(&tree);
464     }
465   }
466 
467   if (!found)
468   {
469     found = 1;
470     min_arg = max_arg = sum[0] = *dec;
471     my_decimal_mul(E_DEC_FATAL_ERROR, sum_sqr, dec, dec);
472     cur_sum= 0;
473     min_length = max_length = length;
474   }
475   else if (!decimal_is_zero(dec))
476   {
477     int next_cur_sum= cur_sum ^ 1;
478     my_decimal sqr_buf;
479 
480     my_decimal_add(E_DEC_FATAL_ERROR, sum+next_cur_sum, sum+cur_sum, dec);
481     my_decimal_mul(E_DEC_FATAL_ERROR, &sqr_buf, dec, dec);
482     my_decimal_add(E_DEC_FATAL_ERROR,
483                    sum_sqr+next_cur_sum, sum_sqr+cur_sum, &sqr_buf);
484     cur_sum= next_cur_sum;
485     if (length < min_length)
486       min_length = length;
487     if (length > max_length)
488       max_length = length;
489     if (my_decimal_cmp(dec, &min_arg) < 0)
490     {
491       min_arg= *dec;
492     }
493     if (my_decimal_cmp(dec, &max_arg) > 0)
494     {
495       max_arg= *dec;
496     }
497   }
498 }
499 
500 
add()501 void field_longlong::add()
502 {
503   char buff[MAX_FIELD_WIDTH];
504   longlong num= item->val_int_result();
505   uint length= (uint) (longlong10_to_str(num, buff, -10) - buff);
506   TREE_ELEMENT *element;
507 
508   if (item->null_value)
509   {
510     nulls++;
511     return;
512   }
513   if (num == 0)
514     empty++;
515 
516   if (room_in_tree)
517   {
518     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
519     {
520       room_in_tree = 0;    // Remove tree, out of RAM ?
521       delete_tree(&tree);
522     }
523     /*
524       if element->count == 1, this element can be found only once from tree
525       if element->count == 2, or more, this element is already in tree
526     */
527     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
528     {
529       room_in_tree = 0;  // Remove tree, too many elements
530       delete_tree(&tree);
531     }
532   }
533 
534   if (!found)
535   {
536     found = 1;
537     min_arg = max_arg = sum = num;
538     sum_sqr = num * num;
539     min_length = max_length = length;
540   }
541   else if (num != 0)
542   {
543     sum += num;
544     sum_sqr += num * num;
545     if (length < min_length)
546       min_length = length;
547     if (length > max_length)
548       max_length = length;
549     if (compare_longlong(&num, &min_arg) < 0)
550       min_arg = num;
551     if (compare_longlong(&num, &max_arg) > 0)
552       max_arg = num;
553   }
554 } // field_longlong::add
555 
556 
add()557 void field_ulonglong::add()
558 {
559   char buff[MAX_FIELD_WIDTH];
560   longlong num= item->val_int_result();
561   uint length= (uint) (longlong10_to_str(num, buff, 10) - buff);
562   TREE_ELEMENT *element;
563 
564   if (item->null_value)
565   {
566     nulls++;
567     return;
568   }
569   if (num == 0)
570     empty++;
571 
572   if (room_in_tree)
573   {
574     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
575     {
576       room_in_tree = 0;    // Remove tree, out of RAM ?
577       delete_tree(&tree);
578     }
579     /*
580       if element->count == 1, this element can be found only once from tree
581       if element->count == 2, or more, this element is already in tree
582     */
583     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
584     {
585       room_in_tree = 0;  // Remove tree, too many elements
586       delete_tree(&tree);
587     }
588   }
589 
590   if (!found)
591   {
592     found = 1;
593     min_arg = max_arg = sum = num;
594     sum_sqr = num * num;
595     min_length = max_length = length;
596   }
597   else if (num != 0)
598   {
599     sum += num;
600     sum_sqr += num * num;
601     if (length < min_length)
602       min_length = length;
603     if (length > max_length)
604       max_length = length;
605     if (compare_ulonglong((ulonglong*) &num, &min_arg) < 0)
606       min_arg = num;
607     if (compare_ulonglong((ulonglong*) &num, &max_arg) > 0)
608       max_arg = num;
609   }
610 } // field_ulonglong::add
611 
612 
send_data(List<Item> &)613 bool Query_result_analyse::send_data(List<Item> & /* field_list */)
614 {
615   field_info **f = f_info;
616 
617   rows++;
618 
619   for (;f != f_end; f++)
620   {
621     (*f)->add();
622   }
623   return false;
624 }
625 
626 
send_eof()627 bool Query_result_analyse::send_eof()
628 {
629   field_info **f = f_info;
630   char buff[MAX_FIELD_WIDTH];
631   String *res, s_min(buff, sizeof(buff),&my_charset_bin),
632 	 s_max(buff, sizeof(buff),&my_charset_bin),
633 	 ans(buff, sizeof(buff),&my_charset_bin);
634 
635   if (rows == 0) // for backward compatibility
636     goto ok;
637 
638   for (; f != f_end; f++)
639   {
640     func_items[0]->set((*f)->item->full_name());
641     if (!(*f)->found)
642     {
643       func_items[1]->null_value = 1;
644       func_items[2]->null_value = 1;
645     }
646     else
647     {
648       func_items[1]->null_value = 0;
649       res = (*f)->get_min_arg(&s_min);
650       func_items[1]->set(res->ptr(), res->length(), res->charset());
651       func_items[2]->null_value = 0;
652       res = (*f)->get_max_arg(&s_max);
653       func_items[2]->set(res->ptr(), res->length(), res->charset());
654     }
655     func_items[3]->set((longlong) (*f)->min_length);
656     func_items[4]->set((longlong) (*f)->max_length);
657     func_items[5]->set((longlong) (*f)->empty);
658     func_items[6]->set((longlong) (*f)->nulls);
659     res = (*f)->avg(&s_max, rows);
660     func_items[7]->set(res->ptr(), res->length(), res->charset());
661     func_items[8]->null_value = 0;
662     res = (*f)->std(&s_max, rows);
663     if (!res)
664       func_items[8]->null_value = 1;
665     else
666       func_items[8]->set(res->ptr(), res->length(), res->charset());
667     /*
668       count the dots, quotas, etc. in (ENUM("a","b","c"...))
669       If tree has been removed, don't suggest ENUM.
670       treemem is used to measure the size of tree for strings,
671       tree_elements is used to count the elements
672       max_treemem tells how long the string starting from ENUM("... and
673       ending to ..") shall at maximum be. If case is about numbers,
674       max_tree_elements will tell the length of the above, now
675       every number is considered as length 1
676     */
677     if (((*f)->treemem || (*f)->tree_elements) &&
678 	(*f)->tree.elements_in_tree &&
679 	(((*f)->treemem ? max_treemem : max_tree_elements) >
680 	 (((*f)->treemem ? (*f)->treemem : (*f)->tree_elements) +
681 	   ((*f)->tree.elements_in_tree * 3 - 1 + 6))))
682     {
683       char tmp[331]; //331, because one double prec. num. can be this long
684       String tmp_str(tmp, sizeof(tmp),&my_charset_bin);
685       TREE_INFO tree_info;
686 
687       tree_info.str = &tmp_str;
688       tree_info.found = 0;
689       tree_info.item = (*f)->item;
690 
691       tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin);
692       tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
693 		left_root_right);
694       tmp_str.append(')');
695 
696       if (!(*f)->nulls)
697 	tmp_str.append(STRING_WITH_LEN(" NOT NULL"));
698       output_str_length = tmp_str.length();
699       func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
700       if (result->send_data(result_fields))
701 	goto error;
702       continue;
703     }
704 
705     ans.length(0);
706     if (!(*f)->treemem && !(*f)->tree_elements)
707       ans.append(STRING_WITH_LEN("CHAR(0)"));
708     else if ((*f)->item->type() == Item::FIELD_ITEM)
709     {
710       switch (((Item_field*) (*f)->item)->field->real_type())
711       {
712       case MYSQL_TYPE_TIMESTAMP:
713 	ans.append(STRING_WITH_LEN("TIMESTAMP"));
714 	break;
715       case MYSQL_TYPE_DATETIME:
716 	ans.append(STRING_WITH_LEN("DATETIME"));
717 	break;
718       case MYSQL_TYPE_DATE:
719       case MYSQL_TYPE_NEWDATE:
720 	ans.append(STRING_WITH_LEN("DATE"));
721 	break;
722       case MYSQL_TYPE_SET:
723 	ans.append(STRING_WITH_LEN("SET"));
724 	break;
725       case MYSQL_TYPE_YEAR:
726 	ans.append(STRING_WITH_LEN("YEAR"));
727 	break;
728       case MYSQL_TYPE_TIME:
729 	ans.append(STRING_WITH_LEN("TIME"));
730 	break;
731       case MYSQL_TYPE_DECIMAL:
732 	ans.append(STRING_WITH_LEN("DECIMAL"));
733 	// if item is FIELD_ITEM, it _must_be_ Field_num in this case
734 	if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
735 	  ans.append(STRING_WITH_LEN(" ZEROFILL"));
736 	break;
737       default:
738 	(*f)->get_opt_type(&ans, rows);
739 	break;
740       }
741     }
742     if (!(*f)->nulls)
743       ans.append(STRING_WITH_LEN(" NOT NULL"));
744     func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
745     if (result->send_data(result_fields))
746       goto error;
747   }
748 ok:
749   return result->send_eof();
750 error:
751   abort_result_set();
752   return true;
753 } // Query_result_analyse::send_eof
754 
755 
get_opt_type(String * answer,ha_rows total_rows)756 void field_str::get_opt_type(String *answer, ha_rows total_rows)
757 {
758   char buff[MAX_FIELD_WIDTH];
759 
760   if (can_be_still_num)
761   {
762     if (num_info.is_float)
763       sprintf(buff, "DOUBLE");	  // number was like 1e+50... TODO:
764     else if (num_info.decimals) // DOUBLE(%d,%d) sometime
765     {
766       if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX)
767 	sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
768       else
769 	sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals);
770     }
771     else if (ev_num_info.llval >= -128 &&
772 	     ev_num_info.ullval <=
773 	     (ulonglong) (ev_num_info.llval >= 0 ? 255 : 127))
774       sprintf(buff, "TINYINT(%d)", num_info.integers);
775     else if (ev_num_info.llval >= INT_MIN16 &&
776 	     ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
777 						UINT_MAX16 : INT_MAX16))
778       sprintf(buff, "SMALLINT(%d)", num_info.integers);
779     else if (ev_num_info.llval >= INT_MIN24 &&
780 	     ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
781 						UINT_MAX24 : INT_MAX24))
782       sprintf(buff, "MEDIUMINT(%d)", num_info.integers);
783     else if (ev_num_info.llval >= INT_MIN32 &&
784 	     ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
785 						UINT_MAX32 : INT_MAX32))
786       sprintf(buff, "INT(%d)", num_info.integers);
787     else
788       sprintf(buff, "BIGINT(%d)", num_info.integers);
789     answer->append(buff, strlen(buff));
790     if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0)
791       answer->append(STRING_WITH_LEN(" UNSIGNED"));
792     if (num_info.zerofill)
793       answer->append(STRING_WITH_LEN(" ZEROFILL"));
794   }
795   else if (max_length < 256)
796   {
797     if (must_be_blob)
798     {
799       if (item->collation.collation == &my_charset_bin)
800 	answer->append(STRING_WITH_LEN("TINYBLOB"));
801       else
802 	answer->append(STRING_WITH_LEN("TINYTEXT"));
803     }
804     else if ((max_length * (total_rows - nulls)) < (sum + total_rows))
805     {
806       sprintf(buff, "CHAR(%d)", (int) max_length);
807       answer->append(buff, strlen(buff));
808     }
809     else
810     {
811       sprintf(buff, "VARCHAR(%d)", (int) max_length);
812       answer->append(buff, strlen(buff));
813     }
814   }
815   else if (max_length < (1L << 16))
816   {
817     if (item->collation.collation == &my_charset_bin)
818       answer->append(STRING_WITH_LEN("BLOB"));
819     else
820       answer->append(STRING_WITH_LEN("TEXT"));
821   }
822   else if (max_length < (1L << 24))
823   {
824     if (item->collation.collation == &my_charset_bin)
825       answer->append(STRING_WITH_LEN("MEDIUMBLOB"));
826     else
827       answer->append(STRING_WITH_LEN("MEDIUMTEXT"));
828   }
829   else
830   {
831     if (item->collation.collation == &my_charset_bin)
832       answer->append(STRING_WITH_LEN("LONGBLOB"));
833     else
834       answer->append(STRING_WITH_LEN("LONGTEXT"));
835   }
836 } // field_str::get_opt_type
837 
838 
get_opt_type(String * answer,ha_rows total_rows MY_ATTRIBUTE ((unused)))839 void field_real::get_opt_type(String *answer,
840 			      ha_rows total_rows MY_ATTRIBUTE((unused)))
841 {
842   char buff[MAX_FIELD_WIDTH];
843 
844   if (!max_notzero_dec_len)
845   {
846     int len= (int) max_length - ((item->decimals == NOT_FIXED_DEC) ?
847 				 0 : (item->decimals + 1));
848 
849     if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
850       sprintf(buff, "TINYINT(%d)", len);
851     else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
852 						 UINT_MAX16 : INT_MAX16))
853       sprintf(buff, "SMALLINT(%d)", len);
854     else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
855 						 UINT_MAX24 : INT_MAX24))
856       sprintf(buff, "MEDIUMINT(%d)", len);
857     else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
858 						 UINT_MAX32 : INT_MAX32))
859       sprintf(buff, "INT(%d)", len);
860     else
861       sprintf(buff, "BIGINT(%d)", len);
862     answer->append(buff, strlen(buff));
863     if (min_arg >= 0)
864       answer->append(STRING_WITH_LEN(" UNSIGNED"));
865   }
866   else if (item->decimals == NOT_FIXED_DEC)
867   {
868     if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
869       answer->append(STRING_WITH_LEN("FLOAT"));
870     else
871       answer->append(STRING_WITH_LEN("DOUBLE"));
872   }
873   else
874   {
875     if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
876       sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
877 	      max_notzero_dec_len);
878     else
879       sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len,
880 	      max_notzero_dec_len);
881     answer->append(buff, strlen(buff));
882   }
883   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
884   if (item->type() == Item::FIELD_ITEM &&
885       // a single number shouldn't be zerofill
886       (max_length - (item->decimals + 1)) != 1 &&
887       ((Field_num*) ((Item_field*) item)->field)->zerofill)
888     answer->append(STRING_WITH_LEN(" ZEROFILL"));
889 } // field_real::get_opt_type
890 
891 
get_opt_type(String * answer,ha_rows total_rows MY_ATTRIBUTE ((unused)))892 void field_longlong::get_opt_type(String *answer,
893 				  ha_rows total_rows MY_ATTRIBUTE((unused)))
894 {
895   char buff[MAX_FIELD_WIDTH];
896 
897   if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
898     sprintf(buff, "TINYINT(%d)", (int) max_length);
899   else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
900 					       UINT_MAX16 : INT_MAX16))
901     sprintf(buff, "SMALLINT(%d)", (int) max_length);
902   else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
903 					       UINT_MAX24 : INT_MAX24))
904     sprintf(buff, "MEDIUMINT(%d)", (int) max_length);
905   else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
906 					       UINT_MAX32 : INT_MAX32))
907     sprintf(buff, "INT(%d)", (int) max_length);
908   else
909     sprintf(buff, "BIGINT(%d)", (int) max_length);
910   answer->append(buff, strlen(buff));
911   if (min_arg >= 0)
912     answer->append(STRING_WITH_LEN(" UNSIGNED"));
913 
914   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
915   if ((item->type() == Item::FIELD_ITEM) &&
916       // a single number shouldn't be zerofill
917       max_length != 1 &&
918       ((Field_num*) ((Item_field*) item)->field)->zerofill)
919     answer->append(STRING_WITH_LEN(" ZEROFILL"));
920 } // field_longlong::get_opt_type
921 
922 
get_opt_type(String * answer,ha_rows total_rows MY_ATTRIBUTE ((unused)))923 void field_ulonglong::get_opt_type(String *answer,
924 				   ha_rows total_rows MY_ATTRIBUTE((unused)))
925 {
926   char buff[MAX_FIELD_WIDTH];
927 
928   if (max_arg < 256)
929     sprintf(buff, "TINYINT(%d) UNSIGNED", (int) max_length);
930    else if (max_arg <= ((2 * INT_MAX16) + 1))
931      sprintf(buff, "SMALLINT(%d) UNSIGNED", (int) max_length);
932   else if (max_arg <= ((2 * INT_MAX24) + 1))
933     sprintf(buff, "MEDIUMINT(%d) UNSIGNED", (int) max_length);
934   else if (max_arg < (((ulonglong) 1) << 32))
935     sprintf(buff, "INT(%d) UNSIGNED", (int) max_length);
936   else
937     sprintf(buff, "BIGINT(%d) UNSIGNED", (int) max_length);
938   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
939   answer->append(buff, strlen(buff));
940   if (item->type() == Item::FIELD_ITEM &&
941       // a single number shouldn't be zerofill
942       max_length != 1 &&
943       ((Field_num*) ((Item_field*) item)->field)->zerofill)
944     answer->append(STRING_WITH_LEN(" ZEROFILL"));
945 } //field_ulonglong::get_opt_type
946 
947 
get_opt_type(String * answer,ha_rows total_rows MY_ATTRIBUTE ((unused)))948 void field_decimal::get_opt_type(String *answer,
949                                  ha_rows total_rows MY_ATTRIBUTE((unused)))
950 {
951   my_decimal zero;
952   char buff[MAX_FIELD_WIDTH];
953   size_t length;
954 
955   my_decimal_set_zero(&zero);
956   my_bool is_unsigned= (my_decimal_cmp(&zero, &min_arg) >= 0);
957 
958   length= my_snprintf(buff, sizeof(buff), "DECIMAL(%d, %d)",
959                       static_cast<int>(max_length - (item->decimals ? 1 : 0)),
960                       static_cast<int>(item->decimals));
961   if (is_unsigned)
962     length= (my_stpcpy(buff+length, " UNSIGNED")- buff);
963   answer->append(buff, length);
964 }
965 
966 
get_min_arg(String * str)967 String *field_decimal::get_min_arg(String *str)
968 {
969   my_decimal2string(E_DEC_FATAL_ERROR, &min_arg, 0, 0, '0', str);
970   return str;
971 }
972 
973 
get_max_arg(String * str)974 String *field_decimal::get_max_arg(String *str)
975 {
976   my_decimal2string(E_DEC_FATAL_ERROR, &max_arg, 0, 0, '0', str);
977   return str;
978 }
979 
980 
avg(String * s,ha_rows rows)981 String *field_decimal::avg(String *s, ha_rows rows)
982 {
983   if (!(rows - nulls))
984   {
985     s->set_real(0.0, 1,my_thd_charset);
986     return s;
987   }
988   my_decimal num, avg_val, rounded_avg;
989   int prec_increment= current_thd->variables.div_precincrement;
990 
991   int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
992   my_decimal_div(E_DEC_FATAL_ERROR, &avg_val, sum+cur_sum, &num, prec_increment);
993   /* TODO remove this after decimal_div returns proper frac */
994   my_decimal_round(E_DEC_FATAL_ERROR, &avg_val,
995                    min(sum[cur_sum].frac + prec_increment, DECIMAL_MAX_SCALE),
996                    FALSE,&rounded_avg);
997   my_decimal2string(E_DEC_FATAL_ERROR, &rounded_avg, 0, 0, '0', s);
998   return s;
999 }
1000 
1001 
std(String * s,ha_rows rows)1002 String *field_decimal::std(String *s, ha_rows rows)
1003 {
1004   if (!(rows - nulls))
1005   {
1006     s->set_real(0.0, 1,my_thd_charset);
1007     return s;
1008   }
1009   my_decimal num, tmp, sum2, sum2d;
1010   double std_sqr;
1011   int prec_increment= current_thd->variables.div_precincrement;
1012 
1013   int2my_decimal(E_DEC_FATAL_ERROR, rows - nulls, FALSE, &num);
1014   my_decimal_mul(E_DEC_FATAL_ERROR, &sum2, sum+cur_sum, sum+cur_sum);
1015   my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1016   my_decimal_sub(E_DEC_FATAL_ERROR, &sum2, sum_sqr+cur_sum, &tmp);
1017   my_decimal_div(E_DEC_FATAL_ERROR, &tmp, &sum2, &num, prec_increment);
1018   my_decimal2double(E_DEC_FATAL_ERROR, &tmp, &std_sqr);
1019   s->set_real((std_sqr <= 0.0 ? 0.0 : sqrt(std_sqr)),
1020          min(item->decimals + prec_increment, NOT_FIXED_DEC), my_thd_charset);
1021 
1022   return s;
1023 }
1024 
1025 
collect_string(String * element,element_count count MY_ATTRIBUTE ((unused)),TREE_INFO * info)1026 int collect_string(String *element,
1027 		   element_count count MY_ATTRIBUTE((unused)),
1028 		   TREE_INFO *info)
1029 {
1030   if (info->found)
1031     info->str->append(',');
1032   else
1033     info->found = 1;
1034   info->str->append('\'');
1035   if (append_escaped(info->str, element))
1036     return 1;
1037   info->str->append('\'');
1038   return 0;
1039 } // collect_string
1040 
1041 
collect_real(double * element,element_count count MY_ATTRIBUTE ((unused)),TREE_INFO * info)1042 int collect_real(double *element, element_count count MY_ATTRIBUTE((unused)),
1043 		 TREE_INFO *info)
1044 {
1045   char buff[MAX_FIELD_WIDTH];
1046   String s(buff, sizeof(buff),current_thd->charset());
1047 
1048   if (info->found)
1049     info->str->append(',');
1050   else
1051     info->found = 1;
1052   info->str->append('\'');
1053   s.set_real(*element, info->item->decimals, current_thd->charset());
1054   info->str->append(s);
1055   info->str->append('\'');
1056   return 0;
1057 } // collect_real
1058 
1059 
collect_decimal(uchar * element,element_count count,TREE_INFO * info)1060 int collect_decimal(uchar *element, element_count count,
1061                     TREE_INFO *info)
1062 {
1063   char buff[DECIMAL_MAX_STR_LENGTH + 1];
1064   String s(buff, sizeof(buff),&my_charset_bin);
1065 
1066   if (info->found)
1067     info->str->append(',');
1068   else
1069     info->found = 1;
1070   my_decimal dec;
1071   binary2my_decimal(E_DEC_FATAL_ERROR, element, &dec,
1072                     info->item->max_length, info->item->decimals);
1073 
1074   info->str->append('\'');
1075   my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, '0', &s);
1076   info->str->append(s);
1077   info->str->append('\'');
1078   return 0;
1079 }
1080 
1081 
collect_longlong(longlong * element,element_count count MY_ATTRIBUTE ((unused)),TREE_INFO * info)1082 int collect_longlong(longlong *element,
1083 		     element_count count MY_ATTRIBUTE((unused)),
1084 		     TREE_INFO *info)
1085 {
1086   char buff[MAX_FIELD_WIDTH];
1087   String s(buff, sizeof(buff),&my_charset_bin);
1088 
1089   if (info->found)
1090     info->str->append(',');
1091   else
1092     info->found = 1;
1093   info->str->append('\'');
1094   s.set(*element, current_thd->charset());
1095   info->str->append(s);
1096   info->str->append('\'');
1097   return 0;
1098 } // collect_longlong
1099 
1100 
collect_ulonglong(ulonglong * element,element_count count MY_ATTRIBUTE ((unused)),TREE_INFO * info)1101 int collect_ulonglong(ulonglong *element,
1102 		      element_count count MY_ATTRIBUTE((unused)),
1103 		      TREE_INFO *info)
1104 {
1105   char buff[MAX_FIELD_WIDTH];
1106   String s(buff, sizeof(buff),&my_charset_bin);
1107 
1108   if (info->found)
1109     info->str->append(',');
1110   else
1111     info->found = 1;
1112   info->str->append('\'');
1113   s.set(*element, current_thd->charset());
1114   info->str->append(s);
1115   info->str->append('\'');
1116   return 0;
1117 } // collect_ulonglong
1118 
1119 
1120 /**
1121   Create items for substituted output columns (both metadata and data)
1122 */
change_columns()1123 bool Query_result_analyse::change_columns()
1124 {
1125   func_items[0] = new Item_proc_string("Field_name", 255);
1126   func_items[1] = new Item_proc_string("Min_value", 255);
1127   func_items[1]->maybe_null = 1;
1128   func_items[2] = new Item_proc_string("Max_value", 255);
1129   func_items[2]->maybe_null = 1;
1130   func_items[3] = new Item_proc_int("Min_length");
1131   func_items[4] = new Item_proc_int("Max_length");
1132   func_items[5] = new Item_proc_int("Empties_or_zeros");
1133   func_items[6] = new Item_proc_int("Nulls");
1134   func_items[7] = new Item_proc_string("Avg_value_or_avg_length", 255);
1135   func_items[8] = new Item_proc_string("Std", 255);
1136   func_items[8]->maybe_null = 1;
1137   func_items[9] = new Item_proc_string("Optimal_fieldtype",
1138 				       max<size_t>(64U, output_str_length));
1139   result_fields.empty();
1140   for (uint i = 0; i < array_elements(func_items); i++)
1141   {
1142     if (func_items[i] == NULL)
1143       return true;
1144     result_fields.push_back(func_items[i]);
1145   }
1146   return false;
1147 } // Query_result_analyse::change_columns
1148 
1149 
cleanup()1150 void Query_result_analyse::cleanup()
1151 {
1152   if (f_info)
1153   {
1154     for (field_info **f= f_info; f != f_end; f++)
1155       delete (*f);
1156     f_info= f_end= NULL;
1157   }
1158   rows= 0;
1159   output_str_length= 0;
1160 }
1161 
1162 
send_result_set_metadata(List<Item> & fields,uint flag)1163 bool Query_result_analyse::send_result_set_metadata(List<Item> &fields,
1164                                                     uint flag)
1165 {
1166   return (init(fields) || change_columns() ||
1167 	  result->send_result_set_metadata(result_fields, flag));
1168 }
1169 
1170 
abort_result_set()1171 void Query_result_analyse::abort_result_set()
1172 {
1173   cleanup();
1174   return result->abort_result_set();
1175 }
1176 
1177 
compare_double(const double * s,const double * t)1178 int compare_double(const double *s, const double *t)
1179 {
1180   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1181 } /* compare_double */
1182 
compare_longlong(const longlong * s,const longlong * t)1183 int compare_longlong(const longlong *s, const longlong *t)
1184 {
1185   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1186 } /* compare_longlong */
1187 
compare_ulonglong(const ulonglong * s,const ulonglong * t)1188  int compare_ulonglong(const ulonglong *s, const ulonglong *t)
1189 {
1190   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
1191 } /* compare_ulonglong */
1192 
1193 
check_ulonglong(const char * str,uint length)1194 uint check_ulonglong(const char *str, uint length)
1195 {
1196   const char *long_str = "2147483647", *ulonglong_str = "18446744073709551615";
1197   const uint long_len = 10, ulonglong_len = 20;
1198 
1199   while (*str == '0' && length)
1200   {
1201     str++; length--;
1202   }
1203   if (length < long_len)
1204     return NUM;
1205 
1206   uint smaller, bigger;
1207   const char *cmp;
1208 
1209   if (length == long_len)
1210   {
1211     cmp = long_str;
1212     smaller = NUM;
1213     bigger = LONG_NUM;
1214   }
1215   else if (length > ulonglong_len)
1216     return DECIMAL_NUM;
1217   else
1218   {
1219     cmp = ulonglong_str;
1220     smaller = LONG_NUM;
1221     bigger = DECIMAL_NUM;
1222   }
1223   while (*cmp && *cmp++ == *str++) ;
1224   return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
1225 } /* check_ulonlong */
1226 
1227 
1228 /*
1229   Quote special characters in a string.
1230 
1231   SYNOPSIS
1232    append_escaped(to_str, from_str)
1233    to_str (in) A pointer to a String.
1234    from_str (to) A pointer to an allocated string
1235 
1236   DESCRIPTION
1237     append_escaped() takes a String type variable, where it appends
1238     escaped the second argument. Only characters that require escaping
1239     will be escaped.
1240 
1241   RETURN VALUES
1242     0 Success
1243     1 Out of memory
1244 */
1245 
append_escaped(String * to_str,String * from_str)1246 bool append_escaped(String *to_str, String *from_str)
1247 {
1248   char *from, *end, c;
1249 
1250   if (to_str->mem_realloc(to_str->length() + from_str->length()))
1251     return 1;
1252 
1253   from= (char*) from_str->ptr();
1254   end= from + from_str->length();
1255   for (; from < end; from++)
1256   {
1257     c= *from;
1258     switch (c) {
1259     case '\0':
1260       c= '0';
1261       break;
1262     case '\032':
1263       c= 'Z';
1264       break;
1265     case '\\':
1266     case '\'':
1267       break;
1268     default:
1269       goto normal_character;
1270     }
1271     if (to_str->append('\\'))
1272       return 1;
1273 
1274   normal_character:
1275     if (to_str->append(c))
1276       return 1;
1277   }
1278   return 0;
1279 }
1280 
1281