My Project
|
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 */