diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index 8da95d60a45..50d20c1ed12 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. + Copyright (c) 2010, 2026, MariaDB plc. 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 @@ -45,7 +46,6 @@ int compare_double2(void *, const void *s_, const void *t_) { const double *s= static_cast(s_); const double *t= static_cast(t_); - return compare_double(s,t); } @@ -285,7 +285,7 @@ bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num) { if (((longlong) info->ullval) < 0) return 0; // Impossible to store as a negative number - ev_info->llval = -(longlong) MY_MAX((ulonglong) -ev_info->llval, + ev_info->llval = -(longlong) MY_MAX((ulonglong) -ev_info->llval, info->ullval); ev_info->min_dval = (double) -MY_MAX(-ev_info->min_dval, info->dval); } @@ -300,13 +300,6 @@ bool get_ev_num_info(EV_NUM_INFO *ev_info, NUM_INFO *info, const char *num) } // get_ev_num_info -int free_string(void* str, TREE_FREE, void*) -{ - ((String*)str)->free(); - return 0; -} - - void field_str::add() { char buff[MAX_FIELD_WIDTH], *ptr; @@ -371,22 +364,22 @@ void field_str::add() { if (res != &s) s.copy(*res); - if (!tree_search(&tree, (void*) &s, tree.custom_arg)) // If not in tree + if (!tree.find(s)) // If not in tree { s.copy(); // slow, when SAFE_MALLOC is in use - if (!tree_insert(&tree, (void*) &s, 0, tree.custom_arg)) + if (tree.insert(s)) { - room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree, 0); + room_in_tree = 0; // Remove tree, out of RAM ? + tree.clear(); } else { - bzero((char*) &s, sizeof(s)); // Let tree handle free of this - if ((treemem += length) > pc->max_treemem) - { - room_in_tree = 0; // Remove tree, too big tree - delete_tree(&tree, 0); - } + s.release(); // Let tree handle free of this + if ((treemem += length) > pc->max_treemem) + { + room_in_tree = 0; // Remove tree, too big tree + tree.clear(); + } } } } @@ -402,7 +395,6 @@ void field_real::add() char buff[MAX_FIELD_WIDTH], *ptr, *end; double num= item->val_real(); uint length, zero_count, decs; - TREE_ELEMENT *element; if (item->null_value) { @@ -437,19 +429,15 @@ void field_real::add() if (room_in_tree) { - if (!(element = tree_insert(&tree, (void*) &num, 0, tree.custom_arg))) + if (tree.insert(num)) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree, 0); + tree.clear(); } - /* - if element->count == 1, this element can be found only once from tree - if element->count == 2, or more, this element is already in tree - */ - else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) + else if ((tree_elements= tree.elements()) > pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree, 0); + tree.clear(); } } @@ -481,7 +469,6 @@ void field_decimal::add() /*TODO - remove rounding stuff after decimal_div returns proper frac */ VDec vdec(item); uint length; - TREE_ELEMENT *element; if (vdec.is_null()) { @@ -499,21 +486,17 @@ void field_decimal::add() if (room_in_tree) { - uchar buf[DECIMAL_MAX_FIELD_SIZE]; - dec.to_binary(buf, item->max_length, item->decimals); - if (!(element = tree_insert(&tree, (void*)buf, 0, tree.custom_arg))) + DecimalKey key; + dec.to_binary(key.data, item->max_length, item->decimals); + if (tree.insert(key)) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree, 0); + tree.clear(); } - /* - if element->count == 1, this element can be found only once from tree - if element->count == 2, or more, this element is already in tree - */ - else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) + else if ((tree_elements= tree.elements()) > pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree, 0); + tree.clear(); } } @@ -556,7 +539,6 @@ void field_longlong::add() longlong numlong = item->val_int(); double num = (double) numlong; uint length = (uint) (longlong10_to_str(numlong, buff, -10) - buff); - TREE_ELEMENT *element; if (item->null_value) { @@ -568,19 +550,15 @@ void field_longlong::add() if (room_in_tree) { - if (!(element = tree_insert(&tree, (void*) &numlong, 0, tree.custom_arg))) + if (tree.insert(numlong)) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree, 0); + tree.clear(); } - /* - if element->count == 1, this element can be found only once from tree - if element->count == 2, or more, this element is already in tree - */ - else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) + else if ((tree_elements= tree.elements()) > pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree, 0); + tree.clear(); } } @@ -614,7 +592,6 @@ void field_ulonglong::add() ulonglong numlong = item->val_int(); double num= (double) numlong; uint length = (uint) (longlong10_to_str(numlong, buff, 10) - buff); - TREE_ELEMENT *element; if (item->null_value) { @@ -626,19 +603,15 @@ void field_ulonglong::add() if (room_in_tree) { - if (!(element = tree_insert(&tree, (void*) &numlong, 0, tree.custom_arg))) + if (tree.insert(numlong)) { room_in_tree = 0; // Remove tree, out of RAM ? - delete_tree(&tree, 0); + tree.clear(); } - /* - if element->count == 1, this element can be found only once from tree - if element->count == 2, or more, this element is already in tree - */ - else if (element->count == 1 && (tree_elements++) >= pc->max_tree_elements) + else if ((tree_elements= tree.elements()) > pc->max_tree_elements) { room_in_tree = 0; // Remove tree, too many elements - delete_tree(&tree, 0); + tree.clear(); } } @@ -683,11 +656,9 @@ int analyse::send_row(List & /* field_list */) int analyse::end_of_records() { field_info **f = f_info; - char buff[MAX_FIELD_WIDTH]; - String *res, s_min(buff, sizeof(buff),&my_charset_bin), - s_max(buff, sizeof(buff),&my_charset_bin), - ans(buff, sizeof(buff),&my_charset_bin); + StringBuffer s; StringBuffer name; + String *res; for (; f != f_end; f++) { @@ -708,20 +679,20 @@ int analyse::end_of_records() else { func_items[1]->null_value = 0; - res = (*f)->get_min_arg(&s_min); + res = (*f)->get_min_arg(&s); func_items[1]->set(res->ptr(), res->length(), res->charset()); func_items[2]->null_value = 0; - res = (*f)->get_max_arg(&s_max); + res = (*f)->get_max_arg(&s); func_items[2]->set(res->ptr(), res->length(), res->charset()); } func_items[3]->set((longlong) (*f)->min_length); func_items[4]->set((longlong) (*f)->max_length); func_items[5]->set((longlong) (*f)->empty); func_items[6]->set((longlong) (*f)->nulls); - res = (*f)->avg(&s_max, rows); + res = (*f)->avg(&s, rows); func_items[7]->set(res->ptr(), res->length(), res->charset()); func_items[8]->null_value = 0; - res = (*f)->std(&s_max, rows); + res = (*f)->std(&s, rows); if (!res) func_items[8]->null_value = 1; else @@ -730,17 +701,17 @@ int analyse::end_of_records() count the dots, quotas, etc. in (ENUM("a","b","c"...)) If tree has been removed, don't suggest ENUM. treemem is used to measure the size of tree for strings, - tree_elements is used to count the elements + tree_elements is used to count the elements for numerics max_treemem tells how long the string starting from ENUM("... and ending to ..") shall at maximum be. If case is about numbers, max_tree_elements will tell the length of the above, now every number is considered as length 1 */ if (((*f)->treemem || (*f)->tree_elements) && - (*f)->tree.elements_in_tree && + (*f)->tree_size() && (((*f)->treemem ? max_treemem : max_tree_elements) > (((*f)->treemem ? (*f)->treemem : (*f)->tree_elements) + - ((*f)->tree.elements_in_tree * 3 - 1 + 6)))) + ((*f)->tree_size() * 3 - 1 + 6)))) { char tmp[331]; //331, because one double prec. num. can be this long String tmp_str(tmp, sizeof(tmp),&my_charset_bin); @@ -751,8 +722,7 @@ int analyse::end_of_records() tree_info.item = (*f)->item; tmp_str.set(STRING_WITH_LEN("ENUM("),&my_charset_bin); - tree_walk(&(*f)->tree, (*f)->collect_enum(), (char*) &tree_info, - left_root_right); + (*f)->walk_tree(&tree_info); tmp_str.append(')'); if (!(*f)->nulls) @@ -764,46 +734,46 @@ int analyse::end_of_records() continue; } - ans.length(0); + s.length(0); if (!(*f)->treemem && !(*f)->tree_elements) - ans.append(STRING_WITH_LEN("CHAR(0)")); + s.append(STRING_WITH_LEN("CHAR(0)")); else if ((*f)->item->type() == Item::FIELD_ITEM) { switch (((Item_field*) (*f)->item)->field->real_type()) { case MYSQL_TYPE_TIMESTAMP: - ans.append(STRING_WITH_LEN("TIMESTAMP")); + s.append(STRING_WITH_LEN("TIMESTAMP")); break; case MYSQL_TYPE_DATETIME: - ans.append(STRING_WITH_LEN("DATETIME")); + s.append(STRING_WITH_LEN("DATETIME")); break; case MYSQL_TYPE_DATE: case MYSQL_TYPE_NEWDATE: - ans.append(STRING_WITH_LEN("DATE")); + s.append(STRING_WITH_LEN("DATE")); break; case MYSQL_TYPE_SET: - ans.append(STRING_WITH_LEN("SET")); + s.append(STRING_WITH_LEN("SET")); break; case MYSQL_TYPE_YEAR: - ans.append(STRING_WITH_LEN("YEAR")); + s.append(STRING_WITH_LEN("YEAR")); break; case MYSQL_TYPE_TIME: - ans.append(STRING_WITH_LEN("TIME")); + s.append(STRING_WITH_LEN("TIME")); break; case MYSQL_TYPE_DECIMAL: - ans.append(STRING_WITH_LEN("DECIMAL")); + s.append(STRING_WITH_LEN("DECIMAL")); // if item is FIELD_ITEM, it _must_be_ Field_num in this case if (((Field_num*) ((Item_field*) (*f)->item)->field)->zerofill) - ans.append(STRING_WITH_LEN(" ZEROFILL")); + s.append(STRING_WITH_LEN(" ZEROFILL")); break; default: - (*f)->get_opt_type(&ans, rows); + (*f)->get_opt_type(&s, rows); break; } } if (!(*f)->nulls) - ans.append(STRING_WITH_LEN(" NOT NULL")); - func_items[9]->set(ans.ptr(), ans.length(), ans.charset()); + s.append(STRING_WITH_LEN(" NOT NULL")); + func_items[9]->set(s.ptr(), s.length(), s.charset()); if (result->send_data(result_fields) > 0) return -1; } @@ -1082,26 +1052,27 @@ String *field_decimal::std(String *s, ha_rows rows) } -int collect_string(void *element_, element_count, void *info_) +int collect_string(const String &element, element_count, TREE_INFO *info) { - String *element= static_cast(element_); - TREE_INFO *info= static_cast(info_); if (info->found) info->str->append(','); else info->found = 1; info->str->append('\''); - if (info->str->append_for_single_quote(element)) + if (info->str->append_for_single_quote(&element)) return 1; info->str->append('\''); return 0; } // collect_string - -int collect_real(void *element_, element_count, void *info_) +void field_str::walk_tree(TREE_INFO *info) +{ + tree.walk(collect_string, info); +} + + +int collect_real(const double &element, element_count, TREE_INFO *info) { - double *element= static_cast(element_); - TREE_INFO *info= static_cast(info_); char buff[MAX_FIELD_WIDTH]; String s(buff, sizeof(buff),current_thd->charset()); @@ -1110,17 +1081,20 @@ int collect_real(void *element_, element_count, void *info_) else info->found = 1; info->str->append('\''); - s.set_real(*element, info->item->decimals, current_thd->charset()); + s.set_real(element, info->item->decimals, current_thd->charset()); info->str->append(s); info->str->append('\''); return 0; } // collect_real - -int collect_decimal(void *element_, element_count count, void *info_) +void field_real::walk_tree(TREE_INFO *info) +{ + tree.walk(collect_real, info); +} + + +int collect_decimal(const DecimalKey &key, element_count, TREE_INFO *info) { - uchar *element= static_cast(element_); - TREE_INFO *info= static_cast(info_); char buff[DECIMAL_MAX_STR_LENGTH]; String s(buff, sizeof(buff),&my_charset_bin); @@ -1128,7 +1102,7 @@ int collect_decimal(void *element_, element_count count, void *info_) info->str->append(','); else info->found = 1; - my_decimal dec(element, info->item->max_length, info->item->decimals); + my_decimal dec(key.data, info->item->max_length, info->item->decimals); info->str->append('\''); dec.to_string_native(&s, 0, 0, '0'); info->str->append(s); @@ -1136,11 +1110,14 @@ int collect_decimal(void *element_, element_count count, void *info_) return 0; } - -int collect_longlong(void *element_, element_count, void *info_) +void field_decimal::walk_tree(TREE_INFO *info) +{ + tree.walk(collect_decimal, info); +} + + +int collect_longlong(const longlong &element, element_count, TREE_INFO *info) { - longlong *element= static_cast(element_); - TREE_INFO *info= static_cast(info_); char buff[MAX_FIELD_WIDTH]; String s(buff, sizeof(buff),&my_charset_bin); @@ -1149,17 +1126,20 @@ int collect_longlong(void *element_, element_count, void *info_) else info->found = 1; info->str->append('\''); - s.set(*element, current_thd->charset()); + s.set(element, current_thd->charset()); info->str->append(s); info->str->append('\''); return 0; } // collect_longlong - -int collect_ulonglong(void *element_, element_count, void *info_) +void field_longlong::walk_tree(TREE_INFO *info) +{ + tree.walk(collect_longlong, info); +} + + +int collect_ulonglong(const ulonglong &element, element_count, TREE_INFO *info) { - ulonglong *element= static_cast(element_); - TREE_INFO *info= static_cast(info_); char buff[MAX_FIELD_WIDTH]; String s(buff, sizeof(buff),&my_charset_bin); @@ -1168,12 +1148,17 @@ int collect_ulonglong(void *element_, element_count, void *info_) else info->found = 1; info->str->append('\''); - s.set(*element, current_thd->charset()); + s.set(element, current_thd->charset()); info->str->append(s); info->str->append('\''); return 0; } // collect_ulonglong +void field_ulonglong::walk_tree(TREE_INFO *info) +{ + tree.walk(collect_ulonglong, info); +} + bool analyse::change_columns(THD *thd, List &field_list) { diff --git a/sql/sql_analyse.h b/sql/sql_analyse.h index fdfcd248370..c01a074762d 100644 --- a/sql/sql_analyse.h +++ b/sql/sql_analyse.h @@ -1,7 +1,8 @@ #ifndef SQL_ANALYSE_INCLUDED #define SQL_ANALYSE_INCLUDED -/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. + Copyright (c) 2010, 2026, MariaDB plc. 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 @@ -20,6 +21,7 @@ /* Analyse database */ #include "procedure.h" /* Procedure */ +#include "sql_tree.h" #define my_thd_charset default_charset_info @@ -61,7 +63,12 @@ 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 &field_list); -int free_string(void* str, TREE_FREE, void*); + +struct DecimalKey +{ + uchar data[DECIMAL_MAX_FIELD_SIZE]; +}; + class analyse; class field_info :public Sql_alloc @@ -70,7 +77,6 @@ protected: ulong treemem, tree_elements, empty, nulls, min_length, max_length; uint room_in_tree; bool found; - TREE tree; Item *item; analyse *pc; @@ -79,19 +85,20 @@ public: 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 ~field_info() = default; 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 void walk_tree(TREE_INFO *) = 0; + virtual uint tree_size() const = 0; virtual uint decimals() { return 0; } friend class analyse; }; -int collect_string(void *element, element_count count, void *info); +int collect_string(const String &element, element_count count, TREE_INFO &info); int sortcmp2(void *, const void *a, const void *b); @@ -103,17 +110,16 @@ class field_str :public field_info can_be_still_num; NUM_INFO num_info; EV_NUM_INFO ev_num_info; + Tree tree; public: - field_str(Item* a, analyse* b) :field_info(a,b), + 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)); - }; + was_maybe_zerofill(0), can_be_still_num(1), + tree(sortcmp2, nullptr, MYF(MY_THREAD_SPECIFIC)) + {}; void add() override; void get_opt_type(String*, ha_rows) override; @@ -130,17 +136,18 @@ public: 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; } + void walk_tree(TREE_INFO *info) override; + uint tree_size() const override { return tree.elements(); } + friend int collect_string(const String &element, element_count count, + TREE_INFO &info); 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); +int collect_decimal(const DecimalKey &element, element_count count, + TREE_INFO &info); class field_decimal :public field_info { @@ -148,42 +155,40 @@ class field_decimal :public field_info my_decimal sum[2], sum_sqr[2]; int cur_sum; int bin_size; + Tree tree; 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)); - }; + field_decimal(Item* a, analyse* b) :field_info(a,b), + bin_size((int) my_decimal_get_binary_size(a->max_length, a->decimals)), + tree(compare_decimal2, &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; } + friend int collect_decimal(const DecimalKey &element, element_count count, + TREE_INFO &info); + void walk_tree(TREE_INFO *info) override; + uint tree_size() const override { return tree.elements(); } String *std(String *s, ha_rows rows) override; }; -int collect_real(void *element, element_count count, void *info); +int collect_real(const double &element, element_count count, TREE_INFO &info); class field_real: public field_info { double min_arg, max_arg; double sum, sum_sqr; uint max_notzero_dec_len; + Tree tree; 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)); - } + min_arg(0), max_arg(0), sum(0), sum_sqr(0), max_notzero_dec_len(0), + tree(compare_double2, nullptr, MYF(MY_THREAD_SPECIFIC)) + {} void add() override; void get_opt_type(String*, ha_rows) override; @@ -219,26 +224,26 @@ public: 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;} + void walk_tree(TREE_INFO *info) override; + uint tree_size() const override { return tree.elements(); } + friend int collect_real(const double &element, element_count count, + TREE_INFO &info); }; -int collect_longlong(void *element, element_count count, void *info); +int collect_longlong(const longlong &element, element_count count, + TREE_INFO &info); class field_longlong: public field_info { longlong min_arg, max_arg; double sum, sum_sqr; + Tree tree; 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)); - } + field_longlong(Item* a, analyse* b) :field_info(a,b), + min_arg(0), max_arg(0), sum(0), sum_sqr(0.0), + tree(compare_longlong2, nullptr, MYF(MY_THREAD_SPECIFIC)) + {} void add() override; void get_opt_type(String*, ha_rows) override; @@ -265,26 +270,26 @@ public: } return s; } - friend int collect_longlong(longlong *element, element_count count, - TREE_INFO *info); - tree_walk_action collect_enum() override - { return collect_longlong;} + void walk_tree(TREE_INFO *info) override; + uint tree_size() const override { return tree.elements(); } + friend int collect_longlong(const longlong &element, element_count count, + TREE_INFO &info); }; -int collect_ulonglong(void *element, element_count count, void *info); +int collect_ulonglong(const ulonglong &element, element_count count, + TREE_INFO &info); class field_ulonglong: public field_info { ulonglong min_arg, max_arg; double sum, sum_sqr; + Tree tree; 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)); - } + min_arg(0), max_arg(0), sum(0),sum_sqr(0), + tree(compare_ulonglong2, nullptr, 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; } @@ -312,10 +317,10 @@ public: } return s; } - friend int collect_ulonglong(ulonglong *element, element_count count, - TREE_INFO *info); - tree_walk_action collect_enum() override - { return collect_ulonglong; } + void walk_tree(TREE_INFO *info) override; + uint tree_size() const override { return tree.elements(); } + friend int collect_ulonglong(const ulonglong &element, element_count count, + TREE_INFO &info); }; diff --git a/sql/sql_tree.h b/sql/sql_tree.h new file mode 100644 index 00000000000..c6c69aca7a5 --- /dev/null +++ b/sql/sql_tree.h @@ -0,0 +1,89 @@ +#ifndef SQL_TREE_INCLUDED +#define SQL_TREE_INCLUDED +/* + Copyright (c) 2026, MariaDB plc + + 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 +*/ + +#include + +/* + Type-safe wrapper around the C TREE red-black tree. +*/ +template +class Tree +{ + TREE m_tree; + + static int free_shim(void *elem, TREE_FREE action, void *) + { + if (action == free_free) + static_cast(elem)->~T(); + return 0; + } + + template + struct walk_arg + { + int (*fn)(const T &, element_count, Ctx *); + Ctx *ctx; + }; + + template + static int call_shim(void *elem, element_count cnt, void *arg_) + { + auto *arg= static_cast *>(arg_); + return arg->fn(*static_cast(elem), cnt, arg->ctx); + } + +public: + explicit Tree(qsort_cmp2 fn, Param *extra_arg= nullptr, myf flags= MYF(0)) + { + init_tree(&m_tree, 0, 0, sizeof(T), fn, free_shim, (void*)extra_arg, flags); + } + ~Tree() { delete_tree(&m_tree, 0); } + + void clear() { delete_tree(&m_tree, 0); } + + Tree(const Tree &)= delete; + Tree &operator=(const Tree &)= delete; + + /* Insert val; returns true on OOM. Duplicate inserts increment the count. */ + bool insert(const T &val) + { + return tree_insert(&m_tree, &val, 0, m_tree.custom_arg) == nullptr; + } + + T *find(const T &key) + { + return static_cast(tree_search(&m_tree, &key, m_tree.custom_arg)); + } + + /* + Walk all elements in order, calling fn(const T &, element_count, Ctx &). + fn should return 0 to continue, non-zero to stop. + */ + template + int walk(int (*fn)(const T &, element_count, Ctx *), Ctx *ctx, + TREE_WALK dir= left_root_right) + { + walk_arg arg= {fn, ctx}; + return tree_walk(&m_tree, call_shim, &arg, dir); + } + + uint elements() const { return m_tree.elements_in_tree; } +}; + +#endif /* SQL_TREE_INCLUDED */ diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index acbdf73a9e3..87d82831947 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -377,7 +377,6 @@ #include "sql_priv.h" #include "sql_servers.h" // FOREIGN_SERVER, get_server_by_name #include "sql_class.h" // SSV -#include "sql_analyse.h" // append_escaped #include #include "ha_federated.h" diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index ff0ca86abb7..c2cf93be411 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -314,7 +314,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "ha_federatedx.h" #include "sql_servers.h" -#include "sql_analyse.h" // append_escaped() #include "sql_show.h" // append_identifier() #include "tztime.h" // my_tz_find() #include "sql_select.h" diff --git a/storage/spider/spd_db_conn.cc b/storage/spider/spd_db_conn.cc index ea3d2978cf0..1cd05403bb8 100644 --- a/storage/spider/spd_db_conn.cc +++ b/storage/spider/spd_db_conn.cc @@ -21,7 +21,6 @@ #include "probes_mysql.h" #include "sql_class.h" #include "sql_partition.h" -#include "sql_analyse.h" #include "sql_base.h" #include "tztime.h" #include "errmsg.h" diff --git a/storage/spider/spd_db_mysql.cc b/storage/spider/spd_db_mysql.cc index c485b3f6b81..6b5ec96d3d7 100644 --- a/storage/spider/spd_db_mysql.cc +++ b/storage/spider/spd_db_mysql.cc @@ -21,7 +21,6 @@ #include "probes_mysql.h" #include "sql_class.h" #include "sql_partition.h" -#include "sql_analyse.h" #include "sql_base.h" #include "tztime.h" #include "sql_select.h" diff --git a/storage/spider/spd_malloc.cc b/storage/spider/spd_malloc.cc index 0a591bedb4e..51eed38eedf 100644 --- a/storage/spider/spd_malloc.cc +++ b/storage/spider/spd_malloc.cc @@ -20,7 +20,6 @@ #include "sql_priv.h" #include "probes_mysql.h" #include "sql_class.h" -#include "sql_analyse.h" #include "spd_db_include.h" #include "spd_include.h" #include "spd_malloc.h"