sql_analyse.cc
Upload User: tsgydb
Upload Date: 2007-04-14
Package Size: 10674k
Code Size: 27k
Category:

MySQL

Development Platform:

Visual C++

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