My Project
sql_analyse.h
00001 #ifndef SQL_ANALYSE_INCLUDED
00002 #define SQL_ANALYSE_INCLUDED
00003 
00004 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; version 2 of the License.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software Foundation,
00017    51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
00018 
00019 
00020 /* Analyse database */
00021 
00022 #include "procedure.h"                          /* Procedure */
00023 
00024 #define my_thd_charset  default_charset_info
00025 
00026 #define DEC_IN_AVG 4
00027 
00028 typedef struct st_number_info
00029 {
00030   // if zerofill is true, the number must be zerofill, or string
00031   bool      negative, is_float, zerofill, maybe_zerofill;
00032   int8      integers;
00033   int8      decimals;
00034   double    dval;
00035   ulonglong ullval;
00036 } NUM_INFO;
00037 
00038 typedef struct st_extreme_value_number_info
00039 {
00040   ulonglong ullval;
00041   longlong  llval;
00042   double    max_dval, min_dval;
00043 } EV_NUM_INFO;
00044 
00045 typedef struct st_tree_info
00046 {
00047   bool   found;
00048   String *str;
00049   Item   *item;
00050 } TREE_INFO;
00051 
00052 uint check_ulonglong(const char *str, uint length);
00053 bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num);
00054 bool test_if_number(NUM_INFO *info, const char *str, uint str_len);
00055 int compare_double(const double *s, const double *t);
00056 int compare_double2(void* cmp_arg __attribute__((unused)),
00057                     const double *s, const double *t);
00058 int compare_longlong(const longlong *s, const longlong *t);
00059 int compare_longlong2(void* cmp_arg __attribute__((unused)),
00060                       const longlong *s, const longlong *t);
00061 int compare_ulonglong(const ulonglong *s, const ulonglong *t);
00062 int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
00063                        const ulonglong *s, const ulonglong *t);
00064 int compare_decimal2(int* len, const char *s, const char *t);
00065 void free_string(String*);
00066 class select_analyse;
00067 
00068 class field_info :public Sql_alloc
00069 {
00070 protected:
00071   ulong   treemem, tree_elements, empty, nulls, min_length, max_length;
00072   uint    room_in_tree;
00073   my_bool found;
00074   TREE    tree;
00075   Item    *item;
00076   select_analyse *pc;
00077 
00078 public:
00079   field_info(Item* a, select_analyse* b)
00080   : treemem(0), tree_elements(0), empty(0),
00081     nulls(0), min_length(0), max_length(0), room_in_tree(1),
00082     found(0),item(a), pc(b) {};
00083 
00084   virtual ~field_info() { delete_tree(&tree); }
00085   virtual void   add() = 0;
00086   virtual void   get_opt_type(String*, ha_rows) = 0;
00087   virtual String *get_min_arg(String *) = 0;
00088   virtual String *get_max_arg(String *) = 0;
00089   virtual String *avg(String*, ha_rows) = 0;
00090   virtual String *std(String*, ha_rows) = 0;
00091   virtual tree_walk_action collect_enum() = 0;
00092   virtual uint decimals() { return 0; }
00093   friend  class select_analyse;
00094 };
00095 
00096 
00097 int collect_string(String *element, element_count count,
00098                    TREE_INFO *info);
00099 
00100 int sortcmp2(void* cmp_arg __attribute__((unused)),
00101              const String *a,const String *b);
00102 
00103 class field_str :public field_info
00104 {
00105   String      min_arg, max_arg;
00106   ulonglong   sum;
00107   bool        must_be_blob, was_zero_fill, was_maybe_zerofill,
00108               can_be_still_num;
00109   NUM_INFO    num_info;
00110   EV_NUM_INFO ev_num_info;
00111 
00112 public:
00113   field_str(Item* a, select_analyse* b) :field_info(a,b), 
00114     min_arg("",default_charset_info),
00115     max_arg("",default_charset_info), sum(0),
00116     must_be_blob(0), was_zero_fill(0),
00117     was_maybe_zerofill(0), can_be_still_num(1)
00118     { init_tree(&tree, 0, 0, sizeof(String), (qsort_cmp2) sortcmp2,
00119                 0, (tree_element_free) free_string, NULL); };
00120 
00121   void   add();
00122   void   get_opt_type(String*, ha_rows);
00123   String *get_min_arg(String *not_used __attribute__((unused)))
00124   { return &min_arg; }
00125   String *get_max_arg(String *not_used __attribute__((unused)))
00126   { return &max_arg; }
00127   String *avg(String *s, ha_rows rows)
00128   {
00129     if (!(rows - nulls))
00130       s->set_real((double) 0.0, 1,my_thd_charset);
00131     else
00132       s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
00133              DEC_IN_AVG,my_thd_charset);
00134     return s;
00135   }
00136   friend int collect_string(String *element, element_count count,
00137                             TREE_INFO *info);
00138   tree_walk_action collect_enum()
00139   { return (tree_walk_action) collect_string; }
00140   String *std(String *s __attribute__((unused)),
00141               ha_rows rows __attribute__((unused)))
00142   { return (String*) 0; }
00143 };
00144 
00145 
00146 int collect_decimal(uchar *element, element_count count,
00147                     TREE_INFO *info);
00148 
00149 class field_decimal :public field_info
00150 {
00151   my_decimal min_arg, max_arg;
00152   my_decimal sum[2], sum_sqr[2];
00153   int cur_sum;
00154   int bin_size;
00155 public:
00156   field_decimal(Item* a, select_analyse* b) :field_info(a,b)
00157   {
00158     bin_size= my_decimal_get_binary_size(a->max_length, a->decimals);
00159     init_tree(&tree, 0, 0, bin_size, (qsort_cmp2)compare_decimal2,
00160               0, 0, (void *)&bin_size);
00161   };
00162 
00163   void   add();
00164   void   get_opt_type(String*, ha_rows);
00165   String *get_min_arg(String *);
00166   String *get_max_arg(String *);
00167   String *avg(String *s, ha_rows rows);
00168   friend int collect_decimal(uchar *element, element_count count,
00169                              TREE_INFO *info);
00170   tree_walk_action collect_enum()
00171   { return (tree_walk_action) collect_decimal; }
00172   String *std(String *s, ha_rows rows);
00173 };
00174 
00175 
00176 int collect_real(double *element, element_count count, TREE_INFO *info);
00177 
00178 class field_real: public field_info
00179 {
00180   double min_arg, max_arg;
00181   double sum, sum_sqr;
00182   uint   max_notzero_dec_len;
00183 
00184 public:
00185   field_real(Item* a, select_analyse* b) :field_info(a,b),
00186     min_arg(0), max_arg(0),  sum(0), sum_sqr(0), max_notzero_dec_len(0)
00187     { init_tree(&tree, 0, 0, sizeof(double),
00188                 (qsort_cmp2) compare_double2, 0, NULL, NULL); }
00189 
00190   void   add();
00191   void   get_opt_type(String*, ha_rows);
00192   String *get_min_arg(String *s)
00193   {
00194     s->set_real(min_arg, item->decimals, my_thd_charset);
00195     return s;
00196   }
00197   String *get_max_arg(String *s)
00198   {
00199     s->set_real(max_arg, item->decimals, my_thd_charset);
00200     return s;
00201   }
00202   String *avg(String *s, ha_rows rows)
00203   {
00204     if (!(rows - nulls))
00205       s->set_real((double) 0.0, 1,my_thd_charset);
00206     else
00207       s->set_real(((double)sum / (double) (rows - nulls)), item->decimals,my_thd_charset);
00208     return s;
00209   }
00210   String *std(String *s, ha_rows rows)
00211   {
00212     double tmp = ulonglong2double(rows);
00213     if (!(tmp - nulls))
00214       s->set_real((double) 0.0, 1,my_thd_charset);
00215     else
00216     {
00217       double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
00218                      (tmp - nulls));
00219       s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals,my_thd_charset);
00220     }
00221     return s;
00222   }
00223   uint   decimals() { return item->decimals; }
00224   friend int collect_real(double *element, element_count count,
00225                           TREE_INFO *info);
00226   tree_walk_action collect_enum()
00227   { return (tree_walk_action) collect_real;}
00228 };
00229 
00230 int collect_longlong(longlong *element, element_count count,
00231                      TREE_INFO *info);
00232 
00233 class field_longlong: public field_info
00234 {
00235   longlong min_arg, max_arg;
00236   longlong sum, sum_sqr;
00237 
00238 public:
00239   field_longlong(Item* a, select_analyse* b) :field_info(a,b), 
00240     min_arg(0), max_arg(0), sum(0), sum_sqr(0)
00241     { init_tree(&tree, 0, 0, sizeof(longlong),
00242                 (qsort_cmp2) compare_longlong2, 0, NULL, NULL); }
00243 
00244   void   add();
00245   void   get_opt_type(String*, ha_rows);
00246   String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
00247   String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
00248   String *avg(String *s, ha_rows rows)
00249   {
00250     if (!(rows - nulls))
00251       s->set_real((double) 0.0, 1,my_thd_charset);
00252     else
00253       s->set_real(((double) sum / (double) (rows - nulls)), DEC_IN_AVG,my_thd_charset);
00254     return s;
00255   }
00256   String *std(String *s, ha_rows rows)
00257   {
00258     double tmp = ulonglong2double(rows);
00259     if (!(tmp - nulls))
00260       s->set_real((double) 0.0, 1,my_thd_charset);
00261     else
00262     {
00263       double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
00264                     (tmp - nulls));
00265       s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
00266     }
00267     return s;
00268   }
00269   friend int collect_longlong(longlong *element, element_count count,
00270                               TREE_INFO *info);
00271   tree_walk_action collect_enum()
00272   { return (tree_walk_action) collect_longlong;}
00273 };
00274 
00275 int collect_ulonglong(ulonglong *element, element_count count,
00276                       TREE_INFO *info);
00277 
00278 class field_ulonglong: public field_info
00279 {
00280   ulonglong min_arg, max_arg;
00281   ulonglong sum, sum_sqr;
00282 
00283 public:
00284   field_ulonglong(Item* a, select_analyse * b) :field_info(a,b),
00285     min_arg(0), max_arg(0), sum(0),sum_sqr(0)
00286     { init_tree(&tree, 0, 0, sizeof(ulonglong),
00287                 (qsort_cmp2) compare_ulonglong2, 0, NULL, NULL); }
00288   void   add();
00289   void   get_opt_type(String*, ha_rows);
00290   String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
00291   String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
00292   String *avg(String *s, ha_rows rows)
00293   {
00294     if (!(rows - nulls))
00295       s->set_real((double) 0.0, 1,my_thd_charset);
00296     else
00297       s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
00298              DEC_IN_AVG,my_thd_charset);
00299     return s;
00300   }
00301   String *std(String *s, ha_rows rows)
00302   {
00303     double tmp = ulonglong2double(rows);
00304     if (!(tmp - nulls))
00305       s->set_real((double) 0.0, 1,my_thd_charset);
00306     else
00307     {
00308       double tmp2 = ((ulonglong2double(sum_sqr) - 
00309                      ulonglong2double(sum * sum) / (tmp - nulls)) /
00310                      (tmp - nulls));
00311       s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
00312     }
00313     return s;
00314   }
00315   friend int collect_ulonglong(ulonglong *element, element_count count,
00316                                TREE_INFO *info);
00317   tree_walk_action collect_enum()
00318   { return (tree_walk_action) collect_ulonglong; }
00319 };
00320 
00321 
00326 class select_analyse : public select_send
00327 {
00328   select_result *result; //< real output stream
00329   
00330   Item_proc    *func_items[10]; //< items for output metadata and column data
00331   List<Item>   result_fields; //< same as func_items but capable for send_data()
00332   field_info   **f_info, **f_end; //< bounds for column data accumulator array
00333   
00334   ha_rows      rows; //< counter of original SELECT query output rows
00335   uint         output_str_length; //< max.width for the Optimal_fieldtype column
00336 
00337 public:
00338   const uint max_tree_elements; //< maximum number of distinct values per column
00339   const uint max_treemem; //< maximum amount of memory to allocate per column
00340 
00341 public:
00342   select_analyse(select_result *result, const Proc_analyse_params *params)
00343   : result(result), f_info(NULL), f_end(NULL), rows(0), output_str_length(0),
00344     max_tree_elements(params->max_tree_elements),
00345     max_treemem(params->max_treemem)
00346   {}
00347 
00348   ~select_analyse() { cleanup(); }
00349 
00350   virtual void cleanup();
00351   virtual uint field_count(List<Item> &) const
00352   { return array_elements(func_items); }
00353   virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
00354   { return result->prepare(list, u); }
00355   virtual bool send_result_set_metadata(List<Item> &fields, uint flag);
00356   virtual bool send_data(List<Item> &items);
00357   virtual bool send_eof();
00358   virtual void abort_result_set();
00359 
00360 private:
00361   bool init(List<Item> &field_list);
00362   bool change_columns();
00363 };
00364 
00365 bool append_escaped(String *to_str, String *from_str);
00366 
00367 #endif /* SQL_ANALYSE_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines