1
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
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.
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.
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 */
18
/* Analyse database */
21
#pragma interface /* gcc class implementation */
28
typedef struct st_number_info
30
// if zerofill is true, the number must be zerofill, or string
31
bool negative, is_float, zerofill, maybe_zerofill;
38
typedef struct st_extreme_value_number_info
42
double max_dval, min_dval;
45
typedef struct st_tree_info
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 strlen);
55
int compare_double(const double *s, const double *t);
56
int compare_longlong(const longlong *s, const longlong *t);
57
int compare_ulonglong(const ulonglong *s, const ulonglong *t);
58
Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result,
59
List<Item> &field_list);
60
void free_string(String*);
63
class field_info :public Sql_alloc
66
ulong treemem, tree_elements, empty, nulls, min_length, max_length;
74
field_info(Item* a, analyse* b) : treemem(0), tree_elements(0), empty(0),
75
nulls(0), min_length(0), max_length(0), room_in_tree(1),
76
found(0),item(a), pc(b) {};
78
virtual ~field_info() { delete_tree(&tree); }
79
virtual void add() = 0;
80
virtual void get_opt_type(String*, ha_rows) = 0;
81
virtual String *get_min_arg(String *) = 0;
82
virtual String *get_max_arg(String *) = 0;
83
virtual String *avg(String*, ha_rows) = 0;
84
virtual String *std(String*, ha_rows) = 0;
85
virtual tree_walk_action collect_enum() = 0;
86
virtual uint decimals() { return 0; }
91
class field_str :public field_info
93
String min_arg, max_arg;
95
bool must_be_blob, was_zero_fill, was_maybe_zerofill,
98
EV_NUM_INFO ev_num_info;
101
field_str(Item* a, analyse* b) :field_info(a,b), min_arg(""),
103
must_be_blob(0), was_zero_fill(0),
104
was_maybe_zerofill(0), can_be_still_num(1)
105
{ init_tree(&tree, 0, sizeof(String), a->binary ?
106
(qsort_cmp) stringcmp : (qsort_cmp) sortcmp,
107
0, (void (*)(void*)) free_string); };
110
void get_opt_type(String*, ha_rows);
111
String *get_min_arg(String *not_used __attribute__((unused)))
113
String *get_max_arg(String *not_used __attribute__((unused)))
115
String *avg(String *s, ha_rows rows)
118
s->set((double) 0.0, 1);
120
s->set((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
124
friend int collect_string(String *element, element_count count,
126
tree_walk_action collect_enum()
127
{ return (tree_walk_action) collect_string; }
128
String *std(String *s __attribute__((unused)),
129
ha_rows rows __attribute__((unused)))
130
{ return (String*) 0; }
133
class field_real: public field_info
135
double min_arg, max_arg;
137
uint max_notzero_dec_len;
140
field_real(Item* a, analyse* b) :field_info(a,b),
141
min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0)
142
{ init_tree(&tree, 0, sizeof(double),
143
(qsort_cmp) compare_double, 0, NULL); }
146
void get_opt_type(String*, ha_rows);
147
String *get_min_arg(String *s) { s->set(min_arg, item->decimals); return s; }
148
String *get_max_arg(String *s) { s->set(max_arg, item->decimals); return s; }
149
String *avg(String *s, ha_rows rows)
152
s->set((double) 0.0, 1);
154
s->set(((double)sum / (double) (rows - nulls)), item->decimals);
157
String *std(String *s, ha_rows rows)
159
double tmp = ulonglong2double(rows);
161
s->set((double) 0.0, 1);
164
double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
166
s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), item->decimals);
170
uint decimals() { return item->decimals; }
171
friend int collect_real(double *element, element_count count,
173
tree_walk_action collect_enum()
174
{ return (tree_walk_action) collect_real;}
177
class field_longlong: public field_info
179
longlong min_arg, max_arg;
180
longlong sum, sum_sqr;
183
field_longlong(Item* a, analyse* b) :field_info(a,b),
184
min_arg(0), max_arg(0), sum(0), sum_sqr(0)
185
{ init_tree(&tree, 0, sizeof(longlong),
186
(qsort_cmp) compare_longlong, 0, NULL); }
189
void get_opt_type(String*, ha_rows);
190
String *get_min_arg(String *s) { s->set(min_arg); return s; }
191
String *get_max_arg(String *s) { s->set(max_arg); return s; }
192
String *avg(String *s, ha_rows rows)
195
s->set((double) 0.0, 1);
197
s->set(((double) sum / (double) (rows - nulls)), DEC_IN_AVG);
200
String *std(String *s, ha_rows rows)
202
double tmp = ulonglong2double(rows);
204
s->set((double) 0.0, 1);
207
double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
209
s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG);
213
friend int collect_longlong(longlong *element, element_count count,
215
tree_walk_action collect_enum()
216
{ return (tree_walk_action) collect_longlong;}
220
class field_ulonglong: public field_info
222
ulonglong min_arg, max_arg;
223
ulonglong sum, sum_sqr;
226
field_ulonglong(Item* a, analyse * b) :field_info(a,b),
227
min_arg(0), max_arg(0), sum(0),sum_sqr(0)
228
{ init_tree(&tree, 0, sizeof(ulonglong),
229
(qsort_cmp) compare_ulonglong, 0, NULL); }
231
void get_opt_type(String*, ha_rows);
232
String *get_min_arg(String *s) { s->set(min_arg); return s; }
233
String *get_max_arg(String *s) { s->set(max_arg); return s; }
234
String *avg(String *s, ha_rows rows)
237
s->set((double) 0.0, 1);
239
s->set((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
243
String *std(String *s, ha_rows rows)
245
double tmp = ulonglong2double(rows);
247
s->set((double) 0.0, 1);
250
double tmp2 = ((ulonglong2double(sum_sqr) -
251
ulonglong2double(sum * sum) / (tmp - nulls)) /
253
s->set(((double) tmp2 <= 0.0 ? 0.0 : sqrt(tmp2)), DEC_IN_AVG);
257
friend int collect_ulonglong(ulonglong *element, element_count count,
259
tree_walk_action collect_enum()
260
{ return (tree_walk_action) collect_ulonglong; }
264
class analyse: public Procedure
267
Item_proc *func_items[10];
268
List<Item> fields, result_fields;
269
field_info **f_info, **f_end;
271
uint output_str_length;
274
uint max_tree_elements, max_treemem;
276
analyse(select_result *res) :Procedure(res, PROC_NO_SORT), rows(0),
277
output_str_length(0) {}
281
for (field_info **f=f_info; f != f_end; f++)
284
virtual void add() {}
285
virtual bool change_columns(List<Item> &fields);
286
virtual int send_row(List<Item> &fields);
287
virtual void end_group(void) {}
288
virtual bool end_of_records(void);
289
friend Procedure *proc_analyse_init(THD *thd, ORDER *param,
290
select_result *result,
291
List<Item> &field_list);