sql_analyse.cpp
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:29k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /* Analyse database */
  14. /* TODO: - Check if any character fields can be of any date type
  15. **    (date, datetime, year, time, timestamp, newdate)
  16. **  - Check if any number field should be a timestamp
  17. **  - type set is out of optimization yet
  18. */
  19. #ifdef USE_PRAGMA_IMPLEMENTATION
  20. #pragma implementation // gcc: Class implementation
  21. #endif
  22. #include "mysql_priv.h"
  23. #include "procedure.h"
  24. #include "sql_analyse.h"
  25. #include <m_ctype.h>
  26. #define MAX_TREEMEM   8192
  27. #define MAX_TREE_ELEMENTS 256
  28. int sortcmp2(void* cmp_arg __attribute__((unused)),
  29.      const String *a,const String *b)
  30. {
  31.   return sortcmp(a,b,a->charset());
  32. }
  33. int compare_double2(void* cmp_arg __attribute__((unused)),
  34.     const double *s, const double *t)
  35. {
  36.   return compare_double(s,t);
  37. }
  38. int compare_longlong2(void* cmp_arg __attribute__((unused)),
  39.       const longlong *s, const longlong *t)
  40. {
  41.   return compare_longlong(s,t);
  42. }
  43. int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
  44.        const ulonglong *s, const ulonglong *t)
  45. {
  46.   return compare_ulonglong(s,t);
  47. }
  48. static bool append_escaped(String *to_str, String *from_str);
  49. Procedure *
  50. proc_analyse_init(THD *thd, ORDER *param, select_result *result,
  51.   List<Item> &field_list)
  52. {
  53.   char *proc_name = (*param->item)->name;
  54.   analyse *pc = new analyse(result);
  55.   field_info **f_info;
  56.   DBUG_ENTER("proc_analyse_init");
  57.   if (!pc)
  58.     DBUG_RETURN(0);
  59.   if (!(param = param->next))
  60.   {
  61.     pc->max_tree_elements = MAX_TREE_ELEMENTS;
  62.     pc->max_treemem = MAX_TREEMEM;
  63.   }
  64.   else if (param->next)
  65.   {
  66.     // first parameter
  67.     if ((*param->item)->type() != Item::INT_ITEM ||
  68. (*param->item)->val() < 0)
  69.     {
  70.       my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
  71.       goto err;
  72.     }
  73.     pc->max_tree_elements = (uint) (*param->item)->val_int();
  74.     param = param->next;
  75.     if (param->next)  // no third parameter possible
  76.     {
  77.       my_error(ER_WRONG_PARAMCOUNT_TO_PROCEDURE, MYF(0), proc_name);
  78.       goto err;
  79.     }
  80.     // second parameter
  81.     if ((*param->item)->type() != Item::INT_ITEM ||
  82. (*param->item)->val() < 0)
  83.     {
  84.       my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
  85.       goto err;
  86.     }
  87.     pc->max_treemem = (uint) (*param->item)->val_int();
  88.   }
  89.   else if ((*param->item)->type() != Item::INT_ITEM ||
  90.    (*param->item)->val() < 0)
  91.   {
  92.     my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
  93.     goto err;
  94.   }
  95.   // if only one parameter was given, it will be the value of max_tree_elements
  96.   else
  97.   {
  98.     pc->max_tree_elements = (uint) (*param->item)->val_int();
  99.     pc->max_treemem = MAX_TREEMEM;
  100.   }
  101.   if (!(pc->f_info=
  102.         (field_info**)sql_alloc(sizeof(field_info*)*field_list.elements)))
  103.     goto err;
  104.   pc->f_end = pc->f_info + field_list.elements;
  105.   pc->fields = field_list;
  106.   {
  107.     List_iterator_fast<Item> it(pc->fields);
  108.     f_info = pc->f_info;
  109.     Item *item;
  110.     while ((item = it++))
  111.     {
  112.       if (item->result_type() == INT_RESULT)
  113.       {
  114.         // Check if fieldtype is ulonglong
  115.         if (item->type() == Item::FIELD_ITEM &&
  116.             ((Item_field*) item)->field->type() == FIELD_TYPE_LONGLONG &&
  117.             ((Field_longlong*) ((Item_field*) item)->field)->unsigned_flag)
  118.           *f_info++ = new field_ulonglong(item, pc);
  119.         else
  120.           *f_info++ = new field_longlong(item, pc);
  121.       }
  122.       if (item->result_type() == REAL_RESULT)
  123.         *f_info++ = new field_real(item, pc);
  124.       if (item->result_type() == STRING_RESULT)
  125.         *f_info++ = new field_str(item, pc);
  126.     }
  127.   }
  128.   DBUG_RETURN(pc);
  129. err:
  130.   delete pc;
  131.   DBUG_RETURN(0);
  132. }
  133. /*
  134.   Return 1 if number, else return 0
  135.   store info about found number in info
  136.   NOTE:It is expected, that elements of 'info' are all zero!
  137. */
  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.     MySQL removes any endspaces of a string, so we must take care only of
  144.     spaces in front of a string
  145.   */
  146.   for (; str != end && my_isspace(system_charset_info, *str); str++) ;
  147.   if (str == end)
  148.     return 0;
  149.   if (*str == '-')
  150.   {
  151.     info->negative = 1;
  152.     if (++str == end || *str == '0') // converting -0 to a number
  153.       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.       return 0;      // a single number can't be zerofill
  172.     info->maybe_zerofill = 1;
  173.     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.       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.       return 1;
  185.     }
  186.     if (*str == 'e' || *str == 'E')  // number may be something like '1e+50'
  187.     {
  188.       str++;
  189.       if (*str != '-' && *str != '+')
  190. 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. return 1;
  196.       }
  197.       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.       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.       return 1;
  213.     }
  214.   }
  215.   return 0;
  216. }
  217. /*
  218.   Stores the biggest and the smallest value from current 'info'
  219.   to ev_num_info
  220.   If info contains an ulonglong number, which is bigger than
  221.   biggest positive number able to be stored in a longlong variable
  222.   and is marked as negative, function will return 0, else 1.
  223. */
  224. bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num)
  225. {
  226.   if (info->negative)
  227.   {
  228.     if (((longlong) info->ullval) < 0)
  229.       return 0; // Impossible to store as a negative number
  230.     ev_info->llval =  -(longlong) max((ulonglong) -ev_info->llval, 
  231.       info->ullval);
  232.     ev_info->min_dval = (double) -max(-ev_info->min_dval, info->dval);
  233.   }
  234.   else // ulonglong is as big as bigint in MySQL
  235.   {
  236.     if ((check_ulonglong(num, info->integers) == REAL_NUM))
  237.       return 0;
  238.     ev_info->ullval = (ulonglong) max(ev_info->ullval, info->ullval);
  239.     ev_info->max_dval =  (double) max(ev_info->max_dval, info->dval);
  240.   }
  241.   return 1;
  242. } // get_ev_num_info
  243. void free_string(String *s)
  244. {
  245.   s->free();
  246. }
  247. void field_str::add()
  248. {
  249.   char buff[MAX_FIELD_WIDTH], *ptr;
  250.   String s(buff, sizeof(buff),&my_charset_bin), *res;
  251.   ulong length;
  252.   if (!(res = item->val_str(&s)))
  253.   {
  254.     nulls++;
  255.     return;
  256.   }
  257.   if (!(length = res->length()))
  258.     empty++;
  259.   else
  260.   {
  261.     ptr = (char*) res->ptr();
  262.     if (*(ptr + (length - 1)) == ' ')
  263.       must_be_blob = 1;
  264.   }
  265.   if (can_be_still_num)
  266.   {
  267.     bzero((char*) &num_info, sizeof(num_info));
  268.     if (!test_if_number(&num_info, res->ptr(), (uint) length))
  269.       can_be_still_num = 0;
  270.     if (!found)
  271.     {
  272.       bzero((char*) &ev_num_info, sizeof(ev_num_info));
  273.       was_zero_fill = num_info.zerofill;
  274.     }
  275.     else if (num_info.zerofill != was_zero_fill && !was_maybe_zerofill)
  276.       can_be_still_num = 0;  // one more check needed, when length is counted
  277.     if (can_be_still_num)
  278.       can_be_still_num = get_ev_num_info(&ev_num_info, &num_info, res->ptr());
  279.     was_maybe_zerofill = num_info.maybe_zerofill;
  280.   }
  281.   /* Update min and max arguments */
  282.   if (!found)
  283.   {
  284.     found = 1;
  285.     min_arg.copy(*res);
  286.     max_arg.copy(*res);
  287.     min_length = max_length = length; sum=length;
  288.   }
  289.   else if (length)
  290.   {
  291.     sum += length;
  292.     if (length < min_length)
  293.       min_length = length;
  294.     if (length > max_length)
  295.       max_length = length;
  296.     if (sortcmp(res, &min_arg,item->collation.collation) < 0)
  297.       min_arg.copy(*res);
  298.     if (sortcmp(res, &max_arg,item->collation.collation) > 0)
  299.       max_arg.copy(*res);
  300.   }
  301.   if (room_in_tree)
  302.   {
  303.     if (res != &s)
  304.       s.copy(*res);
  305.     if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree
  306.     {
  307.       s.copy();        // slow, when SAFE_MALLOC is in use
  308.       if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg))
  309.       {
  310. room_in_tree = 0;      // Remove tree, out of RAM ?
  311. delete_tree(&tree);
  312.       }
  313.       else
  314.       {
  315. bzero((char*) &s, sizeof(s));  // Let tree handle free of this
  316. if ((treemem += length) > pc->max_treemem)
  317. {
  318.   room_in_tree = 0;  // Remove tree, too big tree
  319.   delete_tree(&tree);
  320. }
  321.       }
  322.     }
  323.   }
  324.   if ((num_info.zerofill && (max_length != min_length)) ||
  325.       (was_zero_fill && (max_length != min_length)))
  326.     can_be_still_num = 0; // zerofilled numbers must be of same length
  327. } // field_str::add
  328. void field_real::add()
  329. {
  330.   char buff[MAX_FIELD_WIDTH], *ptr, *end;
  331.   double num = item->val();
  332.   uint length, zero_count, decs;
  333.   TREE_ELEMENT *element;
  334.   if (item->null_value)
  335.   {
  336.     nulls++;
  337.     return;
  338.   }
  339.   if (num == 0.0)
  340.     empty++;
  341.   if ((decs = decimals()) == NOT_FIXED_DEC)
  342.   {
  343.     length= my_sprintf(buff, (buff, "%g", num));
  344.     if (rint(num) != num)
  345.       max_notzero_dec_len = 1;
  346.   }
  347.   else
  348.   {
  349. #ifdef HAVE_SNPRINTF
  350.     buff[sizeof(buff)-1]=0; // Safety
  351.     snprintf(buff, sizeof(buff)-1, "%-.*f", (int) decs, num);
  352.     length = (uint) strlen(buff);
  353. #else
  354.     length= my_sprintf(buff, (buff, "%-.*f", (int) decs, num));
  355. #endif
  356.     // We never need to check further than this
  357.     end = buff + length - 1 - decs + max_notzero_dec_len;
  358.     zero_count = 0;
  359.     for (ptr = buff + length - 1; ptr > end && *ptr == '0'; ptr--)
  360.       zero_count++;
  361.     if ((decs - zero_count > max_notzero_dec_len))
  362.       max_notzero_dec_len = decs - zero_count;
  363.   }
  364.   if (room_in_tree)
  365.   {
  366.     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
  367.     {
  368.       room_in_tree = 0;    // Remove tree, out of RAM ?
  369.       delete_tree(&tree);
  370.     }
  371.     /*
  372.       if element->count == 1, this element can be found only once from tree
  373.       if element->count == 2, or more, this element is already in tree
  374.     */
  375.     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
  376.     {
  377.       room_in_tree = 0;  // Remove tree, too many elements
  378.       delete_tree(&tree);
  379.     }
  380.   }
  381.   if (!found)
  382.   {
  383.     found = 1;
  384.     min_arg = max_arg = sum = num;
  385.     sum_sqr = num * num;
  386.     min_length = max_length = length;
  387.   }
  388.   else if (num != 0.0)
  389.   {
  390.     sum += num;
  391.     sum_sqr += num * num;
  392.     if (length < min_length)
  393.       min_length = length;
  394.     if (length > max_length)
  395.       max_length = length;
  396.     if (compare_double(&num, &min_arg) < 0)
  397.       min_arg = num;
  398.     if (compare_double(&num, &max_arg) > 0)
  399.       max_arg = num;
  400.   }
  401. } // field_real::add
  402. void field_longlong::add()
  403. {
  404.   char buff[MAX_FIELD_WIDTH];
  405.   longlong num = item->val_int();
  406.   uint length = (uint) (longlong10_to_str(num, buff, -10) - buff);
  407.   TREE_ELEMENT *element;
  408.   if (item->null_value)
  409.   {
  410.     nulls++;
  411.     return;
  412.   }
  413.   if (num == 0)
  414.     empty++;
  415.   if (room_in_tree)
  416.   {
  417.     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
  418.     {
  419.       room_in_tree = 0;    // Remove tree, out of RAM ?
  420.       delete_tree(&tree);
  421.     }
  422.     /*
  423.       if element->count == 1, this element can be found only once from tree
  424.       if element->count == 2, or more, this element is already in tree
  425.     */
  426.     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
  427.     {
  428.       room_in_tree = 0;  // Remove tree, too many elements
  429.       delete_tree(&tree);
  430.     }
  431.   }
  432.   if (!found)
  433.   {
  434.     found = 1;
  435.     min_arg = max_arg = sum = num;
  436.     sum_sqr = num * num;
  437.     min_length = max_length = length;
  438.   }
  439.   else if (num != 0)
  440.   {
  441.     sum += num;
  442.     sum_sqr += num * num;
  443.     if (length < min_length)
  444.       min_length = length;
  445.     if (length > max_length)
  446.       max_length = length;
  447.     if (compare_longlong(&num, &min_arg) < 0)
  448.       min_arg = num;
  449.     if (compare_longlong(&num, &max_arg) > 0)
  450.       max_arg = num;
  451.   }
  452. } // field_longlong::add
  453. void field_ulonglong::add()
  454. {
  455.   char buff[MAX_FIELD_WIDTH];
  456.   longlong num = item->val_int();
  457.   uint length = (uint) (longlong10_to_str(num, buff, 10) - buff);
  458.   TREE_ELEMENT *element;
  459.   if (item->null_value)
  460.   {
  461.     nulls++;
  462.     return;
  463.   }
  464.   if (num == 0)
  465.     empty++;
  466.   if (room_in_tree)
  467.   {
  468.     if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg)))
  469.     {
  470.       room_in_tree = 0;    // Remove tree, out of RAM ?
  471.       delete_tree(&tree);
  472.     }
  473.     /*
  474.       if element->count == 1, this element can be found only once from tree
  475.       if element->count == 2, or more, this element is already in tree
  476.     */
  477.     else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements)
  478.     {
  479.       room_in_tree = 0;  // Remove tree, too many elements
  480.       delete_tree(&tree);
  481.     }
  482.   }
  483.   if (!found)
  484.   {
  485.     found = 1;
  486.     min_arg = max_arg = sum = num;
  487.     sum_sqr = num * num;
  488.     min_length = max_length = length;
  489.   }
  490.   else if (num != 0)
  491.   {
  492.     sum += num;
  493.     sum_sqr += num * num;
  494.     if (length < min_length)
  495.       min_length = length;
  496.     if (length > max_length)
  497.       max_length = length;
  498.     if (compare_ulonglong((ulonglong*) &num, &min_arg) < 0)
  499.       min_arg = num;
  500.     if (compare_ulonglong((ulonglong*) &num, &max_arg) > 0)
  501.       max_arg = num;
  502.   }
  503. } // field_ulonglong::add
  504. int analyse::send_row(List<Item> &field_list __attribute__((unused)))
  505. {
  506.   field_info **f = f_info;
  507.   rows++;
  508.   for (;f != f_end; f++)
  509.   {
  510.     (*f)->add();
  511.   }
  512.   return 0;
  513. } // analyse::send_row
  514. bool analyse::end_of_records()
  515. {
  516.   field_info **f = f_info;
  517.   char buff[MAX_FIELD_WIDTH];
  518.   String *res, s_min(buff, sizeof(buff),&my_charset_bin), 
  519.  s_max(buff, sizeof(buff),&my_charset_bin),
  520.  ans(buff, sizeof(buff),&my_charset_bin);
  521.   for (; f != f_end; f++)
  522.   {
  523.     func_items[0]->set((*f)->item->full_name());
  524.     if (!(*f)->found)
  525.     {
  526.       func_items[1]->null_value = 1;
  527.       func_items[2]->null_value = 1;
  528.     }
  529.     else
  530.     {
  531.       func_items[1]->null_value = 0;
  532.       res = (*f)->get_min_arg(&s_min);
  533.       func_items[1]->set(res->ptr(), res->length(), res->charset());
  534.       func_items[2]->null_value = 0;
  535.       res = (*f)->get_max_arg(&s_max);
  536.       func_items[2]->set(res->ptr(), res->length(), res->charset());
  537.     }
  538.     func_items[3]->set((longlong) (*f)->min_length);
  539.     func_items[4]->set((longlong) (*f)->max_length);
  540.     func_items[5]->set((longlong) (*f)->empty);
  541.     func_items[6]->set((longlong) (*f)->nulls);
  542.     res = (*f)->avg(&s_max, rows);
  543.     func_items[7]->set(res->ptr(), res->length(), res->charset());
  544.     func_items[8]->null_value = 0;
  545.     res = (*f)->std(&s_max, rows);
  546.     if (!res)
  547.       func_items[8]->null_value = 1;
  548.     else
  549.       func_items[8]->set(res->ptr(), res->length(), res->charset());
  550.     /*
  551.       count the dots, quotas, etc. in (ENUM("a","b","c"...))
  552.       If tree has been removed, don't suggest ENUM.
  553.       treemem is used to measure the size of tree for strings,
  554.       tree_elements is used to count the elements
  555.       max_treemem tells how long the string starting from ENUM("... and
  556.       ending to ..") shall at maximum be. If case is about numbers,
  557.       max_tree_elements will tell the length of the above, now
  558.       every number is considered as length 1
  559.     */
  560.     if (((*f)->treemem || (*f)->tree_elements) &&
  561. (*f)->tree.elements_in_tree &&
  562. (((*f)->treemem ? max_treemem : max_tree_elements) >
  563.  (((*f)->treemem ? (*f)->treemem : (*f)->tree_elements) +
  564.    ((*f)->tree.elements_in_tree * 3 - 1 + 6))))
  565.     {
  566.       char tmp[331]; //331, because one double prec. num. can be this long
  567.       String tmp_str(tmp, sizeof(tmp),&my_charset_bin);
  568.       TREE_INFO tree_info;
  569.       tree_info.str = &tmp_str;
  570.       tree_info.found = 0;
  571.       tree_info.item = (*f)->item;
  572.       tmp_str.set("ENUM(", 5,&my_charset_bin);
  573.       tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info,
  574. left_root_right);
  575.       tmp_str.append(')');
  576.       if (!(*f)->nulls)
  577. tmp_str.append(" NOT NULL");
  578.       output_str_length = tmp_str.length();
  579.       func_items[9]->set(tmp_str.ptr(), tmp_str.length(), tmp_str.charset());
  580.       if (result->send_data(result_fields))
  581. return -1;
  582.       continue;
  583.     }
  584.     ans.length(0);
  585.     if (!(*f)->treemem && !(*f)->tree_elements)
  586.       ans.append("CHAR(0)", 7);
  587.     else if ((*f)->item->type() == Item::FIELD_ITEM)
  588.     {
  589.       switch (((Item_field*) (*f)->item)->field->real_type())
  590.       {
  591.       case FIELD_TYPE_TIMESTAMP:
  592. ans.append("TIMESTAMP", 9);
  593. break;
  594.       case FIELD_TYPE_DATETIME:
  595. ans.append("DATETIME", 8);
  596. break;
  597.       case FIELD_TYPE_DATE:
  598.       case FIELD_TYPE_NEWDATE:
  599. ans.append("DATE", 4);
  600. break;
  601.       case FIELD_TYPE_SET:
  602. ans.append("SET", 3);
  603. break;
  604.       case FIELD_TYPE_YEAR:
  605. ans.append("YEAR", 4);
  606. break;
  607.       case FIELD_TYPE_TIME:
  608. ans.append("TIME", 4);
  609. break;
  610.       case FIELD_TYPE_DECIMAL:
  611. ans.append("DECIMAL", 7);
  612. // if item is FIELD_ITEM, it _must_be_ Field_num in this case
  613. if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill)
  614.   ans.append(" ZEROFILL");
  615. break;
  616.       default:
  617. (*f)->get_opt_type(&ans, rows);
  618. break;
  619.       }
  620.     }
  621.     if (!(*f)->nulls)
  622.       ans.append(" NOT NULL");
  623.     func_items[9]->set(ans.ptr(), ans.length(), ans.charset());
  624.     if (result->send_data(result_fields))
  625.       return -1;
  626.   }
  627.   return 0;
  628. } // analyse::end_of_records
  629. void field_str::get_opt_type(String *answer, ha_rows total_rows)
  630. {
  631.   char buff[MAX_FIELD_WIDTH];
  632.   if (can_be_still_num)
  633.   {
  634.     if (num_info.is_float)
  635.       sprintf(buff, "DOUBLE");   // number was like 1e+50... TODO:
  636.     else if (num_info.decimals) // DOUBLE(%d,%d) sometime
  637.     {
  638.       if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX)
  639. sprintf(buff, "FLOAT(%d,%d)", num_info.integers, num_info.decimals);
  640.       else
  641. sprintf(buff, "DOUBLE(%d,%d)", num_info.integers, num_info.decimals);
  642.     }
  643.     else if (ev_num_info.llval >= -128 &&
  644.      ev_num_info.ullval <=
  645.      (ulonglong) (ev_num_info.llval >= 0 ? 255 : 127))
  646.       sprintf(buff, "TINYINT(%d)", num_info.integers);
  647.     else if (ev_num_info.llval >= INT_MIN16 &&
  648.      ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
  649. UINT_MAX16 : INT_MAX16))
  650.       sprintf(buff, "SMALLINT(%d)", num_info.integers);
  651.     else if (ev_num_info.llval >= INT_MIN24 &&
  652.      ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
  653. UINT_MAX24 : INT_MAX24))
  654.       sprintf(buff, "MEDIUMINT(%d)", num_info.integers);
  655.     else if (ev_num_info.llval >= INT_MIN32 &&
  656.      ev_num_info.ullval <= (ulonglong) (ev_num_info.llval >= 0 ?
  657. UINT_MAX32 : INT_MAX32))
  658.       sprintf(buff, "INT(%d)", num_info.integers);
  659.     else
  660.       sprintf(buff, "BIGINT(%d)", num_info.integers);
  661.     answer->append(buff, (uint) strlen(buff));
  662.     if (ev_num_info.llval >= 0 && ev_num_info.min_dval >= 0)
  663.       answer->append(" UNSIGNED");
  664.     if (num_info.zerofill)
  665.       answer->append(" ZEROFILL");
  666.   }
  667.   else if (max_length < 256)
  668.   {
  669.     if (must_be_blob)
  670.     {
  671.       if (item->collation.collation == &my_charset_bin)
  672. answer->append("TINYBLOB", 8);
  673.       else
  674. answer->append("TINYTEXT", 8);
  675.     }
  676.     else if ((max_length * (total_rows - nulls)) < (sum + total_rows))
  677.     {
  678.       sprintf(buff, "CHAR(%d)", (int) max_length);
  679.       answer->append(buff, (uint) strlen(buff));
  680.     }
  681.     else
  682.     {
  683.       sprintf(buff, "VARCHAR(%d)", (int) max_length);
  684.       answer->append(buff, (uint) strlen(buff));
  685.     }
  686.   }
  687.   else if (max_length < (1L << 16))
  688.   {
  689.     if (item->collation.collation == &my_charset_bin)
  690.       answer->append("BLOB", 4);
  691.     else
  692.       answer->append("TEXT", 4);
  693.   }
  694.   else if (max_length < (1L << 24))
  695.   {
  696.     if (item->collation.collation == &my_charset_bin)
  697.       answer->append("MEDIUMBLOB", 10);
  698.     else
  699.       answer->append("MEDIUMTEXT", 10);
  700.   }
  701.   else
  702.   {
  703.     if (item->collation.collation == &my_charset_bin)
  704.       answer->append("LONGBLOB", 8);
  705.     else
  706.       answer->append("LONGTEXT", 8);
  707.   }
  708. } // field_str::get_opt_type
  709. void field_real::get_opt_type(String *answer,
  710.       ha_rows total_rows __attribute__((unused)))
  711. {
  712.   char buff[MAX_FIELD_WIDTH];
  713.   if (!max_notzero_dec_len)
  714.   {
  715.     int len= (int) max_length - ((item->decimals == NOT_FIXED_DEC) ?
  716.  0 : (item->decimals + 1));
  717.     if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
  718.       sprintf(buff, "TINYINT(%d)", len);
  719.     else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
  720.  UINT_MAX16 : INT_MAX16))
  721.       sprintf(buff, "SMALLINT(%d)", len);
  722.     else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
  723.  UINT_MAX24 : INT_MAX24))
  724.       sprintf(buff, "MEDIUMINT(%d)", len);
  725.     else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
  726.  UINT_MAX32 : INT_MAX32))
  727.       sprintf(buff, "INT(%d)", len);
  728.     else
  729.       sprintf(buff, "BIGINT(%d)", len);
  730.     answer->append(buff, (uint) strlen(buff));
  731.     if (min_arg >= 0)
  732.       answer->append(" UNSIGNED");
  733.   }
  734.   else if (item->decimals == NOT_FIXED_DEC)
  735.   {
  736.     if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
  737.       answer->append("FLOAT", 5);      
  738.     else
  739.       answer->append("DOUBLE", 6);
  740.   }
  741.   else
  742.   {
  743.     if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX)
  744.       sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1),
  745.       max_notzero_dec_len);
  746.     else
  747.       sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1),
  748.       max_notzero_dec_len);
  749.     answer->append(buff, (uint) strlen(buff));
  750.   }
  751.   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
  752.   if (item->type() == Item::FIELD_ITEM &&
  753.       // a single number shouldn't be zerofill
  754.       (max_length - (item->decimals + 1)) != 1 &&
  755.       ((Field_num*) ((Item_field*) item)->field)->zerofill)
  756.     answer->append(" ZEROFILL");
  757. } // field_real::get_opt_type
  758. void field_longlong::get_opt_type(String *answer,
  759.   ha_rows total_rows __attribute__((unused)))
  760. {
  761.   char buff[MAX_FIELD_WIDTH];
  762.   if (min_arg >= -128 && max_arg <= (min_arg >= 0 ? 255 : 127))
  763.     sprintf(buff, "TINYINT(%d)", (int) max_length);
  764.   else if (min_arg >= INT_MIN16 && max_arg <= (min_arg >= 0 ?
  765.        UINT_MAX16 : INT_MAX16))
  766.     sprintf(buff, "SMALLINT(%d)", (int) max_length);
  767.   else if (min_arg >= INT_MIN24 && max_arg <= (min_arg >= 0 ?
  768.        UINT_MAX24 : INT_MAX24))
  769.     sprintf(buff, "MEDIUMINT(%d)", (int) max_length);
  770.   else if (min_arg >= INT_MIN32 && max_arg <= (min_arg >= 0 ?
  771.        UINT_MAX32 : INT_MAX32))
  772.     sprintf(buff, "INT(%d)", (int) max_length);
  773.   else
  774.     sprintf(buff, "BIGINT(%d)", (int) max_length);
  775.   answer->append(buff, (uint) strlen(buff));
  776.   if (min_arg >= 0)
  777.     answer->append(" UNSIGNED");
  778.   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
  779.   if ((item->type() == Item::FIELD_ITEM) &&
  780.       // a single number shouldn't be zerofill
  781.       max_length != 1 &&
  782.       ((Field_num*) ((Item_field*) item)->field)->zerofill)
  783.     answer->append(" ZEROFILL");
  784. } // field_longlong::get_opt_type
  785. void field_ulonglong::get_opt_type(String *answer,
  786.    ha_rows total_rows __attribute__((unused)))
  787. {
  788.   char buff[MAX_FIELD_WIDTH];
  789.   if (max_arg < 256)
  790.     sprintf(buff, "TINYINT(%d) UNSIGNED", (int) max_length);
  791.    else if (max_arg <= ((2 * INT_MAX16) + 1))
  792.      sprintf(buff, "SMALLINT(%d) UNSIGNED", (int) max_length);
  793.   else if (max_arg <= ((2 * INT_MAX24) + 1))
  794.     sprintf(buff, "MEDIUMINT(%d) UNSIGNED", (int) max_length);
  795.   else if (max_arg < (((ulonglong) 1) << 32))
  796.     sprintf(buff, "INT(%d) UNSIGNED", (int) max_length);
  797.   else
  798.     sprintf(buff, "BIGINT(%d) UNSIGNED", (int) max_length);
  799.   // if item is FIELD_ITEM, it _must_be_ Field_num in this class
  800.   answer->append(buff, (uint) strlen(buff));
  801.   if (item->type() == Item::FIELD_ITEM &&
  802.       // a single number shouldn't be zerofill
  803.       max_length != 1 &&
  804.       ((Field_num*) ((Item_field*) item)->field)->zerofill)
  805.     answer->append(" ZEROFILL");
  806. } //field_ulonglong::get_opt_type
  807. int collect_string(String *element,
  808.    element_count count __attribute__((unused)),
  809.    TREE_INFO *info)
  810. {
  811.   if (info->found)
  812.     info->str->append(',');
  813.   else
  814.     info->found = 1;
  815.   info->str->append(''');
  816.   if (append_escaped(info->str, element))
  817.     return 1;
  818.   info->str->append(''');
  819.   return 0;
  820. } // collect_string
  821. int collect_real(double *element, element_count count __attribute__((unused)),
  822.  TREE_INFO *info)
  823. {
  824.   char buff[MAX_FIELD_WIDTH];
  825.   String s(buff, sizeof(buff),current_thd->charset());
  826.   if (info->found)
  827.     info->str->append(',');
  828.   else
  829.     info->found = 1;
  830.   info->str->append(''');
  831.   s.set(*element, info->item->decimals, current_thd->charset());
  832.   info->str->append(s);
  833.   info->str->append(''');
  834.   return 0;
  835. } // collect_real
  836. int collect_longlong(longlong *element,
  837.      element_count count __attribute__((unused)),
  838.      TREE_INFO *info)
  839. {
  840.   char buff[MAX_FIELD_WIDTH];
  841.   String s(buff, sizeof(buff),&my_charset_bin);
  842.   if (info->found)
  843.     info->str->append(',');
  844.   else
  845.     info->found = 1;
  846.   info->str->append(''');
  847.   s.set(*element, current_thd->charset());
  848.   info->str->append(s);
  849.   info->str->append(''');
  850.   return 0;
  851. } // collect_longlong
  852. int collect_ulonglong(ulonglong *element,
  853.       element_count count __attribute__((unused)),
  854.       TREE_INFO *info)
  855. {
  856.   char buff[MAX_FIELD_WIDTH];
  857.   String s(buff, sizeof(buff),&my_charset_bin);
  858.   if (info->found)
  859.     info->str->append(',');
  860.   else
  861.     info->found = 1;
  862.   info->str->append(''');
  863.   s.set(*element, current_thd->charset());
  864.   info->str->append(s);
  865.   info->str->append(''');
  866.   return 0;
  867. } // collect_ulonglong
  868. bool analyse::change_columns(List<Item> &field_list)
  869. {
  870.   field_list.empty();
  871.   func_items[0] = new Item_proc_string("Field_name", 255);
  872.   func_items[1] = new Item_proc_string("Min_value", 255);
  873.   func_items[1]->maybe_null = 1;
  874.   func_items[2] = new Item_proc_string("Max_value", 255);
  875.   func_items[2]->maybe_null = 1;
  876.   func_items[3] = new Item_proc_int("Min_length");
  877.   func_items[4] = new Item_proc_int("Max_length");
  878.   func_items[5] = new Item_proc_int("Empties_or_zeros");
  879.   func_items[6] = new Item_proc_int("Nulls");
  880.   func_items[7] = new Item_proc_string("Avg_value_or_avg_length", 255);
  881.   func_items[8] = new Item_proc_string("Std", 255);
  882.   func_items[8]->maybe_null = 1;
  883.   func_items[9] = new Item_proc_string("Optimal_fieldtype",
  884.        max(64, output_str_length));
  885.   for (uint i = 0; i < array_elements(func_items); i++)
  886.     field_list.push_back(func_items[i]);
  887.   result_fields = field_list;
  888.   return 0;
  889. } // analyse::change_columns
  890. int compare_double(const double *s, const double *t)
  891. {
  892.   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
  893. } /* compare_double */
  894. int compare_longlong(const longlong *s, const longlong *t)
  895. {
  896.   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
  897. } /* compare_longlong */
  898.  int compare_ulonglong(const ulonglong *s, const ulonglong *t)
  899. {
  900.   return ((*s < *t) ? -1 : *s > *t ? 1 : 0);
  901. } /* compare_ulonglong */
  902. uint check_ulonglong(const char *str, uint length)
  903. {
  904.   const char *long_str = "2147483647", *ulonglong_str = "18446744073709551615";
  905.   const uint long_len = 10, ulonglong_len = 20;
  906.   while (*str == '0' && length)
  907.   {
  908.     str++; length--;
  909.   }
  910.   if (length < long_len)
  911.     return NUM;
  912.   uint smaller, bigger;
  913.   const char *cmp;
  914.   if (length == long_len)
  915.   {
  916.     cmp = long_str;
  917.     smaller = NUM;
  918.     bigger = LONG_NUM;
  919.   }
  920.   else if (length > ulonglong_len)
  921.     return REAL_NUM;
  922.   else
  923.   {
  924.     cmp = ulonglong_str;
  925.     smaller = LONG_NUM;
  926.     bigger = REAL_NUM;
  927.   }
  928.   while (*cmp && *cmp++ == *str++) ;
  929.   return ((uchar) str[-1] <= (uchar) cmp[-1]) ? smaller : bigger;
  930. } /* check_ulonlong */
  931. /*
  932.   Quote special characters in a string.
  933.   SYNOPSIS
  934.    append_escaped(to_str, from_str)
  935.    to_str (in) A pointer to a String.
  936.    from_str (to) A pointer to an allocated string
  937.   DESCRIPTION
  938.     append_escaped() takes a String type variable, where it appends
  939.     escaped the second argument. Only characters that require escaping
  940.     will be escaped.
  941.   RETURN VALUES
  942.     0 Success
  943.     1 Out of memory
  944. */
  945. static bool append_escaped(String *to_str, String *from_str)
  946. {
  947.   char *from, *end, c;
  948.   if (to_str->realloc(to_str->length() + from_str->length()))
  949.     return 1;
  950.   from= (char*) from_str->ptr();
  951.   end= from + from_str->length();
  952.   for (; from < end; from++)
  953.   {
  954.     c= *from;
  955.     switch (c) {
  956.     case '':
  957.       c= '0';
  958.       break;
  959.     case '32':
  960.       c= 'Z';
  961.       break;
  962.     case '\':
  963.     case ''':
  964.       break;
  965.     default:
  966.       goto normal_character;
  967.     }
  968.     if (to_str->append('\'))
  969.       return 1;
  970.   normal_character:
  971.     if (to_str->append(c))
  972.       return 1;
  973.   }
  974.   return 0;
  975. }