MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_analyse.h
1 #ifndef SQL_ANALYSE_INCLUDED
2 #define SQL_ANALYSE_INCLUDED
3 
4 /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; version 2 of the License.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software Foundation,
17  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
18 
19 
20 /* Analyse database */
21 
22 #include "procedure.h" /* Procedure */
23 
24 #define my_thd_charset default_charset_info
25 
26 #define DEC_IN_AVG 4
27 
28 typedef struct st_number_info
29 {
30  // if zerofill is true, the number must be zerofill, or string
31  bool negative, is_float, zerofill, maybe_zerofill;
32  int8 integers;
33  int8 decimals;
34  double dval;
35  ulonglong ullval;
36 } NUM_INFO;
37 
39 {
40  ulonglong ullval;
41  longlong llval;
42  double max_dval, min_dval;
43 } EV_NUM_INFO;
44 
45 typedef struct st_tree_info
46 {
47  bool found;
48  String *str;
49  Item *item;
50 } TREE_INFO;
51 
52 uint check_ulonglong(const char *str, uint length);
53 bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num);
54 bool test_if_number(NUM_INFO *info, const char *str, uint str_len);
55 int compare_double(const double *s, const double *t);
56 int compare_double2(void* cmp_arg __attribute__((unused)),
57  const double *s, const double *t);
58 int compare_longlong(const longlong *s, const longlong *t);
59 int compare_longlong2(void* cmp_arg __attribute__((unused)),
60  const longlong *s, const longlong *t);
61 int compare_ulonglong(const ulonglong *s, const ulonglong *t);
62 int compare_ulonglong2(void* cmp_arg __attribute__((unused)),
63  const ulonglong *s, const ulonglong *t);
64 int compare_decimal2(int* len, const char *s, const char *t);
65 void free_string(String*);
66 class select_analyse;
67 
68 class field_info :public Sql_alloc
69 {
70 protected:
71  ulong treemem, tree_elements, empty, nulls, min_length, max_length;
72  uint room_in_tree;
73  my_bool found;
74  TREE tree;
75  Item *item;
76  select_analyse *pc;
77 
78 public:
80  : treemem(0), tree_elements(0), empty(0),
81  nulls(0), min_length(0), max_length(0), room_in_tree(1),
82  found(0),item(a), pc(b) {};
83 
84  virtual ~field_info() { delete_tree(&tree); }
85  virtual void add() = 0;
86  virtual void get_opt_type(String*, ha_rows) = 0;
87  virtual String *get_min_arg(String *) = 0;
88  virtual String *get_max_arg(String *) = 0;
89  virtual String *avg(String*, ha_rows) = 0;
90  virtual String *std(String*, ha_rows) = 0;
91  virtual tree_walk_action collect_enum() = 0;
92  virtual uint decimals() { return 0; }
93  friend class select_analyse;
94 };
95 
96 
97 int collect_string(String *element, element_count count,
98  TREE_INFO *info);
99 
100 int sortcmp2(void* cmp_arg __attribute__((unused)),
101  const String *a,const String *b);
102 
103 class field_str :public field_info
104 {
105  String min_arg, max_arg;
106  ulonglong sum;
107  bool must_be_blob, was_zero_fill, was_maybe_zerofill,
108  can_be_still_num;
109  NUM_INFO num_info;
110  EV_NUM_INFO ev_num_info;
111 
112 public:
113  field_str(Item* a, select_analyse* b) :field_info(a,b),
114  min_arg("",default_charset_info),
115  max_arg("",default_charset_info), sum(0),
116  must_be_blob(0), was_zero_fill(0),
117  was_maybe_zerofill(0), can_be_still_num(1)
118  { init_tree(&tree, 0, 0, sizeof(String), (qsort_cmp2) sortcmp2,
119  0, (tree_element_free) free_string, NULL); };
120 
121  void add();
122  void get_opt_type(String*, ha_rows);
123  String *get_min_arg(String *not_used __attribute__((unused)))
124  { return &min_arg; }
125  String *get_max_arg(String *not_used __attribute__((unused)))
126  { return &max_arg; }
127  String *avg(String *s, ha_rows rows)
128  {
129  if (!(rows - nulls))
130  s->set_real((double) 0.0, 1,my_thd_charset);
131  else
132  s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
133  DEC_IN_AVG,my_thd_charset);
134  return s;
135  }
136  friend int collect_string(String *element, element_count count,
137  TREE_INFO *info);
138  tree_walk_action collect_enum()
139  { return (tree_walk_action) collect_string; }
140  String *std(String *s __attribute__((unused)),
141  ha_rows rows __attribute__((unused)))
142  { return (String*) 0; }
143 };
144 
145 
146 int collect_decimal(uchar *element, element_count count,
147  TREE_INFO *info);
148 
150 {
151  my_decimal min_arg, max_arg;
152  my_decimal sum[2], sum_sqr[2];
153  int cur_sum;
154  int bin_size;
155 public:
157  {
158  bin_size= my_decimal_get_binary_size(a->max_length, a->decimals);
159  init_tree(&tree, 0, 0, bin_size, (qsort_cmp2)compare_decimal2,
160  0, 0, (void *)&bin_size);
161  };
162 
163  void add();
164  void get_opt_type(String*, ha_rows);
165  String *get_min_arg(String *);
166  String *get_max_arg(String *);
167  String *avg(String *s, ha_rows rows);
168  friend int collect_decimal(uchar *element, element_count count,
169  TREE_INFO *info);
170  tree_walk_action collect_enum()
171  { return (tree_walk_action) collect_decimal; }
172  String *std(String *s, ha_rows rows);
173 };
174 
175 
176 int collect_real(double *element, element_count count, TREE_INFO *info);
177 
178 class field_real: public field_info
179 {
180  double min_arg, max_arg;
181  double sum, sum_sqr;
182  uint max_notzero_dec_len;
183 
184 public:
186  min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0)
187  { init_tree(&tree, 0, 0, sizeof(double),
188  (qsort_cmp2) compare_double2, 0, NULL, NULL); }
189 
190  void add();
191  void get_opt_type(String*, ha_rows);
192  String *get_min_arg(String *s)
193  {
194  s->set_real(min_arg, item->decimals, my_thd_charset);
195  return s;
196  }
197  String *get_max_arg(String *s)
198  {
199  s->set_real(max_arg, item->decimals, my_thd_charset);
200  return s;
201  }
202  String *avg(String *s, ha_rows rows)
203  {
204  if (!(rows - nulls))
205  s->set_real((double) 0.0, 1,my_thd_charset);
206  else
207  s->set_real(((double)sum / (double) (rows - nulls)), item->decimals,my_thd_charset);
208  return s;
209  }
210  String *std(String *s, ha_rows rows)
211  {
212  double tmp = ulonglong2double(rows);
213  if (!(tmp - nulls))
214  s->set_real((double) 0.0, 1,my_thd_charset);
215  else
216  {
217  double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
218  (tmp - nulls));
219  s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals,my_thd_charset);
220  }
221  return s;
222  }
223  uint decimals() { return item->decimals; }
224  friend int collect_real(double *element, element_count count,
225  TREE_INFO *info);
226  tree_walk_action collect_enum()
227  { return (tree_walk_action) collect_real;}
228 };
229 
230 int collect_longlong(longlong *element, element_count count,
231  TREE_INFO *info);
232 
234 {
235  longlong min_arg, max_arg;
236  longlong sum, sum_sqr;
237 
238 public:
240  min_arg(0), max_arg(0), sum(0), sum_sqr(0)
241  { init_tree(&tree, 0, 0, sizeof(longlong),
242  (qsort_cmp2) compare_longlong2, 0, NULL, NULL); }
243 
244  void add();
245  void get_opt_type(String*, ha_rows);
246  String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
247  String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
248  String *avg(String *s, ha_rows rows)
249  {
250  if (!(rows - nulls))
251  s->set_real((double) 0.0, 1,my_thd_charset);
252  else
253  s->set_real(((double) sum / (double) (rows - nulls)), DEC_IN_AVG,my_thd_charset);
254  return s;
255  }
256  String *std(String *s, ha_rows rows)
257  {
258  double tmp = ulonglong2double(rows);
259  if (!(tmp - nulls))
260  s->set_real((double) 0.0, 1,my_thd_charset);
261  else
262  {
263  double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
264  (tmp - nulls));
265  s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
266  }
267  return s;
268  }
269  friend int collect_longlong(longlong *element, element_count count,
270  TREE_INFO *info);
271  tree_walk_action collect_enum()
272  { return (tree_walk_action) collect_longlong;}
273 };
274 
275 int collect_ulonglong(ulonglong *element, element_count count,
276  TREE_INFO *info);
277 
279 {
280  ulonglong min_arg, max_arg;
281  ulonglong sum, sum_sqr;
282 
283 public:
285  min_arg(0), max_arg(0), sum(0),sum_sqr(0)
286  { init_tree(&tree, 0, 0, sizeof(ulonglong),
287  (qsort_cmp2) compare_ulonglong2, 0, NULL, NULL); }
288  void add();
289  void get_opt_type(String*, ha_rows);
290  String *get_min_arg(String *s) { s->set(min_arg,my_thd_charset); return s; }
291  String *get_max_arg(String *s) { s->set(max_arg,my_thd_charset); return s; }
292  String *avg(String *s, ha_rows rows)
293  {
294  if (!(rows - nulls))
295  s->set_real((double) 0.0, 1,my_thd_charset);
296  else
297  s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
298  DEC_IN_AVG,my_thd_charset);
299  return s;
300  }
301  String *std(String *s, ha_rows rows)
302  {
303  double tmp = ulonglong2double(rows);
304  if (!(tmp - nulls))
305  s->set_real((double) 0.0, 1,my_thd_charset);
306  else
307  {
308  double tmp2 = ((ulonglong2double(sum_sqr) -
309  ulonglong2double(sum * sum) / (tmp - nulls)) /
310  (tmp - nulls));
311  s->set_real(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG,my_thd_charset);
312  }
313  return s;
314  }
315  friend int collect_ulonglong(ulonglong *element, element_count count,
316  TREE_INFO *info);
317  tree_walk_action collect_enum()
318  { return (tree_walk_action) collect_ulonglong; }
319 };
320 
321 
326 class select_analyse : public select_send
327 {
328  select_result *result; //< real output stream
329 
330  Item_proc *func_items[10]; //< items for output metadata and column data
331  List<Item> result_fields; //< same as func_items but capable for send_data()
332  field_info **f_info, **f_end; //< bounds for column data accumulator array
333 
334  ha_rows rows; //< counter of original SELECT query output rows
335  uint output_str_length; //< max.width for the Optimal_fieldtype column
336 
337 public:
338  const uint max_tree_elements; //< maximum number of distinct values per column
339  const uint max_treemem; //< maximum amount of memory to allocate per column
340 
341 public:
342  select_analyse(select_result *result, const Proc_analyse_params *params)
343  : result(result), f_info(NULL), f_end(NULL), rows(0), output_str_length(0),
344  max_tree_elements(params->max_tree_elements),
345  max_treemem(params->max_treemem)
346  {}
347 
348  ~select_analyse() { cleanup(); }
349 
350  virtual void cleanup();
351  virtual uint field_count(List<Item> &) const
352  { return array_elements(func_items); }
353  virtual int prepare(List<Item> &list, SELECT_LEX_UNIT *u)
354  { return result->prepare(list, u); }
355  virtual bool send_result_set_metadata(List<Item> &fields, uint flag);
356  virtual bool send_data(List<Item> &items);
357  virtual bool send_eof();
358  virtual void abort_result_set();
359 
360 private:
361  bool init(List<Item> &field_list);
362  bool change_columns();
363 };
364 
365 bool append_escaped(String *to_str, String *from_str);
366 
367 #endif /* SQL_ANALYSE_INCLUDED */