diff options
author | bell@sanja.is.com.ua <> | 2002-11-27 19:31:11 +0200 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2002-11-27 19:31:11 +0200 |
commit | 4be2cfd62d077590420e7b4d1ab006ae014738cc (patch) | |
tree | d1b07dc0628b773032c9602776d3da5f234266e5 /sql | |
parent | a3ae370db8df2a10b5414d3c7dd54b69f1029d4b (diff) | |
parent | 5f2016bb20b3d5036f87d7fb3178894be81f430a (diff) | |
download | mariadb-git-4be2cfd62d077590420e7b4d1ab006ae014738cc.tar.gz |
merging
Diffstat (limited to 'sql')
41 files changed, 481 insertions, 126 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am index 828e74c67fc..c5af51e8397 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -45,7 +45,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 \ @@ -60,7 +61,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 fab666a1203..97e06997617 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 @@ -83,7 +84,7 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length, #endif // BAR TODO: this is not absolutely correct, but OK for now - for(i=0;i<table->fields;i++) + for (i=0;i<table->fields;i++) if (!table->field[i]->binary()) charset=table->field[i]->charset(); // /BAR TODO @@ -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,10 @@ 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); + break; } if (sortorder->item->maybe_null) length++; // Place for NULL marker diff --git a/sql/item.cc b/sql/item.cc index ece627f9fe3..346bc545ef3 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -59,6 +59,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) @@ -1010,6 +1020,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) return 1; } fixed= 1; + if (ref && (*ref)->check_cols(1)) + return 1; return 0; } @@ -1032,6 +1044,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 414dcfbc328..9ff2b78eb04 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 */ @@ -94,6 +94,11 @@ public: CHARSET_INFO *thd_charset() const; CHARSET_INFO *charset() const { return str_value.charset(); }; void set_charset(CHARSET_INFO *cs) { str_value.set_charset(cs); } + + // Row emulation + virtual uint cols() { return 1; } + virtual Item* el(uint i) { return this; } + virtual bool check_cols(uint c); }; @@ -520,6 +525,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 178eeab1e5a..b1cbe405e73 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" Item_bool_func2* Item_bool_func2::eq_creator(Item *a, Item *b) { return new Item_func_eq(a, b); @@ -107,7 +107,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; } } @@ -119,88 +119,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; } @@ -242,6 +269,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 } @@ -249,34 +281,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; } @@ -625,7 +657,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; @@ -639,7 +671,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; @@ -653,7 +685,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; @@ -732,6 +764,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 @@ -794,8 +831,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; @@ -1037,6 +1076,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++) @@ -1063,6 +1106,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; @@ -1173,7 +1220,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) } if (abort_on_null) item->top_level_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; @@ -1475,7 +1522,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 f1e51e674e9..8f7bfa0fda4 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,17 +92,18 @@ 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; static Item_bool_func2* eq_creator(Item *a, Item *b); static Item_bool_func2* ne_creator(Item *a, Item *b); static Item_bool_func2* gt_creator(Item *a, Item *b); @@ -56,6 +112,14 @@ public: static Item_bool_func2* le_creator(Item *a, Item *b); }; +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 { @@ -65,10 +129,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; } @@ -90,10 +154,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; } @@ -102,10 +166,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; } @@ -114,10 +178,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; } @@ -126,10 +190,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; } @@ -138,10 +202,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; } @@ -186,7 +250,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(); @@ -426,7 +491,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 2af26e2fd9a..364bea4c1f5 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; @@ -249,6 +251,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; } @@ -890,6 +896,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 } @@ -1297,7 +1308,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); @@ -1426,6 +1437,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; @@ -1878,6 +1893,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; @@ -2004,11 +2023,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; } @@ -2083,6 +2108,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; } @@ -2100,6 +2129,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 } @@ -2117,6 +2150,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 } @@ -2277,7 +2314,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 38f461acc13..43fb28e77e8 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))) @@ -602,7 +607,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 fc3b4da8561..7eb7e57a8ca 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2061,7 +2061,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(); @@ -2094,7 +2094,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 9fd9143586e..457bc2e7648 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 555b7ae45c3..1e016da9ec0 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -96,7 +96,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 567b5ee6ffa..6b13cac94ca 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) { arg_count=list.elements; @@ -127,7 +127,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; @@ -153,7 +153,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) @@ -341,6 +341,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 } @@ -372,6 +376,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 } @@ -414,6 +422,10 @@ bool Item_sum_min::add() } } break; + case ROW_RESULT: + // This case should never be choosen + DBUG_ASSERT(0); + break; } return 0; } @@ -457,6 +469,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 4838de12ed6..74ee4579f8f 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 91fa06f184f..a045eea36cd 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 50c70ce0d2c..0a03769b4ce 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 1c5564b9ad5..4118e2cc077 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 8a49cc7fb69..78d6fce3472 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 a8b602ee295..3eb80c96883 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 cb449738d61..2eaca078a5b 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 f6c650468b1..be464a6e334 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 fe47d79a101..9ba2847eb43 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 0d951857392..e6bb8cf2548 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 df78901a6e9..f36b838e858 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 c20110e1aa5..7aca245c3c9 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 c75c3ed6140..630c4cb5ac3 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 b5a660773ab..fe4e00f7d97 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 c65a16bf1e4..565469e46ce 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 355ae90c157..8ab11ea8350 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 c7a5b41deac..b502cf43d96 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 35134e6d9d5..f64a6c1f21d 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 354c0bdfac4..f5892ce1a53 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 4f49aeb2f6e..5190cfdc297 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 1bd4aed6897..27ac07c24b6 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 af3f7ca33dd..9b38ee1b068 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -240,7 +240,7 @@ "Fick fatalt fel %d: '%-.128s' från master vid läsning av binär loggen", "Felaktig FOREIGN KEY definition för '%-.64s': %s", "Nyckel referensen och table referensen stämmer inte överens", -"Subselect returnerade mer än 1 fält", +"Cardinality error (more/less than %d columns)", "Subselect returnerade mer än 1 rad", "Okänd PREPARED STATEMENT id (%ld) var given till %s", "Hjälp databasen finns inte eller är skadad", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index c5bfff130fd..cac0cf8f526 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -245,10 +245,10 @@ "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ÄÚÁÐÉÔ", +"ãÉË̦ÞÎÅ ÐÏÓÉÌÁÎÎÑ ÎÁ ЦÄÚÁÐÉÔ", "ðÅÒÅÔ×ÏÒÅÎÎÑ ÓÔÏ×ÂÃÁ '%s' Ú %s Õ %s", "ðÏÓÉÌÁÎÎÑ '%-.64s' ÎÅ ÐiÄÔÒÉÍÕÅÔÓÑ (%s)", diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 8aa33a65ce3..ba86b524401 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2110,7 +2110,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)); } @@ -2324,7 +2324,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 5104487c700..65644b93331 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -207,6 +207,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 bb7f23a6710..3c063428509 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -3340,8 +3340,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) @@ -3361,8 +3360,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]); } } } @@ -3702,6 +3700,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; @@ -3758,6 +3760,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 cb1c7fed838..216cd52d408 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1973,6 +1973,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; } |