From b1beb31400540e16f3294e18e7f664c641093dbc Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Sat, 7 Dec 2002 16:00:39 +0200 Subject: [PATCH 1/4] Row item fixing (SCRUM related) Inserted comment --- sql/item_row.cc | 23 ++++++++++++++++++++--- sql/item_row.h | 12 +++++++++--- sql/sql_select.cc | 10 ++++++++++ 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/sql/item_row.cc b/sql/item_row.cc index 464a8fd0ec5..e073f8e24e7 100644 --- a/sql/item_row.cc +++ b/sql/item_row.cc @@ -18,8 +18,10 @@ #include "assert.h" Item_row::Item_row(List &arg): - Item(), array_holder(1) + Item(), array_holder(1), used_tables_cache(0), const_item_cache(1) { + + //TODO: think placing 2-3 component items in item (as it done for function) if ((arg_count= arg.elements)) items= (Item**) sql_alloc(sizeof(Item*)*arg_count); else @@ -45,16 +47,31 @@ void Item_row::illegal_method_call(const char *method) bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) { - tables= 0; + null_value= 0; + maybe_null= 0; for (uint i= 0; i < arg_count; i++) { if (items[i]->fix_fields(thd, tabl, items+i)) return 1; - tables |= items[i]->used_tables(); + used_tables_cache |= items[i]->used_tables(); + const_item_cache&= items[i]->const_item(); + maybe_null|= items[i]->maybe_null; } return 0; } +void Item_row::update_used_tables() +{ + used_tables_cache= 0; + const_item_cache= 1; + for (uint i= 0; i < arg_count; i++) + { + items[i]->update_used_tables(); + used_tables_cache|= items[i]->used_tables(); + const_item_cache&= items[i]->const_item(); + } +} + bool Item_row::check_cols(uint c) { if (c != arg_count) diff --git a/sql/item_row.h b/sql/item_row.h index 5580250b4fb..d097fca8f1d 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -17,13 +17,17 @@ class Item_row: public Item { bool array_holder; - table_map tables; + table_map used_tables_cache; + bool const_item_cache; uint arg_count; Item **items; public: Item_row(List &); Item_row(Item_row *item): - Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count), + Item(), array_holder(0), + used_tables_cache(item->used_tables_cache), + const_item_cache(item->const_item_cache), + arg_count(item->arg_count), items(item->items) {} @@ -56,8 +60,10 @@ public: return 0; }; bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); - table_map used_tables() const { return tables; }; + table_map used_tables() const { return used_tables_cache; }; + bool const_item() const { return const_item_cache; }; enum Item_result result_type() const { return ROW_RESULT; } + void update_used_tables(); virtual uint cols() { return arg_count; } virtual Item* el(uint i) { return items[i]; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 50820b931b6..4e9f8cf9383 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -763,6 +763,16 @@ JOIN::exec() select_options, unit))) DBUG_VOID_RETURN; + /* + We don't have to store rows in temp table that doesn't match HAVING if: + - we are sorting the table and writing complete group rows to the + temp table. + - We are using DISTINCT without resolving the distinct as a GROUP BY + on all columns. + + If having is not handled here, it will be checked before the row + is sent to the client. + */ if (having_list && (sort_and_group || (exec_tmp_table->distinct && !group_list))) having=having_list; From 67eebb4382e925a7ffb804c2f2bf7341ece64432 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Sat, 7 Dec 2002 19:58:05 +0200 Subject: [PATCH 2/4] IN with row item without constant optimisation (SCRUM) renamed row item test --- mysql-test/r/{row_test.result => row.result} | 16 +++++ mysql-test/t/{row_test.test => row.test} | 6 ++ sql/item_cmpfunc.cc | 73 +++++++++++++++----- sql/item_cmpfunc.h | 22 ++++-- 4 files changed, 91 insertions(+), 26 deletions(-) rename mysql-test/r/{row_test.result => row.result} (76%) rename mysql-test/t/{row_test.test => row.test} (78%) diff --git a/mysql-test/r/row_test.result b/mysql-test/r/row.result similarity index 76% rename from mysql-test/r/row_test.result rename to mysql-test/r/row.result index f6e989789c7..e5bc5f4abe5 100644 --- a/mysql-test/r/row_test.result +++ b/mysql-test/r/row.result @@ -1,3 +1,9 @@ +select row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); +row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) +1 +select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); +row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) +0 SELECT ROW(1,2,3)=ROW(1,2,3); ROW(1,2,3)=ROW(1,2,3) 1 @@ -48,6 +54,16 @@ select * from t1 where ROW(1,2,3)result_type()) { + case STRING_RESULT: + if (item->binary()) + return new cmp_item_binary_string; + else + return new cmp_item_sort_string; + break; + case INT_RESULT: + return new cmp_item_int; + break; + case REAL_RESULT: + return new cmp_item_real; + break; + case ROW_RESULT: + return new cmp_item_row; + break; + } + return 0; // to satisfy compiler :) +} + +void cmp_item_row::store_value(Item *item) +{ + n= item->cols(); + if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n))) + { + for (uint i=0; i < n; i++) + if ((comparators[i]= cmp_item::get_comparator(item->el(i)))) + comparators[i]->store_value(item->el(i)); + else + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } + } + else + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } +} + +int cmp_item_row::cmp(Item *arg) +{ + for(uint i=0; i < n; i++) + if(comparators[i]->cmp(arg->el(i))) + return 1; + return 0; +} void Item_func_in::fix_length_and_dec() { - if (const_item()) + if (const_item() && item->result_type()!=ROW_RESULT) { switch (item->result_type()) { case STRING_RESULT: @@ -1155,24 +1207,7 @@ void Item_func_in::fix_length_and_dec() } else { - switch (item->result_type()) { - case STRING_RESULT: - if (item->binary()) - in_item= new cmp_item_binary_string; - else - in_item= new cmp_item_sort_string; - break; - case INT_RESULT: - in_item= new cmp_item_int; - break; - case REAL_RESULT: - in_item= new cmp_item_real; - break; - case ROW_RESULT: - // This case should never be choosen - DBUG_ASSERT(0); - break; - } + in_item= cmp_item:: get_comparator(item); } maybe_null= item->maybe_null; max_length=2; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index a18f5179169..d15e8856ece 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -38,16 +38,12 @@ public: Arg_comparator() {}; Arg_comparator(Item **a1, Item **a2): a(a1), b(a2) {}; - inline void seta(Item **item) { a= item; } - inline void setb(Item **item) { b= item; } - int set_compare_func(Item_bool_func2 *owner, Item_result type); inline int set_compare_func(Item_bool_func2 *owner) { return set_compare_func(owner, item_cmp_type((*a)->result_type(), (*b)->result_type())); } - inline int set_cmp_func(Item_bool_func2 *owner, Item **a1, Item **a2, Item_result type) @@ -437,6 +433,7 @@ public: virtual ~cmp_item() {} virtual void store_value(Item *item)=0; virtual int cmp(Item *item)=0; + static cmp_item* get_comparator(Item *); }; @@ -503,6 +500,14 @@ public: } }; +class cmp_item_row :public cmp_item +{ + cmp_item **comparators; + uint n; +public: + void store_value(Item *item); + int cmp(Item *arg); +}; class Item_func_in :public Item_int_func { @@ -512,12 +517,15 @@ class Item_func_in :public Item_int_func bool have_null; public: Item_func_in(Item *a,List &list) - :Item_int_func(list), item(a), array(0), in_item(0), have_null(0) {} + :Item_int_func(list), item(a), array(0), in_item(0), have_null(0) + { + allowed_arg_cols= item->cols(); + } longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->check_cols(1) || - item->fix_fields(thd, tlist, &item) || + // We do not check item->cols(), because allowed_arg_cols assigned from it + return (item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); From 814510d5474e7e94983ddc2584b2840ab851560d Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Sun, 8 Dec 2002 03:19:03 +0200 Subject: [PATCH 3/4] optimized IN with Rows (SCRUM) NULL with row (IN) cardinality error of row inside row new[] fixed layout --- mysql-test/r/row.result | 76 +++++++++++++--- mysql-test/t/row.test | 25 +++++- sql/item_cmpfunc.cc | 130 +++++++++++++++++++++++++-- sql/item_cmpfunc.h | 195 ++++++++++++++++++++++++++++++---------- sql/sql_list.h | 10 ++- 5 files changed, 367 insertions(+), 69 deletions(-) diff --git a/mysql-test/r/row.result b/mysql-test/r/row.result index e5bc5f4abe5..e0b524d9bb2 100644 --- a/mysql-test/r/row.result +++ b/mysql-test/r/row.result @@ -4,6 +4,35 @@ row(1,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) select row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)); row(10,2,3) IN (row(3,2,3), row(1,2,3), row(1,3,3)) 0 +select row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)); +row(1,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)) +1 +select row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)); +row(10,2,3) IN (row(3,NULL,3), row(1,2,3), row(1,3,3)) +NULL +select row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a')); +row('a',1.5,3) IN (row(1,2,3), row('a',1.5,3), row('a','a','a')) +1 +select row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3)); +row('a',0,3) IN (row(3,2,3), row('a','0','3'), row(1,3,3)) +1 +select row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3)); +row('a',0,3) IN (row(3,2,3), row('a','a','3'), row(1,3,3)) +1 +select row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); +row('a',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)) +1 +select row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)); +row('b',1.5,3) IN (row(3,NULL,3), row('a',1.5,3), row(1,3,3)) +NULL +select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4))); +row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,4))) +1 +select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,4)); +Cardinality error (more/less than 2 columns) +select row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))); +row(1,2,row(3,4)) IN (row(3,2,row(3,4)), row(1,2,row(3,NULL))) +NULL SELECT ROW(1,2,3)=ROW(1,2,3); ROW(1,2,3)=ROW(1,2,3) 1 @@ -42,9 +71,20 @@ ROW('test',2,3.33)=ROW('test',2,3.33) 1 SELECT ROW('test',2,3.33)=ROW('test',2,3.33,4); Cardinality error (more/less than 3 columns) +SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33)); +ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,33)) +1 +SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3)); +ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,3)) +0 +SELECT ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL)); +ROW('test',2,ROW(3,33))=ROW('test',2,ROW(3,NULL)) +NULL +SELECT ROW('test',2,ROW(3,33))=ROW('test',2,4); +Cardinality error (more/less than 2 columns) drop table if exists t1; create table t1 ( a int, b int, c int); -insert into t1 values (1,2,3), (2,3,1), (3,2,1); +insert into t1 values (1,2,3), (2,3,1), (3,2,1), (1,2,NULL); select * from t1 where ROW(1,2,3)=ROW(a,b,c); a b c 1 2 3 @@ -54,16 +94,30 @@ select * from t1 where ROW(1,2,3)cols() != (*a)->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), (*a)->cols()); + return 1; + } comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); + } else { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); @@ -1033,6 +1040,11 @@ static int cmp_double(double *a,double *b) return *a < *b ? -1 : *a == *b ? 0 : 1; } +static int cmp_row(cmp_item_row* a, cmp_item_row* b) +{ + return a->compare(b); +} + int in_vector::find(Item *item) { byte *result=get_value(item); @@ -1055,7 +1067,6 @@ int in_vector::find(Item *item) return (int) ((*compare)(base+start*size,result) == 0); } - in_string::in_string(uint elements,qsort_cmp cmp_func) :in_vector(elements,sizeof(String),cmp_func),tmp(buff,sizeof(buff),default_charset_info) {} @@ -1082,6 +1093,29 @@ byte *in_string::get_value(Item *item) return (byte*) item->val_str(&tmp); } +in_row::in_row(uint elements, Item * item) +{ + DBUG_ENTER("in_row::in_row"); + base= (char*) new cmp_item_row[elements]; + size= sizeof(cmp_item_row); + compare= (qsort_cmp) cmp_row; + tmp.store_value(item); + DBUG_VOID_RETURN; +} + +byte *in_row::get_value(Item *item) +{ + tmp.store_value(item); + return (byte *)&tmp; +} + +void in_row::set(uint pos, Item *item) +{ + DBUG_ENTER("in_row::set"); + DBUG_PRINT("enter", ("pos %u item 0x%lx", pos, (ulong) item)); + ((cmp_item_row*) base)[pos].store_value_by_template(&tmp, item); + DBUG_VOID_RETURN; +} in_longlong::in_longlong(uint elements) :in_vector(elements,sizeof(longlong),(qsort_cmp) cmp_longlong) @@ -1094,13 +1128,12 @@ void in_longlong::set(uint pos,Item *item) byte *in_longlong::get_value(Item *item) { - tmp=item->val_int(); + tmp= item->val_int(); if (item->null_value) - return 0; /* purecov: inspected */ + return 0; return (byte*) &tmp; } - in_double::in_double(uint elements) :in_vector(elements,sizeof(double),(qsort_cmp) cmp_double) {} @@ -1112,7 +1145,7 @@ void in_double::set(uint pos,Item *item) byte *in_double::get_value(Item *item) { - tmp=item->val(); + tmp= item->val(); if (item->null_value) return 0; /* purecov: inspected */ return (byte*) &tmp; @@ -1140,14 +1173,43 @@ cmp_item* cmp_item::get_comparator (Item *item) return 0; // to satisfy compiler :) } +cmp_item* cmp_item_sort_string::make_same() +{ + return new cmp_item_sort_string_in_static(); +} + +cmp_item* cmp_item_binary_string::make_same() +{ + return new cmp_item_binary_string_in_static(); +} + +cmp_item* cmp_item_int::make_same() +{ + return new cmp_item_int(); +} + +cmp_item* cmp_item_real::make_same() +{ + return new cmp_item_real(); +} + +cmp_item* cmp_item_row::make_same() +{ + return new cmp_item_row(); +} + void cmp_item_row::store_value(Item *item) { n= item->cols(); if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n))) { + item->null_value= 0; for (uint i=0; i < n; i++) if ((comparators[i]= cmp_item::get_comparator(item->el(i)))) + { comparators[i]->store_value(item->el(i)); + item->null_value|= item->el(i)->null_value; + } else { my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); @@ -1163,17 +1225,70 @@ void cmp_item_row::store_value(Item *item) } } +void cmp_item_row::store_value_by_template(cmp_item *t, Item *item) +{ + cmp_item_row *tmpl= (cmp_item_row*) t; + if (tmpl->n != item->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), tmpl->n); + return; + } + n= tmpl->n; + if ((comparators= (cmp_item **) sql_alloc(sizeof(cmp_item *)*n))) + { + item->null_value= 0; + for (uint i=0; i < n; i++) + if ((comparators[i]= tmpl->comparators[i]->make_same())) + { + comparators[i]->store_value_by_template(tmpl->comparators[i], + item->el(i)); + item->null_value|= item->el(i)->null_value; + } + else + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } + } + else + { + my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); + current_thd->fatal_error= 1; + return; + } +} + int cmp_item_row::cmp(Item *arg) { + arg->null_value= 0; + if (arg->cols() != n) + { + my_error(ER_CARDINALITY_COL, MYF(0), n); + return 1; + } for(uint i=0; i < n; i++) if(comparators[i]->cmp(arg->el(i))) + { + arg->null_value|= arg->el(i)->null_value; return 1; + } + return 0; +} + +int cmp_item_row::compare(cmp_item *c) +{ + int res; + cmp_item_row *cmp= (cmp_item_row *) c; + for(uint i=0; i < n; i++) + if((res= comparators[i]->compare(cmp->comparators[i]))) + return res; return 0; } void Item_func_in::fix_length_and_dec() { - if (const_item() && item->result_type()!=ROW_RESULT) + if (const_item()) { switch (item->result_type()) { case STRING_RESULT: @@ -1189,8 +1304,7 @@ void Item_func_in::fix_length_and_dec() array= new in_double(arg_count); break; case ROW_RESULT: - // This case should never be choosen - DBUG_ASSERT(0); + array= new in_row(arg_count, item); break; } uint j=0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index d15e8856ece..fbf0eb3c123 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -17,6 +17,8 @@ /* compare and test functions */ +#include "assert.h" + #ifdef __GNUC__ #pragma interface /* gcc class implementation */ #endif @@ -375,6 +377,7 @@ class in_vector :public Sql_alloc uint count; public: uint used_count; + in_vector() {} in_vector(uint elements,uint element_length,qsort_cmp cmp_func) :base((char*) sql_calloc(elements*element_length)), size(element_length), compare(cmp_func), count(elements), @@ -389,7 +392,6 @@ public: int find(Item *item); }; - class in_string :public in_vector { char buff[80]; @@ -401,7 +403,6 @@ public: byte *get_value(Item *item); }; - class in_longlong :public in_vector { longlong tmp; @@ -411,7 +412,6 @@ public: byte *get_value(Item *item); }; - class in_double :public in_vector { double tmp; @@ -421,7 +421,6 @@ public: byte *get_value(Item *item); }; - /* ** Classes for easy comparing of non const items */ @@ -431,73 +430,114 @@ class cmp_item :public Sql_alloc public: cmp_item() {} virtual ~cmp_item() {} - virtual void store_value(Item *item)=0; - virtual int cmp(Item *item)=0; + virtual void store_value(Item *item)= 0; + virtual int cmp(Item *item)= 0; + // for optimized IN with row + virtual int compare(cmp_item *item)= 0; static cmp_item* get_comparator(Item *); + virtual cmp_item *make_same()= 0; + virtual void store_value_by_template(cmp_item *tmpl, Item *item) + { + store_value(item); + } }; - -class cmp_item_sort_string :public cmp_item { - protected: - char value_buff[80]; - String value,*value_res; +class cmp_item_string :public cmp_item +{ +protected: + String *value_res; public: - cmp_item_sort_string() :value(value_buff,sizeof(value_buff),default_charset_info) {} + friend class cmp_item_sort_string; + friend class cmp_item_binary_string; + friend class cmp_item_sort_string_in_static; + friend class cmp_item_binary_string_in_static; +}; + +class cmp_item_sort_string :public cmp_item_string +{ +protected: + char value_buff[80]; + String value; +public: + cmp_item_sort_string(): + value(value_buff, sizeof(value_buff), default_charset_info) {} void store_value(Item *item) - { - value_res=item->val_str(&value); - } + { + value_res= item->val_str(&value); + } int cmp(Item *arg) - { - char buff[80]; - String tmp(buff,sizeof(buff),default_charset_info),*res; - if (!(res=arg->val_str(&tmp))) - return 1; /* Can't be right */ - return sortcmp(value_res,res); - } + { + char buff[80]; + String tmp(buff, sizeof(buff), default_charset_info), *res; + if (!(res= arg->val_str(&tmp))) + return 1; /* Can't be right */ + return sortcmp(value_res, res); + } + int compare(cmp_item *c) + { + cmp_item_string *cmp= (cmp_item_string *)c; + return sortcmp(value_res, cmp->value_res); + } + cmp_item *make_same(); }; class cmp_item_binary_string :public cmp_item_sort_string { public: cmp_item_binary_string() {} int cmp(Item *arg) - { - char buff[80]; - String tmp(buff,sizeof(buff),default_charset_info),*res; - if (!(res=arg->val_str(&tmp))) - return 1; /* Can't be right */ - return stringcmp(value_res,res); - } + { + char buff[80]; + String tmp(buff,sizeof(buff),default_charset_info),*res; + if (!(res=arg->val_str(&tmp))) + return 1; /* Can't be right */ + return stringcmp(value_res,res); + } + int compare(cmp_item *c) + { + cmp_item_string *cmp= (cmp_item_string *)c; + return stringcmp(value_res, cmp->value_res); + } + cmp_item *make_same(); }; - class cmp_item_int :public cmp_item { longlong value; public: void store_value(Item *item) - { - value=item->val_int(); - } + { + value= item->val_int(); + } int cmp(Item *arg) - { - return value != arg->val_int(); - } + { + return value != arg->val_int(); + } + int compare(cmp_item *c) + { + cmp_item_int *cmp= (cmp_item_int *)c; + return (value < cmp->value) ? -1 : ((value == cmp->value) ? 0 : 1); + } + cmp_item *make_same(); }; - class cmp_item_real :public cmp_item { double value; public: void store_value(Item *item) - { - value= item->val(); - } + { + value= item->val(); + } int cmp(Item *arg) - { - return value != arg->val(); - } + { + return value != arg->val(); + } + int compare(cmp_item *c) + { + cmp_item_real *cmp= (cmp_item_real *)c; + return (value < cmp->value)? -1 : ((value == cmp->value) ? 0 : 1); + } + cmp_item *make_same(); }; class cmp_item_row :public cmp_item @@ -505,8 +545,75 @@ class cmp_item_row :public cmp_item cmp_item **comparators; uint n; public: + cmp_item_row(): comparators(0), n(0) {} + ~cmp_item_row() + { + if(comparators) + for(uint i= 0; i < n; i++) + if (comparators[i]) + delete comparators[i]; + } void store_value(Item *item); int cmp(Item *arg); + int compare(cmp_item *arg); + cmp_item *make_same(); + void store_value_by_template(cmp_item *tmpl, Item *); +}; + + +class in_row :public in_vector +{ + cmp_item_row tmp; +public: + in_row(uint elements, Item *); + void set(uint pos,Item *item); + byte *get_value(Item *item); +}; + +/* + cmp_item for optimized IN with row (right part string, which never + be changed) +*/ + +class cmp_item_sort_string_in_static :public cmp_item_string +{ + protected: + String value; +public: + cmp_item_sort_string_in_static() {} + void store_value(Item *item) + { + value_res= item->val_str(&value); + } + int cmp(Item *item) + { + // Should never be called + DBUG_ASSERT(0); + return 1; + } + int compare(cmp_item *c) + { + cmp_item_string *cmp= (cmp_item_string *)c; + return sortcmp(value_res, cmp->value_res); + } + cmp_item * make_same() + { + return new cmp_item_sort_string_in_static(); + } +}; + +class cmp_item_binary_string_in_static :public cmp_item_sort_string_in_static { +public: + cmp_item_binary_string_in_static() {} + int compare(cmp_item *c) + { + cmp_item_string *cmp= (cmp_item_string *)c; + return stringcmp(value_res, cmp->value_res); + } + cmp_item * make_same() + { + return new cmp_item_binary_string_in_static(); + } }; class Item_func_in :public Item_int_func @@ -546,8 +653,6 @@ class Item_func_in :public Item_int_func } }; - - /* Functions used by where clause */ class Item_func_isnull :public Item_bool_func diff --git a/sql/sql_list.h b/sql/sql_list.h index 56e6528f214..1711a340cae 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -25,8 +25,16 @@ class Sql_alloc { public: - static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); } + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } + static void *operator new[](size_t size) + { + return (void*) sql_alloc((uint) size); + } static void operator delete(void *ptr, size_t size) {} /*lint -e715 */ + static void operator delete[](void *ptr, size_t size) {} #ifdef HAVE_purify bool dummy; inline Sql_alloc() :dummy(0) {} From 3172a45149140b60db335d1186b0bae54357b59b Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Sun, 8 Dec 2002 23:56:40 +0200 Subject: [PATCH 4/4] fixed typo in cardinality check of row items (SCRUM) --- sql/item_cmpfunc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 370feb65e3a..0bcda36338e 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -145,9 +145,9 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) if ((comparators= (Arg_comparator *) sql_alloc(sizeof(Arg_comparator)*n))) for (uint i=0; i < n; i++) { - if ((*a)->cols() != (*a)->cols()) + if ((*a)->el(i)->cols() != (*b)->el(i)->cols()) { - my_error(ER_CARDINALITY_COL, MYF(0), (*a)->cols()); + my_error(ER_CARDINALITY_COL, MYF(0), (*a)->el(i)->cols()); return 1; } comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));