home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / sql / sql_analyse.cpp < prev    next >
C/C++ Source or Header  |  2000-08-31  |  27KB  |  988 lines

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