#ifndef SQL_ANALYSE_INCLUDED
#define SQL_ANALYSE_INCLUDED
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; version 2 of the License .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
/* Analyse database */
#include "procedure.h" /* Procedure */
#define my_thd_charset default_charset_info
#define DEC_IN_AVG 4
typedef struct st_number_info
{
// if zerofill is true, the number must be zerofill, or string
bool negative, is_float, zerofill, maybe_zerofill;
int8 integers;
int8 decimals;
double dval;
ulonglong ullval;
} NUM_INFO;
typedef struct st_extreme_value_number_info
{
ulonglong ullval;
longlong llval;
double max_dval, min_dval;
} EV_NUM_INFO;
typedef struct st_tree_info
{
bool found;
String *str;
Item *item;
} TREE_INFO;
uint check_ulonglong(const char *str, uint length);
bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num);
bool test_if_number(NUM_INFO *info, const char *str, uint str_len);
int compare_double(const double *s, const double *t);
int compare_double2(void *, const void *s, const void *t);
int compare_longlong(const longlong *s, const longlong *t);
int compare_longlong2(void *, const void *s, const void *t);
int compare_ulonglong(const ulonglong *s, const ulonglong *t);
int compare_ulonglong2(void *, const void *s, const void *t);
int compare_decimal2(void *len, const void *s, const void *t);
Procedure *proc_analyse_init(THD *thd, ORDER *param, select_result *result,
List<Item> &field_list);
int free_string(void * str, TREE_FREE, void *);
class analyse;
class field_info :public Sql_alloc
{
protected :
ulong treemem, tree_elements, empty, nulls, min_length, max_length;
uint room_in_tree;
bool found;
TREE tree;
Item *item;
analyse *pc;
public :
field_info(Item* a, analyse* b) : treemem(0 ), tree_elements(0 ), empty(0 ),
nulls(0 ), min_length(0 ), max_length(0 ), room_in_tree(1 ),
found(0 ),item(a), pc(b) {};
virtual ~field_info() { delete_tree(&tree, 0 ); }
virtual void add() = 0 ;
virtual void get_opt_type(String*, ha_rows) = 0 ;
virtual String *get_min_arg(String *) = 0 ;
virtual String *get_max_arg(String *) = 0 ;
virtual String *avg(String*, ha_rows) = 0 ;
virtual String *std(String*, ha_rows) = 0 ;
virtual tree_walk_action collect_enum() = 0 ;
virtual uint decimals() { return 0 ; }
friend class analyse;
};
int collect_string(void *element, element_count count, void *info);
int sortcmp2(void *, const void *a, const void *b);
class field_str :public field_info
{
String min_arg, max_arg;
ulonglong sum;
bool must_be_blob, was_zero_fill, was_maybe_zerofill,
can_be_still_num;
NUM_INFO num_info;
EV_NUM_INFO ev_num_info;
public :
field_str(Item* a, analyse* b) :field_info(a,b),
min_arg("" ,0 ,default_charset_info),
max_arg("" ,0 ,default_charset_info), sum(0 ),
must_be_blob(0 ), was_zero_fill(0 ),
was_maybe_zerofill(0 ), can_be_still_num(1 )
{
init_tree(&tree, 0 , 0 , sizeof (String), sortcmp2, free_string, NULL,
MYF(MY_THREAD_SPECIFIC));
};
void add() override;
void get_opt_type(String*, ha_rows) override;
String *get_min_arg(String *not_used __attribute__((unused))) override
{ return &min_arg; }
String *get_max_arg(String *not_used __attribute__((unused))) override
{ return &max_arg; }
String *avg(String *s, ha_rows rows) override
{
if (!(rows - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
s->set_real((ulonglong2double(sum) / ulonglong2double(rows - nulls)),
DEC_IN_AVG,my_thd_charset);
return s;
}
friend int collect_string(String *element, element_count count,
TREE_INFO *info);
tree_walk_action collect_enum() override
{ return collect_string; }
String *std(String *s __attribute__((unused)),
ha_rows rows __attribute__((unused))) override
{ return (String*) 0 ; }
};
int collect_decimal(void *element, element_count count, void *info);
class field_decimal :public field_info
{
my_decimal min_arg, max_arg;
my_decimal sum[2 ], sum_sqr[2 ];
int cur_sum;
int bin_size;
public :
field_decimal(Item* a, analyse* b) :field_info(a,b)
{
bin_size= my_decimal_get_binary_size(a->max_length, a->decimals);
init_tree(&tree, 0 , 0 , bin_size, compare_decimal2, 0 , (void *) &bin_size,
MYF(MY_THREAD_SPECIFIC));
};
void add() override;
void get_opt_type(String*, ha_rows) override;
String *get_min_arg(String *) override;
String *get_max_arg(String *) override;
String *avg(String *s, ha_rows rows) override;
friend int collect_decimal(uchar *element, element_count count,
TREE_INFO *info);
tree_walk_action collect_enum() override
{ return collect_decimal; }
String *std(String *s, ha_rows rows) override;
};
int collect_real(void *element, element_count count, void *info);
class field_real: public field_info
{
double min_arg, max_arg;
double sum, sum_sqr;
uint max_notzero_dec_len;
public :
field_real(Item* a, analyse* b) :field_info(a,b),
min_arg(0 ), max_arg(0 ), sum(0 ), sum_sqr(0 ), max_notzero_dec_len(0 )
{
init_tree(&tree, 0 , 0 , sizeof (double ), compare_double2, NULL, NULL,
MYF(MY_THREAD_SPECIFIC));
}
void add() override;
void get_opt_type(String*, ha_rows) override;
String *get_min_arg(String *s) override
{
s->set_real(min_arg, item->decimals, my_thd_charset);
return s;
}
String *get_max_arg(String *s) override
{
s->set_real(max_arg, item->decimals, my_thd_charset);
return s;
}
String *avg(String *s, ha_rows rows) override
{
if (!(rows - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
s->set_real(((double )sum / (double ) (rows - nulls)), item->decimals,my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows) override
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
{
double tmp2 = ((sum_sqr - sum * sum / (tmp - nulls)) /
(tmp - nulls));
s->set_real(((double ) tmp2 <= 0 .0 ? 0 .0 : sqrt(tmp2)), item->decimals,my_thd_charset);
}
return s;
}
uint decimals() override { return item->decimals; }
friend int collect_real(double *element, element_count count,
TREE_INFO *info);
tree_walk_action collect_enum() override
{ return collect_real;}
};
int collect_longlong(void *element, element_count count, void *info);
class field_longlong: public field_info
{
longlong min_arg, max_arg;
double sum, sum_sqr;
public :
field_longlong(Item* a, analyse* b) :field_info(a,b),
min_arg(0 ), max_arg(0 ), sum(0 ), sum_sqr(0 .0 )
{
init_tree(&tree, 0 , 0 , sizeof (longlong), compare_longlong2, NULL, NULL,
MYF(MY_THREAD_SPECIFIC));
}
void add() override;
void get_opt_type(String*, ha_rows) override;
String *get_min_arg(String *s) override { s->set(min_arg,my_thd_charset); return s; }
String *get_max_arg(String *s) override { s->set(max_arg,my_thd_charset); return s; }
String *avg(String *s, ha_rows rows) override
{
if (!(rows - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
s->set_real(((double ) sum / (double ) (rows - nulls)), DEC_IN_AVG,my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows) override
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
{
double tmp2 = (sum_sqr - sum * sum / (tmp - nulls)) /
(tmp - nulls);
s->set_real(tmp2 <= 0 .0 ? 0 .0 : sqrt(tmp2), DEC_IN_AVG,my_thd_charset);
}
return s;
}
friend int collect_longlong(longlong *element, element_count count,
TREE_INFO *info);
tree_walk_action collect_enum() override
{ return collect_longlong;}
};
int collect_ulonglong(void *element, element_count count, void *info);
class field_ulonglong: public field_info
{
ulonglong min_arg, max_arg;
double sum, sum_sqr;
public :
field_ulonglong(Item* a, analyse * b) :field_info(a,b),
min_arg(0 ), max_arg(0 ), sum(0 ),sum_sqr(0 )
{
init_tree(&tree, 0 , 0 , sizeof (ulonglong), compare_ulonglong2, NULL, NULL,
MYF(MY_THREAD_SPECIFIC));
}
void add() override;
void get_opt_type(String*, ha_rows) override;
String *get_min_arg(String *s) override { s->set(min_arg,my_thd_charset); return s; }
String *get_max_arg(String *s) override { s->set(max_arg,my_thd_charset); return s; }
String *avg(String *s, ha_rows rows) override
{
if (!(rows - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
s->set_real(sum / ulonglong2double(rows - nulls),
DEC_IN_AVG, my_thd_charset);
return s;
}
String *std(String *s, ha_rows rows) override
{
double tmp = ulonglong2double(rows);
if (!(tmp - nulls))
s->set_real((double ) 0 .0 , 1 ,my_thd_charset);
else
{
double tmp2 = (sum_sqr -
(sum * sum) / (tmp - nulls)) /
(tmp - nulls);
s->set_real(tmp2 <= 0 .0 ? 0 .0 : sqrt(tmp2), DEC_IN_AVG,my_thd_charset);
}
return s;
}
friend int collect_ulonglong(ulonglong *element, element_count count,
TREE_INFO *info);
tree_walk_action collect_enum() override
{ return collect_ulonglong; }
};
Procedure *proc_analyse_init(THD *thd, ORDER *param,
select_result *result,
List<Item> &field_list);
class analyse: public Procedure
{
protected :
Item_proc *func_items[10 ];
List<Item> fields, result_fields;
field_info **f_info, **f_end;
ha_rows rows;
uint output_str_length;
public :
uint max_tree_elements, max_treemem;
analyse(select_result *res) :Procedure(res, PROC_NO_SORT), f_info(0 ),
rows(0 ), output_str_length(0 ) {}
~analyse()
{
if (f_info)
{
for (field_info **f=f_info; f != f_end; f++)
delete (*f);
}
}
void add() override {}
bool change_columns(THD *thd, List<Item> &fields) override;
int send_row(List<Item> &field_list) override;
void end_group(void ) override {}
int end_of_records(void ) override;
friend Procedure *proc_analyse_init(THD *thd, ORDER *param,
select_result *result,
List<Item> &field_list);
};
#endif /* SQL_ANALYSE_INCLUDED */
Messung V0.5 in Prozent C=99 H=100 G=99
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-10-08)
¤
*© Formatika GbR, Deutschland