summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorbell@sanja.is.com.ua <>2002-11-27 19:31:11 +0200
committerbell@sanja.is.com.ua <>2002-11-27 19:31:11 +0200
commit4be2cfd62d077590420e7b4d1ab006ae014738cc (patch)
treed1b07dc0628b773032c9602776d3da5f234266e5 /sql
parenta3ae370db8df2a10b5414d3c7dd54b69f1029d4b (diff)
parent5f2016bb20b3d5036f87d7fb3178894be81f430a (diff)
downloadmariadb-git-4be2cfd62d077590420e7b4d1ab006ae014738cc.tar.gz
merging
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am6
-rw-r--r--sql/filesort.cc11
-rw-r--r--sql/item.cc14
-rw-r--r--sql/item.h8
-rw-r--r--sql/item_cmpfunc.cc143
-rw-r--r--sql/item_cmpfunc.h104
-rw-r--r--sql/item_func.cc45
-rw-r--r--sql/item_func.h26
-rw-r--r--sql/item_row.cc66
-rw-r--r--sql/item_row.h65
-rw-r--r--sql/item_strfunc.cc4
-rw-r--r--sql/item_strfunc.h11
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_sum.cc23
-rw-r--r--sql/share/czech/errmsg.txt4
-rw-r--r--sql/share/danish/errmsg.txt2
-rw-r--r--sql/share/dutch/errmsg.txt2
-rw-r--r--sql/share/english/errmsg.txt2
-rw-r--r--sql/share/estonian/errmsg.txt2
-rw-r--r--sql/share/french/errmsg.txt2
-rw-r--r--sql/share/german/errmsg.txt2
-rw-r--r--sql/share/greek/errmsg.txt2
-rw-r--r--sql/share/hungarian/errmsg.txt2
-rw-r--r--sql/share/italian/errmsg.txt2
-rw-r--r--sql/share/japanese/errmsg.txt2
-rw-r--r--sql/share/korean/errmsg.txt2
-rw-r--r--sql/share/norwegian-ny/errmsg.txt2
-rw-r--r--sql/share/norwegian/errmsg.txt2
-rw-r--r--sql/share/polish/errmsg.txt2
-rw-r--r--sql/share/portuguese/errmsg.txt2
-rw-r--r--sql/share/romanian/errmsg.txt2
-rw-r--r--sql/share/russian/errmsg.txt2
-rw-r--r--sql/share/serbian/errmsg.txt2
-rw-r--r--sql/share/slovak/errmsg.txt2
-rw-r--r--sql/share/spanish/errmsg.txt2
-rw-r--r--sql/share/swedish/errmsg.txt2
-rw-r--r--sql/share/ukrainian/errmsg.txt6
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_lex.cc4
-rw-r--r--sql/sql_select.cc14
-rw-r--r--sql/sql_yacc.yy5
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; }