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