diff options
author | unknown <bell@sanja.is.com.ua> | 2002-11-15 20:32:09 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2002-11-15 20:32:09 +0200 |
commit | 3f742831211a4d53d97c5ac6ee402b4782de8776 (patch) | |
tree | bf6f2bb43cd9c75eef36dd94166c76c6b9d402af /sql | |
parent | 5a8c6a33c22ed68acdccbde0649420cd8a80ad9d (diff) | |
download | mariadb-git-3f742831211a4d53d97c5ac6ee402b4782de8776.tar.gz |
basic row Items (SCRUM)
include/mysql_com.h:
basic row Items
include/mysqld_error.h:
more wide error mening
libmysqld/Makefile.am:
basic row Items
mysql-test/r/subselect.result:
more wide error mening
sql/Makefile.am:
basic row Items
sql/filesort.cc:
basic row Items
sql/item.cc:
basic row Items
sql/item.h:
basic row Items
sql/item_cmpfunc.cc:
basic row Items
sql/item_cmpfunc.h:
basic row Items
sql/item_func.cc:
basic row Items
sql/item_func.h:
basic row Items
sql/item_strfunc.cc:
basic row Items
sql/item_strfunc.h:
basic row Items
sql/item_subselect.cc:
basic row Items
sql/item_sum.cc:
basic row Items
sql/share/czech/errmsg.txt:
more wide error mening
sql/share/danish/errmsg.txt:
more wide error mening
sql/share/dutch/errmsg.txt:
more wide error mening
sql/share/english/errmsg.txt:
more wide error mening
sql/share/estonian/errmsg.txt:
more wide error mening
sql/share/french/errmsg.txt:
more wide error mening
sql/share/german/errmsg.txt:
more wide error mening
sql/share/greek/errmsg.txt:
more wide error mening
sql/share/hungarian/errmsg.txt:
more wide error mening
sql/share/italian/errmsg.txt:
more wide error mening
sql/share/japanese/errmsg.txt:
more wide error mening
sql/share/korean/errmsg.txt:
more wide error mening
sql/share/norwegian-ny/errmsg.txt:
more wide error mening
sql/share/norwegian/errmsg.txt:
more wide error mening
sql/share/polish/errmsg.txt:
more wide error mening
sql/share/portuguese/errmsg.txt:
more wide error mening
sql/share/romanian/errmsg.txt:
more wide error mening
sql/share/russian/errmsg.txt:
more wide error mening
sql/share/serbian/errmsg.txt:
more wide error mening
sql/share/slovak/errmsg.txt:
more wide error mening
sql/share/spanish/errmsg.txt:
more wide error mening
sql/share/swedish/errmsg.txt:
more wide error mening
sql/share/ukrainian/errmsg.txt:
more wide error mening
sql/sql_base.cc:
fix_fields error handling
sql/sql_lex.cc:
basic row Items
sql/sql_select.cc:
basic row Items
sql/sql_yacc.yy:
basic row Items
Diffstat (limited to 'sql')
41 files changed, 484 insertions, 126 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am index 09fedd393c2..409613dbbbe 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -46,7 +46,8 @@ mysqld_LDADD = @MYSQLD_EXTRA_LDFLAGS@ \ $(LDADD) $(CXXLDFLAGS) $(WRAPLIBS) @LIBDL@ @openssl_libs@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ item_strfunc.h item_timefunc.h item_uniq.h \ - item_create.h item_subselect.h mysql_priv.h \ + item_create.h item_subselect.h item_row.h \ + mysql_priv.h \ procedure.h sql_class.h sql_lex.h sql_list.h \ sql_manager.h sql_map.h sql_string.h unireg.h \ field.h handler.h \ @@ -61,7 +62,8 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ mysqld_SOURCES = sql_lex.cc sql_handler.cc \ item.cc item_sum.cc item_buff.cc item_func.cc \ item_cmpfunc.cc item_strfunc.cc item_timefunc.cc \ - thr_malloc.cc item_create.cc item_subselect.cc\ + thr_malloc.cc item_create.cc item_subselect.cc \ + item_row.cc \ field.cc key.cc sql_class.cc sql_list.cc \ net_serv.cc net_pkg.cc lock.cc my_lock.c \ sql_string.cc sql_manager.cc sql_map.cc \ diff --git a/sql/filesort.cc b/sql/filesort.cc index 53af60b0370..8247b52ad1b 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -23,6 +23,7 @@ #endif #include <m_ctype.h> #include "sql_sort.h" +#include "assert.h" #ifndef THREAD #define SKIP_DBUG_IN_FILESORT @@ -579,6 +580,10 @@ static void make_sortkey(register SORTPARAM *param, change_double_for_sort(value,(byte*) to); break; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } if (sort_field->reverse) @@ -965,6 +970,9 @@ sortlength(SORT_FIELD *sortorder, uint s_length) case REAL_RESULT: sortorder->length=sizeof(double); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); } if (sortorder->item->maybe_null) length++; // Place for NULL marker diff --git a/sql/item.cc b/sql/item.cc index 48ec11d02c2..91c4e70cc8f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -58,6 +58,16 @@ bool Item::check_loop(uint id) DBUG_RETURN(0); } +bool Item::check_cols(uint c) +{ + if (c != 1) + { + my_error(ER_CARDINALITY_COL, MYF(0), 1); + return 1; + } + return 0; +} + void Item::set_name(const char *str,uint length) { if (!length) @@ -885,6 +895,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) maybe_null= (*ref)->maybe_null; decimals= (*ref)->decimals; } + if (ref && (*ref)->check_cols(1)) + return 1; return 0; } @@ -907,6 +919,8 @@ Item_result item_cmp_type(Item_result a,Item_result b) return STRING_RESULT; else if (a == INT_RESULT && b == INT_RESULT) return INT_RESULT; + else if (a == ROW_RESULT || b == ROW_RESULT) + return ROW_RESULT; else return REAL_RESULT; } diff --git a/sql/item.h b/sql/item.h index c67c16c50ad..192a908c347 100644 --- a/sql/item.h +++ b/sql/item.h @@ -34,7 +34,7 @@ public: INT_ITEM,REAL_ITEM,NULL_ITEM,VARBIN_ITEM, COPY_STR_ITEM,FIELD_AVG_ITEM, DEFAULT_ITEM, PROC_ITEM,COND_ITEM,REF_ITEM,FIELD_STD_ITEM, CONST_ITEM, - SUBSELECT_ITEM}; + SUBSELECT_ITEM, ROW_ITEM}; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; String str_value; /* used to store value */ @@ -87,10 +87,18 @@ public: virtual bool is_null() { return 0; }; virtual CHARSET_INFO *thd_charset() const; virtual CHARSET_INFO *charset() const { return str_value.charset(); }; - virtual bool binary() const { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } + virtual bool binary() const + { + return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0; + } virtual void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } virtual bool check_loop(uint id); + + // Row emulation + virtual uint cols() { return 1; } + virtual Item* el(uint i) { return this; } + virtual bool check_cols(uint c); }; @@ -469,6 +477,7 @@ public: #include "item_timefunc.h" #include "item_uniq.h" #include "item_subselect.h" +#include "item_row.h" class Item_copy_string :public Item { diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 744ed1bceca..5fca3566521 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -23,7 +23,7 @@ #include "mysql_priv.h" #include <m_ctype.h> - +#include "assert.h" /* Test functions @@ -83,7 +83,7 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[1])) { - cmp_func= &Item_bool_func2::compare_int; // Works for all types. + cmp_func= new Compare_func_int(this); // Works for all types. return; } } @@ -95,88 +95,115 @@ void Item_bool_func2::fix_length_and_dec() { if (convert_constant_item(field,&args[0])) { - cmp_func= &Item_bool_func2::compare_int; // Works for all types. + cmp_func= new Compare_func_int(this); // Works for all types. return; } } } - set_cmp_func(item_cmp_type(args[0]->result_type(),args[1]->result_type())); + set_cmp_func(args[0], args[1]); } - -void Item_bool_func2::set_cmp_func(Item_result type) +Compare_func* Compare_func::get_compare_func(Item_bool_func2 *owner, + Item *a, Item* b) { - switch (type) { + switch (item_cmp_type(a->result_type(), b->result_type())) + { case STRING_RESULT: - cmp_func=&Item_bool_func2::compare_string; - break; + return new Compare_func_string(owner); case REAL_RESULT: - cmp_func=&Item_bool_func2::compare_real; - break; + return new Compare_func_real(owner); case INT_RESULT: - cmp_func=&Item_bool_func2::compare_int; - break; + return new Compare_func_int(owner); + case ROW_RESULT: + return new Compare_func_row(owner, a, b); } + return 0; } +Compare_func_row::Compare_func_row(Item_bool_func2 *owner, Item *a, Item* b): + Compare_func(owner) +{ + uint n= a->cols(); + if (n != b->cols()) + { + my_error(ER_CARDINALITY_COL, MYF(0), n); + cmp_func= 0; + return; + } + cmp_func= (Compare_func **) sql_alloc(sizeof(Compare_func*)*n); + for(uint i=0; i < n; i++) + cmp_func[i]= Compare_func::get_compare_func(owner, a->el(i), b->el(i)); +} -int Item_bool_func2::compare_string() +int Compare_func_string::compare(Item *a, Item *b) { String *res1,*res2; - if ((res1=args[0]->val_str(&tmp_value1))) + if ((res1= a->val_str(&owner->tmp_value1))) { - if ((res2=args[1]->val_str(&tmp_value2))) + if ((res2= b->val_str(&owner->tmp_value2))) { - null_value=0; - return binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); + owner->null_value= 0; + return owner->binary() ? stringcmp(res1,res2) : sortcmp(res1,res2); } } - null_value=1; + owner->null_value= 1; return -1; } -int Item_bool_func2::compare_real() +int Compare_func_real::compare(Item *a, Item *b) { - double val1=args[0]->val(); - if (!args[0]->null_value) + double val1= a->val(); + if (!a->null_value) { - double val2=args[1]->val(); - if (!args[1]->null_value) + double val2= b->val(); + if (!b->null_value) { - null_value=0; + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - null_value=1; + owner->null_value= 1; return -1; } -int Item_bool_func2::compare_int() +int Compare_func_int::compare(Item *a, Item *b) { - longlong val1=args[0]->val_int(); - if (!args[0]->null_value) + longlong val1= a->val_int(); + if (!a->null_value) { - longlong val2=args[1]->val_int(); - if (!args[1]->null_value) + longlong val2= b->val_int(); + if (!b->null_value) { - null_value=0; + owner->null_value= 0; if (val1 < val2) return -1; if (val1 == val2) return 0; return 1; } } - null_value=1; + owner->null_value= 1; return -1; } - +int Compare_func_row::compare(Item *a, Item *b) +{ + int res= 0; + uint n= a->cols(); + for(uint i= 0; i<n; i++) + { + if ((res= cmp_func[i]->compare(a->el(i), b->el(i)))) + return res; + if (owner->null_value) + return -1; + } + return res; +} longlong Item_func_eq::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value == 0 ? 1 : 0; } @@ -218,6 +245,11 @@ longlong Item_func_equal::val_int() return test(args[0]->null_value && args[1]->null_value); return test(val1 == val2); } + case ROW_RESULT: + { + my_error(ER_WRONG_USAGE, MYF(0), "row", "<=>"); + return 0; + } } return 0; // Impossible } @@ -225,34 +257,34 @@ longlong Item_func_equal::val_int() longlong Item_func_ne::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value != 0 && !null_value ? 1 : 0; } longlong Item_func_ge::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value >= 0 ? 1 : 0; } longlong Item_func_gt::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value > 0 ? 1 : 0; } longlong Item_func_le::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value <= 0 && !null_value ? 1 : 0; } longlong Item_func_lt::val_int() { - int value=(this->*cmp_func)(); + int value= cmp_func->compare(args[0], args[1]); return value < 0 && !null_value ? 1 : 0; } @@ -595,7 +627,7 @@ double Item_func_nullif::val() { double value; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0.0; @@ -609,7 +641,7 @@ longlong Item_func_nullif::val_int() { longlong value; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0; @@ -623,7 +655,7 @@ String * Item_func_nullif::val_str(String *str) { String *res; - if (!(this->*cmp_func)() || null_value) + if (!cmp_func->compare(args[0], args[1]) || null_value) { null_value=1; return 0; @@ -702,6 +734,11 @@ Item *Item_func_case::find_item(String *str) } if (args[i]->val()==first_expr_real && !args[i]->null_value) return args[i+1]; + break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } // No, WHEN clauses all missed, return ELSE expression @@ -764,8 +801,10 @@ double Item_func_case::val() bool Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) || - else_expr && else_expr->fix_fields(thd, tables, &else_expr)) + if (first_expr && (first_expr->check_cols(1) || + first_expr->fix_fields(thd, tables, &first_expr)) || + else_expr && (else_expr->check_cols(1) || + else_expr->fix_fields(thd, tables, &else_expr))) return 1; if (Item_func::fix_fields(thd, tables, ref)) return 1; @@ -1007,6 +1046,10 @@ void Item_func_in::fix_length_and_dec() case REAL_RESULT: array= new in_double(arg_count); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } uint j=0; for (uint i=0 ; i < arg_count ; i++) @@ -1033,6 +1076,10 @@ void Item_func_in::fix_length_and_dec() case REAL_RESULT: in_item= new cmp_item_real; break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } } maybe_null= item->maybe_null; @@ -1141,7 +1188,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) #endif item= *li.ref(); // new current item } - if (item->fix_fields(thd, tables, li.ref())) + if (item->check_cols(1) || item->fix_fields(thd, tables, li.ref())) return 1; /* purecov: inspected */ used_tables_cache|=item->used_tables(); with_sum_func= with_sum_func || item->with_sum_func; @@ -1390,7 +1437,9 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref) bool Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) { - if (args[0]->fix_fields(thd, tables, args) || + if (args[0]->check_cols(1) || + args[1]->check_cols(1) || + args[0]->fix_fields(thd, tables, args) || args[1]->fix_fields(thd,tables, args + 1)) return 1; /* purecov: inspected */ with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 489d54ae786..dd1cf8d6da6 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -30,6 +30,61 @@ public: void fix_length_and_dec() { decimals=0; max_length=1; } }; +class Item_bool_func2; + +class Compare_func +{ +protected: + Item_bool_func2 *owner; +public: + static void *operator new(size_t size) + { + return (void*) sql_alloc((uint) size); + } + static void operator delete(void *ptr,size_t size) {} + + Compare_func(Item_bool_func2 *o) { owner= o; } + virtual ~Compare_func() {}; + virtual int compare(Item *, Item*)= 0; + + static Compare_func* get_compare_func(Item_bool_func2 *owner, + Item* a, Item* b); +}; + +class Compare_func_string: public Compare_func +{ +public: + Compare_func_string(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_real: public Compare_func +{ +public: + Compare_func_real(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_int: public Compare_func +{ +public: + Compare_func_int(Item_bool_func2 *owner): Compare_func(owner) {}; + int compare(Item *, Item*); +}; + +class Compare_func_row: public Compare_func +{ + Compare_func **cmp_func; +public: + Compare_func_row(Item_bool_func2 *owner, Item* a, Item* b); + ~Compare_func_row() + { + if(cmp_func) + sql_element_free(cmp_func); + } + int compare(Item *, Item*); +}; + class Item_bool_func2 :public Item_int_func { /* Bool with 2 string args */ protected: @@ -37,18 +92,28 @@ protected: public: Item_bool_func2(Item *a,Item *b) :Item_int_func(a,b) {} void fix_length_and_dec(); - void set_cmp_func(Item_result type); - int (Item_bool_func2::*cmp_func)(); - int compare_string(); /* compare arg[0] & arg[1] */ - int compare_real(); /* compare arg[0] & arg[1] */ - int compare_int(); /* compare arg[0] & arg[1] */ + Compare_func *cmp_func; + void set_cmp_func(Item *a, Item *b) + { + cmp_func= Compare_func::get_compare_func(this, args[0], args[1]); + } optimize_type select_optimize() const { return OPTIMIZE_OP; } virtual enum Functype rev_functype() const { return UNKNOWN_FUNC; } bool have_rev_func() const { return rev_functype() != UNKNOWN_FUNC; } void print(String *str) { Item_func::print_op(str); } bool is_null() { return test(args[0]->is_null() || args[1]->is_null()); } + + friend class Compare_func_string; }; +class Item_bool_rowready_func2 :public Item_bool_func2 +{ +public: + Item_bool_rowready_func2(Item *a,Item *b) :Item_bool_func2(a,b) + { + allowed_arg_cols= a->cols(); + } +}; class Item_func_not :public Item_bool_func { @@ -58,10 +123,10 @@ public: const char *func_name() const { return "not"; } }; -class Item_func_eq :public Item_bool_func2 +class Item_func_eq :public Item_bool_rowready_func2 { public: - Item_func_eq(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_eq(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return EQ_FUNC; } enum Functype rev_functype() const { return EQ_FUNC; } @@ -83,10 +148,10 @@ public: }; -class Item_func_ge :public Item_bool_func2 +class Item_func_ge :public Item_bool_rowready_func2 { public: - Item_func_ge(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_ge(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return GE_FUNC; } enum Functype rev_functype() const { return LE_FUNC; } @@ -95,10 +160,10 @@ public: }; -class Item_func_gt :public Item_bool_func2 +class Item_func_gt :public Item_bool_rowready_func2 { public: - Item_func_gt(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_gt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return GT_FUNC; } enum Functype rev_functype() const { return LT_FUNC; } @@ -107,10 +172,10 @@ public: }; -class Item_func_le :public Item_bool_func2 +class Item_func_le :public Item_bool_rowready_func2 { public: - Item_func_le(Item *a,Item *b) :Item_bool_func2(a,b) { }; + Item_func_le(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { }; longlong val_int(); enum Functype functype() const { return LE_FUNC; } enum Functype rev_functype() const { return GE_FUNC; } @@ -119,10 +184,10 @@ public: }; -class Item_func_lt :public Item_bool_func2 +class Item_func_lt :public Item_bool_rowready_func2 { public: - Item_func_lt(Item *a,Item *b) :Item_bool_func2(a,b) { } + Item_func_lt(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { } longlong val_int(); enum Functype functype() const { return LT_FUNC; } enum Functype rev_functype() const { return GT_FUNC; } @@ -131,10 +196,10 @@ public: }; -class Item_func_ne :public Item_bool_func2 +class Item_func_ne :public Item_bool_rowready_func2 { public: - Item_func_ne(Item *a,Item *b) :Item_bool_func2(a,b) { } + Item_func_ne(Item *a,Item *b) :Item_bool_rowready_func2(a,b) { } longlong val_int(); enum Functype functype() const { return NE_FUNC; } cond_result eq_cmp_result() const { return COND_FALSE; } @@ -179,7 +244,8 @@ public: longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); @@ -414,7 +480,8 @@ class Item_func_in :public Item_int_func longlong val_int(); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); diff --git a/sql/item_func.cc b/sql/item_func.cc index aa39b3cc857..36a804e600c 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -39,7 +39,8 @@ eval_const_cond(COND *cond) } -Item_func::Item_func(List<Item> &list) +Item_func::Item_func(List<Item> &list): + allowed_arg_cols(1) { arg_count=list.elements; if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count))) @@ -111,7 +112,8 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) set_charset((*args)->charset()); for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) { - if ((*arg)->fix_fields(thd, tables, arg)) + if ((*arg)->check_cols(allowed_arg_cols) || + (*arg)->fix_fields(thd, tables, arg)) return 1; /* purecov: inspected */ if ((*arg)->maybe_null) maybe_null=1; @@ -248,6 +250,10 @@ Field *Item_func::tmp_table_field(TABLE *t_arg) else res= new Field_string(max_length, maybe_null, name, t_arg, charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return res; } @@ -869,6 +875,11 @@ String *Item_func_min_max::val_str(String *str) } return res; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; + } return 0; // Keep compiler happy } @@ -1276,7 +1287,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func, arg != arg_end ; arg++,i++) { - if ((*arg)->fix_fields(thd, tables, arg)) + if ((*arg)->check_cols(1) || (*arg)->fix_fields(thd, tables, arg)) return 1; if ((*arg)->binary()) func->set_charset(my_charset_bin); @@ -1405,6 +1416,10 @@ bool udf_handler::get_arguments() to+= ALIGN_SIZE(sizeof(double)); } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + ; } } return 0; @@ -1857,6 +1872,10 @@ longlong Item_func_benchmark::val_int() case STRING_RESULT: (void) args[0]->val_str(&tmp); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } return 0; @@ -1983,11 +2002,17 @@ Item_func_set_user_var::update() (void) val_int(); break; case STRING_RESULT: + { char buffer[MAX_FIELD_WIDTH]; String tmp(buffer,sizeof(buffer),default_charset_info); (void) val_str(&tmp); break; } + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } return current_thd->fatal_error; } @@ -2062,6 +2087,10 @@ Item_func_get_user_var::val_str(String *str) return NULL; } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return str; } @@ -2079,6 +2108,10 @@ double Item_func_get_user_var::val() return (double) *(longlong*) entry->value; case STRING_RESULT: return atof(entry->value); // This is null terminated + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return 0.0; // Impossible } @@ -2096,6 +2129,10 @@ longlong Item_func_get_user_var::val_int() return *(longlong*) entry->value; case STRING_RESULT: return strtoull(entry->value,NULL,10); // String is null terminated + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return LL(0); // Impossible } @@ -2256,7 +2293,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) while ((item=li++)) { - if (item->fix_fields(thd, tlist, li.ref())) + if (item->check_cols(1) || item->fix_fields(thd, tlist, li.ref())) return 1; if (item->type() == Item::REF_ITEM) li.replace(item= *((Item_ref *)item)->ref); diff --git a/sql/item_func.h b/sql/item_func.h index 581809fc9cb..ce05eb0d1d8 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -32,6 +32,7 @@ class Item_func :public Item_result_field { protected: Item **args,*tmp_arg[2]; + uint allowed_arg_cols; public: uint arg_count; table_map used_tables_cache; @@ -49,25 +50,27 @@ public: enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL }; enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } - Item_func(void) + Item_func(void): + allowed_arg_cols(1), arg_count(0) { - arg_count=0; with_sum_func=0; + with_sum_func=0; } - Item_func(Item *a) + Item_func(Item *a): + allowed_arg_cols(1), arg_count(1) { - arg_count=1; args=tmp_arg; args[0]=a; with_sum_func=a->with_sum_func; } - Item_func(Item *a,Item *b) + Item_func(Item *a,Item *b): + allowed_arg_cols(1), arg_count(2) { - arg_count=2; args=tmp_arg; args[0]=a; args[1]=b; with_sum_func=a->with_sum_func || b->with_sum_func; } - Item_func(Item *a,Item *b,Item *c) + Item_func(Item *a,Item *b,Item *c): + allowed_arg_cols(1) { arg_count=0; if ((args=(Item**) sql_alloc(sizeof(Item*)*3))) @@ -77,7 +80,8 @@ public: with_sum_func=a->with_sum_func || b->with_sum_func || c->with_sum_func; } } - Item_func(Item *a,Item *b,Item *c,Item *d) + Item_func(Item *a,Item *b,Item *c,Item *d): + allowed_arg_cols(1) { arg_count=0; if ((args=(Item**) sql_alloc(sizeof(Item*)*4))) @@ -88,7 +92,8 @@ public: d->with_sum_func; } } - Item_func(Item *a,Item *b,Item *c,Item *d,Item* e) + Item_func(Item *a,Item *b,Item *c,Item *d,Item* e): + allowed_arg_cols(1) { arg_count=5; if ((args=(Item**) sql_alloc(sizeof(Item*)*5))) @@ -590,7 +595,8 @@ public: longlong val_int(); bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void update_used_tables() diff --git a/sql/item_row.cc b/sql/item_row.cc new file mode 100644 index 00000000000..95da4f5901e --- /dev/null +++ b/sql/item_row.cc @@ -0,0 +1,66 @@ +/* Copyright (C) 2000 MySQL AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "mysql_priv.h" +#include "assert.h" + +Item_row::Item_row(List<Item> &arg): + Item(), array_holder(1) +{ + if ((arg_count= arg.elements)) + items= (Item**) sql_alloc(sizeof(Item*)*arg_count); + else + items= 0; + List_iterator<Item> li(arg); + uint i= 0; + Item *item; + while ((item= li++)) + { + items[i]= item; + i++; + } +} + +void Item_row::illegal_method_call(const char *method) +{ + DBUG_ENTER("Item_row::illegal_method_call"); + DBUG_PRINT("error", ("!!! %s method was called for row item", method)); + DBUG_ASSERT(0); + my_error(ER_CARDINALITY_COL, MYF(0), arg_count); + DBUG_VOID_RETURN; +} + +bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref) +{ + tables= 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(); + } + return 0; +} + +bool Item_row::check_cols(uint c) +{ + if (c != arg_count) + { + my_error(ER_CARDINALITY_COL, MYF(0), arg_count); + return 1; + } + return 0; +} diff --git a/sql/item_row.h b/sql/item_row.h new file mode 100644 index 00000000000..6970b240b31 --- /dev/null +++ b/sql/item_row.h @@ -0,0 +1,65 @@ +/* Copyright (C) 2000 MySQL AB + + 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; either version 2 of the License, or + (at your option) any later version. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +class Item_row: public Item +{ + bool array_holder; + table_map tables; + uint arg_count; + Item **items; +public: + Item_row(List<Item> &); + Item_row(Item_row *item): + Item(), array_holder(0), tables(item->tables), arg_count(item->arg_count), + items(item->items) + {} + + ~Item_row() + { + if(array_holder && items) + sql_element_free(items); + } + + enum Type type() const { return ROW_ITEM; }; + void illegal_method_call(const char *); + bool is_null() { return null_value; } + void make_field(Send_field *) + { + illegal_method_call((const char*)"make_field"); + }; + double val() + { + illegal_method_call((const char*)"val"); + return 0; + }; + longlong val_int() + { + illegal_method_call((const char*)"val_int"); + return 0; + }; + String *val_str(String *) + { + illegal_method_call((const char*)"val_str"); + return 0; + }; + bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + table_map used_tables() const { return tables; }; + enum Item_result result_type() const { return ROW_RESULT; } + + virtual uint cols() { return arg_count; } + virtual Item* el(uint i) { return items[i]; } + virtual bool check_cols(uint c); +}; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1a561c9eb34..01958f81deb 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2059,7 +2059,7 @@ bool Item_func_conv_charset::fix_fields(THD *thd,struct st_table_list *tables, I if (thd && check_stack_overrun(thd,buff)) return 0; // Fatal error if flag is set! - if (args[0]->fix_fields(thd, tables, args)) + if (args[0]->check_cols(1) || args[0]->fix_fields(thd, tables, args)) return 1; maybe_null=args[0]->maybe_null; const_item_cache=args[0]->const_item(); @@ -2091,7 +2091,7 @@ bool Item_func_set_collation::fix_fields(THD *thd,struct st_table_list *tables, if (thd && check_stack_overrun(thd,buff)) return 0; // Fatal error if flag is set! - if (args[0]->fix_fields(thd, tables, args)) + if (args[0]->check_cols(1) || args[0]->fix_fields(thd, tables, args)) return 1; maybe_null=args[0]->maybe_null; set_charset(set_collation); diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 2b308630b48..60462621630 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -101,8 +101,9 @@ public: void update_used_tables(); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (separator->fix_fields(thd, tlist, &separator) - || Item_func::fix_fields(thd, tlist, ref)); + return (separator->check_cols(1) || + separator->fix_fields(thd, tlist, &separator) || + Item_func::fix_fields(thd, tlist, ref)); } const char *func_name() const { return "concat_ws"; } bool check_loop(uint id) @@ -362,7 +363,8 @@ public: String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); @@ -389,7 +391,8 @@ public: String *val_str(String *str); bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { - return (item->fix_fields(thd, tlist, &item) || + return (item->check_cols(1) || + item->fix_fields(thd, tlist, &item) || Item_func::fix_fields(thd, tlist, ref)); } void fix_length_and_dec(); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 1f1944026ef..0d7f77fb283 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -87,7 +87,7 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) // Is it one field subselect? if (engine->cols() > max_columns) { - my_message(ER_SUBSELECT_NO_1_COL, ER(ER_SUBSELECT_NO_1_COL), MYF(0)); + my_error(ER_CARDINALITY_COL, MYF(0), 1); return 1; } fix_length_and_dec(); diff --git a/sql/item_sum.cc b/sql/item_sum.cc index db4c45fc412..5e1b30dfddf 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -22,7 +22,7 @@ #endif #include "mysql_priv.h" - +#include "assert.h" Item_sum::Item_sum(List<Item> &list) { @@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) maybe_null=0; for (uint i=0 ; i < arg_count ; i++) { - if (args[i]->fix_fields(thd, tables, args + i)) + if (args[i]->check_cols(1) || args[i]->fix_fields(thd, tables, args + i)) return 1; if (decimals < args[i]->decimals) decimals=args[i]->decimals; @@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return 1; } thd->allow_sum_func=0; // No included group funcs - if (item->fix_fields(thd, tables, args)) + if (item->check_cols(1) || item->fix_fields(thd, tables, args)) return 1; hybrid_type=item->result_type(); if (hybrid_type == INT_RESULT) @@ -336,6 +336,10 @@ double Item_sum_hybrid::val() return (double) sum_int; case REAL_RESULT: return sum; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } return 0; // Keep compiler happy } @@ -367,6 +371,10 @@ Item_sum_hybrid::val_str(String *str) else str->set((longlong) sum_int,thd_charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return str; // Keep compiler happy } @@ -409,6 +417,10 @@ bool Item_sum_min::add() } } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return 0; } @@ -452,6 +464,11 @@ bool Item_sum_max::add() } } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; + } return 0; } diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index d43a433da06..2ef5dc43180 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -1,4 +1,4 @@ -/* +v/* Modifikoval Petr -B╘najdr, snajdr@pvt.net, snajdr@cpress.cz v.0.01 -A ISO LATIN-8852-2 Dal-B╧М verze Jan Pazdziora, adelton@fi.muni.cz-A @@ -249,7 +249,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 3a947bcbe38..74d8dadaf72 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 1cb81849be1..5c8261fc07d 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -251,7 +251,7 @@ "Kreeg fatale fout %d: '%-.128s' van master tijdens lezen van data uit binaire log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 6e96fdb393e..89789669612 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 394c40c5778..f1716831b2a 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -245,7 +245,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index b18d3f8fb38..ab07311aa5e 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 49ea31dd05b..028297531fa 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect return more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect return more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index b203c63949b..240a0119f84 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 07081e689ad..63f61a3ca5a 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 0a380e2b48f..569e6d1cacb 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 2e0a083ca06..96eb983cc5d 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 19fcf98e3c7..4f68c071d58 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 810aaf38f74..cda119773d9 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index a74a0a910b8..11f2cffd896 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -242,7 +242,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index efde31ff4c9..63079565d83 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -244,7 +244,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index e90d5844b9b..64eee8c525f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 18f0bf7f79d..3461df87734 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -244,7 +244,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 790d738031c..06e44722cf5 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -243,7 +243,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Подзапрос возвращает более одного поля", +"Ошибка мощьности множества (больше/меньше %d колонок)", "Подзапрос возвращает более одной записи", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index e8186d38a5b..f7438457660 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -236,7 +236,7 @@ "User '%-.64s' has exceeded the '%s' resource (current value: %ld)", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 216d46fcd3a..8db9dd7770b 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -248,7 +248,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 5076b1b6679..19377803257 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -241,7 +241,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index a3bb40fb4f5..e12a30ed422 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -240,7 +240,7 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Subselect returns more than 1 field", +"Cardinality error (more/less than %d columns)", "Subselect returns more than 1 record", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 426c2a14e3b..a824fd1cdd8 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -245,8 +245,8 @@ "Got fatal error %d: '%-.128s' from master when reading data from binary log", "Wrong foreign key definition for '%-.64s': %s", "Key reference and table reference doesn't match", -"Пiдзапит поверта╓ бiльш нiж 1 стовбець", -"Пiдзапит поверта╓ бiльш нiж 1 запис", +"Cardinality error (б╕льше/меньше н╕ж %d стовбц╕в)", +"П╕дзапит поверта╓ б╕льш нiж 1 запис", "Unknown prepared statement handler (%ld) given to %s", "Help database is corrupt or does not exist", -"Циклiчне посилання на пiдзапит", +"Цикл╕чне посилання на п╕дзапит", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fd6c2c48020..c50298292ac 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2027,7 +2027,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, thd->used_tables|=item->used_tables(); } } - DBUG_RETURN(test(thd->fatal_error)); + DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); } @@ -2239,7 +2239,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) table->on_expr=and_conds(table->on_expr,cond_and); } } - DBUG_RETURN(test(thd->fatal_error)); + DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 0865e6da05f..5da2066cfb9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -191,6 +191,10 @@ static int find_keyword(LEX *lex, uint len, bool function) return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM; case INT_RESULT: return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } #endif diff --git a/sql/sql_select.cc b/sql/sql_select.cc index b3838628d35..a3672e47d42 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3317,8 +3317,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(), - func->arguments()[1]->result_type())); + func->set_cmp_func(func->arguments()[0],func->arguments()[1]); } } else if (left_item->eq(field,0) && right_item != value) @@ -3338,8 +3337,7 @@ change_cond_ref_to_const(I_List<COND_CMP> *save_list,Item *and_father, if ((tmp2=new COND_CMP(and_father,func))) save_list->push_back(tmp2); } - func->set_cmp_func(item_cmp_type(func->arguments()[0]->result_type(), - func->arguments()[1]->result_type())); + func->set_cmp_func(func->arguments()[0], func->arguments()[1]); } } } @@ -3679,6 +3677,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, item->name,table,item->charset()); return new Field_string(item_sum->max_length,maybe_null, item->name,table,item->charset()); + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + return 0; } } thd->fatal_error=1; @@ -3735,6 +3737,10 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, new_field= new Field_string(item->max_length,maybe_null, item->name,table,item->str_value.charset()); break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } if (copy_func) *((*copy_func)++) = (Item_result_field*) item; // Save for copy_funcs diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d432a76770d..1a2a3e9f37e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1873,6 +1873,11 @@ simple_expr: | NOT expr %prec NEG { $$= new Item_func_not($2); } | '!' expr %prec NEG { $$= new Item_func_not($2); } | '(' expr ')' { $$= $2; } + | '(' expr ',' expr_list ')' + { + $4->push_front($2); + $$= new Item_row(*$4); + } | EXISTS exists_subselect { $$= $2; } | singleval_subselect { $$= $1; } | '{' ident expr '}' { $$= $3; } |