summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authormonty@narttu.mysql.fi <>2003-06-04 18:28:51 +0300
committermonty@narttu.mysql.fi <>2003-06-04 18:28:51 +0300
commit23145cfed72954c29f5a47e82af22898164be4b0 (patch)
treef2e86edc169afb1fed9cecefdecd9f13561780c9 /sql
parent7df5635ff2845bd708711f6b790997a3c68d5f2a (diff)
downloadmariadb-git-23145cfed72954c29f5a47e82af22898164be4b0.tar.gz
Added SQLSTATE to client/server protocol
bmove_allign -> bmove_align Added OLAP function ROLLUP Split mysql_fix_privilege_tables to a script and a .sql data file Added new (MEMROOT*) functions to avoid calling current_thd() when creating some common objects. Added table_alias_charset, for easier --lower-case-table-name handling Better SQL_MODE handling (Setting complex options also sets sub options) New (faster) assembler string functions for x86
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am3
-rw-r--r--sql/item.cc34
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_sum.cc160
-rw-r--r--sql/item_sum.h79
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/mysql_priv.h10
-rw-r--r--sql/mysqld.cc68
-rw-r--r--sql/net_serv.cc7
-rw-r--r--sql/protocol.cc7
-rw-r--r--sql/set_var.cc133
-rw-r--r--sql/set_var.h6
-rw-r--r--sql/sql_base.cc27
-rw-r--r--sql/sql_cache.cc3
-rw-r--r--sql/sql_list.h3
-rw-r--r--sql/sql_prepare.cc2
-rw-r--r--sql/sql_select.cc489
-rw-r--r--sql/sql_select.h49
-rw-r--r--sql/sql_show.cc27
-rw-r--r--sql/sql_state.c53
-rw-r--r--sql/sql_string.cc4
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_table.cc5
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy19
-rw-r--r--sql/unireg.h4
26 files changed, 897 insertions, 306 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 608b959a8b9..1d8e8cde2db 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -64,7 +64,8 @@ mysqld_SOURCES = sql_lex.cc sql_handler.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 protocol.cc lock.cc my_lock.c \
+ net_serv.cc protocol.cc sql_state.c \
+ lock.cc my_lock.c \
sql_string.cc sql_manager.cc sql_map.cc \
mysqld.cc password.c hash_filo.cc hostname.cc \
set_var.cc sql_parse.cc sql_yacc.yy \
diff --git a/sql/item.cc b/sql/item.cc
index 636cefb511b..bdf180b4828 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -117,7 +117,9 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
/*
- This function is only called when comparing items in the WHERE clause
+ This function is called when:
+ - Comparing items in the WHERE clause (when doing where optimization)
+ - When trying to find an ORDER BY/GROUP BY item in the SELECT part
*/
bool Item::eq(const Item *item, bool binary_cmp) const
@@ -243,6 +245,7 @@ void Item_field::set_field(Field *field_par)
decimals= field->decimals();
table_name=field_par->table_name;
field_name=field_par->field_name;
+ db_name=field_par->table->table_cache_key;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
set_charset(field_par->charset(), COER_IMPLICIT);
}
@@ -344,9 +347,34 @@ longlong Item_field::val_int_result()
return result_field->val_int();
}
+
bool Item_field::eq(const Item *item, bool binary_cmp) const
{
- return item->type() == FIELD_ITEM && ((Item_field*) item)->field == field;
+ if (item->type() != FIELD_ITEM)
+ return 0;
+
+ Item_field *item_field= (Item_field*) item;
+ if (item_field->field)
+ return item_field->field == field;
+ /*
+ We may come here when we are trying to find a function in a GROUP BY
+ clause from the select list.
+ In this case the '100 % correct' way to do this would be to first
+ run fix_fields() on the GROUP BY item and then retry this function, but
+ I think it's better to relax the checking a bit as we will in
+ most cases do the correct thing by just checking the field name.
+ (In cases where we would choose wrong we would have to generate a
+ ER_NON_UNIQ_ERROR).
+ */
+ return (!my_strcasecmp(system_charset_info, item_field->name,
+ field_name) &&
+ (!item_field->table_name ||
+ (!my_strcasecmp(table_alias_charset, item_field->table_name,
+ table_name) &&
+ (!item_field->db_name ||
+ (item_field->db_name && !my_strcasecmp(table_alias_charset,
+ item_field->db_name,
+ db_name))))));
}
table_map Item_field::used_tables() const
@@ -837,7 +865,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
}
}
- }
+ }
else if (!tmp)
return -1;
diff --git a/sql/item.h b/sql/item.h
index 470937f8ee7..934ea83d218 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -29,6 +29,8 @@ class Item {
void operator=(Item &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr,size_t size) {} /*lint -e715 */
enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index fa8bf7e6e0f..a57291702bc 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -217,11 +217,19 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
** reset and add of sum_func
***********************************************************************/
-void Item_sum_sum::reset()
+Item *Item_sum_sum::copy_or_same(THD* thd)
{
- null_value=1; sum=0.0; Item_sum_sum::add();
+ return new (&thd->mem_root) Item_sum_sum(thd, *this);
}
+
+bool Item_sum_sum::reset()
+{
+ null_value=1; sum=0.0;
+ return Item_sum_sum::add();
+}
+
+
bool Item_sum_sum::add()
{
sum+=args[0]->val();
@@ -230,17 +238,26 @@ bool Item_sum_sum::add()
return 0;
}
+
double Item_sum_sum::val()
{
return sum;
}
-void Item_sum_count::reset()
+Item *Item_sum_count::copy_or_same(THD* thd)
{
- count=0; add();
+ return new (&thd->mem_root) Item_sum_count(thd, *this);
}
+
+bool Item_sum_count::reset()
+{
+ count=0;
+ return add();
+}
+
+
bool Item_sum_count::add()
{
if (!args[0]->maybe_null)
@@ -260,14 +277,22 @@ longlong Item_sum_count::val_int()
}
/*
-** Avgerage
+ Avgerage
*/
-void Item_sum_avg::reset()
+Item *Item_sum_avg::copy_or_same(THD* thd)
{
- sum=0.0; count=0; Item_sum_avg::add();
+ return new (&thd->mem_root) Item_sum_avg(thd, *this);
}
+
+bool Item_sum_avg::reset()
+{
+ sum=0.0; count=0;
+ return Item_sum_avg::add();
+}
+
+
bool Item_sum_avg::add()
{
double nr=args[0]->val();
@@ -292,7 +317,7 @@ double Item_sum_avg::val()
/*
-** Standard deviation
+ Standard deviation
*/
double Item_sum_std::val()
@@ -301,15 +326,27 @@ double Item_sum_std::val()
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
+Item *Item_sum_std::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_std(thd, *this);
+}
+
+
/*
-** variance
+ Variance
*/
-void Item_sum_variance::reset()
+Item *Item_sum_variance::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_variance(thd, *this);
+}
+
+
+bool Item_sum_variance::reset()
{
sum=sum_sqr=0.0;
count=0;
- (void) Item_sum_variance::add();
+ return Item_sum_variance::add();
}
bool Item_sum_variance::add()
@@ -440,6 +477,13 @@ Item_sum_hybrid::val_str(String *str)
return str; // Keep compiler happy
}
+
+Item *Item_sum_min::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_min(thd, *this);
+}
+
+
bool Item_sum_min::add()
{
switch (hybrid_type) {
@@ -487,6 +531,12 @@ bool Item_sum_min::add()
}
+Item *Item_sum_max::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_max(thd, *this);
+}
+
+
bool Item_sum_max::add()
{
switch (hybrid_type) {
@@ -541,11 +591,19 @@ longlong Item_sum_bit::val_int()
return (longlong) bits;
}
-void Item_sum_bit::reset()
+
+bool Item_sum_bit::reset()
+{
+ bits=reset_bits;
+ return add();
+}
+
+Item *Item_sum_or::copy_or_same(THD* thd)
{
- bits=reset_bits; add();
+ return new (&thd->mem_root) Item_sum_or(thd, *this);
}
+
bool Item_sum_or::add()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -554,6 +612,12 @@ bool Item_sum_or::add()
return 0;
}
+Item *Item_sum_and::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_and(thd, *this);
+}
+
+
bool Item_sum_and::add()
{
ulonglong value= (ulonglong) args[0]->val_int();
@@ -1032,12 +1096,21 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
Item **ref)
{
- if (Item_sum_num::fix_fields(thd, tables, ref) ||
- !(tmp_table_param= new TMP_TABLE_PARAM))
+ if (Item_sum_num::fix_fields(thd, tables, ref))
return 1;
return 0;
}
+/* This is used by rollup to create a separate usable copy of the function */
+
+void Item_sum_count_distinct::make_unique()
+{
+ table=0;
+ original= 0;
+ tree= &tree_base;
+}
+
+
bool Item_sum_count_distinct::setup(THD *thd)
{
List<Item> list;
@@ -1045,6 +1118,9 @@ bool Item_sum_count_distinct::setup(THD *thd)
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
+ if (!(tmp_table_param= new TMP_TABLE_PARAM))
+ return 1;
+
/* Create a table with an unique key over all parameters */
for (uint i=0; i < arg_count ; i++)
{
@@ -1192,7 +1268,14 @@ int Item_sum_count_distinct::tree_to_myisam()
return 0;
}
-void Item_sum_count_distinct::reset()
+
+Item *Item_sum_count_distinct::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_count_distinct(thd, *this);
+}
+
+
+bool Item_sum_count_distinct::reset()
{
if (use_tree)
reset_tree(tree);
@@ -1202,7 +1285,7 @@ void Item_sum_count_distinct::reset()
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
}
- (void) add();
+ return add();
}
bool Item_sum_count_distinct::add()
@@ -1265,11 +1348,11 @@ longlong Item_sum_count_distinct::val_int()
#ifdef HAVE_DLOPEN
-void Item_udf_sum::reset()
+bool Item_udf_sum::reset()
{
DBUG_ENTER("Item_udf_sum::reset");
udf.reset(&null_value);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
}
bool Item_udf_sum::add()
@@ -1279,6 +1362,11 @@ bool Item_udf_sum::add()
DBUG_RETURN(0);
}
+Item *Item_sum_udf_float::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_float(thd, *this);
+}
+
double Item_sum_udf_float::val()
{
DBUG_ENTER("Item_sum_udf_float::val");
@@ -1298,6 +1386,12 @@ String *Item_sum_udf_float::val_str(String *str)
}
+Item *Item_sum_udf_int::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_int(thd, *this);
+}
+
+
longlong Item_sum_udf_int::val_int()
{
DBUG_ENTER("Item_sum_udf_int::val_int");
@@ -1306,6 +1400,7 @@ longlong Item_sum_udf_int::val_int()
DBUG_RETURN(udf.val_int(&null_value));
}
+
String *Item_sum_udf_int::val_str(String *str)
{
longlong nr=val_int();
@@ -1327,6 +1422,13 @@ void Item_sum_udf_str::fix_length_and_dec()
DBUG_VOID_RETURN;
}
+
+Item *Item_sum_udf_str::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_sum_udf_str(thd, *this);
+}
+
+
String *Item_sum_udf_str::val_str(String *str)
{
DBUG_ENTER("Item_sum_udf_str::str");
@@ -1568,7 +1670,13 @@ Item_func_group_concat::~Item_func_group_concat()
}
-void Item_func_group_concat::reset()
+Item *Item_func_group_concat::copy_or_same(THD* thd)
+{
+ return new (&thd->mem_root) Item_func_group_concat(thd, *this);
+}
+
+
+bool Item_func_group_concat::reset()
{
result.length(0);
result.copy();
@@ -1582,7 +1690,7 @@ void Item_func_group_concat::reset()
}
if (tree_mode)
reset_tree(tree);
- add();
+ return add();
}
@@ -1768,6 +1876,16 @@ bool Item_func_group_concat::setup(THD *thd)
return 0;
}
+/* This is used by rollup to create a separate usable copy of the function */
+
+void Item_func_group_concat::make_unique()
+{
+ table=0;
+ original= 0;
+ tree= &tree_base;
+}
+
+
String* Item_func_group_concat::val_str(String* str)
{
if (null_value)
diff --git a/sql/item_sum.h b/sql/item_sum.h
index f996f980fff..c8614dda679 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -26,9 +26,11 @@
class Item_sum :public Item_result_field
{
public:
- enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
- MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
- UDF_SUM_FUNC, GROUP_CONCAT_FUNC };
+ enum Sumfunctype
+ { COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_FUNC,
+ MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
+ UDF_SUM_FUNC, GROUP_CONCAT_FUNC
+ };
Item **args,*tmp_args[2];
uint arg_count;
@@ -60,7 +62,7 @@ public:
enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0;
- virtual void reset()=0;
+ virtual bool reset()=0;
virtual bool add()=0;
virtual void reset_field()=0;
virtual void update_field(int offset)=0;
@@ -78,6 +80,7 @@ public:
void fix_num_length_and_dec();
void no_rows_in_result() { reset(); }
virtual bool setup(THD *thd) {return 0;}
+ virtual void make_unique() {}
Item *get_tmp_table_item(THD *thd);
};
@@ -121,14 +124,14 @@ class Item_sum_sum :public Item_sum_num
Item_sum_sum(THD *thd, Item_sum_sum &item)
:Item_sum_num(thd, item), sum(item.sum) {}
enum Sumfunctype sum_func () const {return SUM_FUNC;}
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
void update_field(int offset);
void no_rows_in_result() {}
const char *func_name() const { return "sum"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_sum(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -148,7 +151,7 @@ class Item_sum_count :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
- void reset();
+ bool reset();
void no_rows_in_result() { count=0; }
bool add();
void make_const(longlong count_arg) { count=count_arg; used_table_cache=0; }
@@ -156,7 +159,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void update_field(int offset);
const char *func_name() const { return "count"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_count(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -222,17 +225,15 @@ class Item_sum_count_distinct :public Item_sum_int
table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
- void reset();
+ bool reset();
bool add();
longlong val_int();
void reset_field() { return ;} // Never called
void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd);
- Item *copy_or_same(THD* thd)
- {
- return new Item_sum_count_distinct(thd, *this);
- }
+ void make_unique();
+ Item *copy_or_same(THD* thd);
void no_rows_in_result() {}
};
@@ -268,7 +269,7 @@ class Item_sum_avg :public Item_sum_num
Item_sum_avg(THD *thd, Item_sum_avg &item)
:Item_sum_num(thd, item), sum(item.sum), count(item.count) {}
enum Sumfunctype sum_func () const {return AVG_FUNC;}
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
@@ -276,7 +277,7 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_avg_field(this); }
const char *func_name() const { return "avg"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_avg(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
class Item_sum_variance;
@@ -321,7 +322,7 @@ class Item_sum_variance : public Item_sum_num
Item_sum_num(thd, item), sum(item.sum), sum_sqr(item.sum_sqr),
count(item.count) {}
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
- void reset();
+ bool reset();
bool add();
double val();
void reset_field();
@@ -329,7 +330,7 @@ class Item_sum_variance : public Item_sum_num
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
const char *func_name() const { return "variance"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_variance(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
class Item_sum_std;
@@ -349,12 +350,16 @@ public:
class Item_sum_std :public Item_sum_variance
{
public:
- Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
+ Item_sum_std(Item *item_par) :Item_sum_variance(item_par) {}
+ Item_sum_std(THD *thd, Item_sum_std &item)
+ :Item_sum_variance(thd, item)
+ {}
enum Sumfunctype sum_func () const { return STD_FUNC; }
double val();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
+ Item *copy_or_same(THD* thd);
};
// This class is a string or number function depending on num_func
@@ -386,13 +391,13 @@ class Item_sum_hybrid :public Item_sum
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
- void reset()
+ bool reset()
{
sum=0.0;
sum_int=0;
value.length(0);
null_value=1;
- add();
+ return add();
}
double val();
longlong val_int();
@@ -418,7 +423,7 @@ public:
bool add();
const char *func_name() const { return "min"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_min(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -431,7 +436,7 @@ public:
bool add();
const char *func_name() const { return "max"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_max(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -446,7 +451,7 @@ class Item_sum_bit :public Item_sum_int
Item_sum_bit(THD *thd, Item_sum_bit &item):
Item_sum_int(thd, item), reset_bits(item.reset_bits), bits(item.bits) {}
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
- void reset();
+ bool reset();
longlong val_int();
void reset_field();
void fix_length_and_dec()
@@ -462,7 +467,7 @@ class Item_sum_or :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_or"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_or(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -474,7 +479,7 @@ class Item_sum_and :public Item_sum_bit
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_and"; }
- Item *copy_or_same(THD* thd) { return new Item_sum_and(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
/*
@@ -504,7 +509,7 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
virtual bool have_field_update(void) const { return 0; }
- void reset();
+ bool reset();
bool add();
void reset_field() {};
void update_field(int offset_arg) {};
@@ -524,7 +529,7 @@ class Item_sum_udf_float :public Item_udf_sum
double val();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -542,7 +547,7 @@ public:
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
@@ -571,7 +576,7 @@ public:
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@ -586,10 +591,9 @@ class Item_sum_udf_float :public Item_sum_num
~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_float(thd, *this); }
};
@@ -604,10 +608,9 @@ public:
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; }
double val() { return 0; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_int(thd, *this); }
};
@@ -625,10 +628,9 @@ public:
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec() { maybe_null=1; max_length=0; }
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- void reset() {}
+ bool reset() { return 0; }
bool add() { return 0; }
void update_field(int offset) {}
- Item *copy_or_same(THD* thd) { return new Item_sum_udf_str(thd, *this); }
};
#endif /* HAVE_DLOPEN */
@@ -676,7 +678,7 @@ class Item_func_group_concat : public Item_sum
warning(item.warning),
warning_available(item.warning_available),
separator(item.separator),
- tree(item.tree),
+ tree(item.tree),
table(item.table),
expr(item.expr),
order(item.order),
@@ -700,11 +702,12 @@ class Item_func_group_concat : public Item_sum
enum Type type() const { return SUM_FUNC_ITEM; }
void fix_length_and_dec() { max_length=group_concat_max_len; }
virtual Item_result result_type () const { return STRING_RESULT; }
- void reset();
+ bool reset();
bool add();
void reset_field();
bool fix_fields(THD *, TABLE_LIST *, Item **);
bool setup(THD *thd);
+ void make_unique();
virtual void update_field(int offset) {};
double val()
{
@@ -717,5 +720,5 @@ class Item_func_group_concat : public Item_sum
return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
}
String* val_str(String* str);
- Item *copy_or_same(THD* thd) { return new Item_func_group_concat(thd, *this); }
+ Item *copy_or_same(THD* thd);
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 5ffd10be7a5..f2c64c4bde9 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -41,7 +41,7 @@ public:
:Item_sum_num(thd, item) {}
double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
- void reset() {}
+ bool reset() { return 0;}
bool add() { return 0; }
void reset_field() {}
void update_field(int offset) {}
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 712c8853a20..97158191111 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -66,9 +66,8 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#endif
#endif
-extern CHARSET_INFO *system_charset_info;
-extern CHARSET_INFO *files_charset_info;
-extern CHARSET_INFO *national_charset_info;
+extern CHARSET_INFO *system_charset_info, *files_charset_info ;
+extern CHARSET_INFO *national_charset_info, *table_alias_charset;
/***************************************************************************
Configuration parameters
@@ -208,7 +207,7 @@ extern CHARSET_INFO *national_charset_info;
#define MODE_PIPES_AS_CONCAT 2
#define MODE_ANSI_QUOTES 4
#define MODE_IGNORE_SPACE 8
-#define MODE_SERIALIZABLE 16
+#define MODE_NOT_USED 16
#define MODE_ONLY_FULL_GROUP_BY 32
#define MODE_NO_UNSIGNED_SUBTRACTION 64
#define MODE_POSTGRESQL 128
@@ -221,6 +220,7 @@ extern CHARSET_INFO *national_charset_info;
#define MODE_NO_FIELD_OPTIONS 16384
#define MODE_MYSQL323 32768
#define MODE_MYSQL40 65536
+#define MODE_ANSI (MODE_MYSQL40*2)
#define RAID_BLOCK_SIZE 1024
@@ -723,7 +723,7 @@ extern ulong ha_read_rnd_count, ha_read_rnd_next_count;
extern ulong ha_commit_count, ha_rollback_count,table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong max_insert_delayed_threads, max_user_connections;
-extern ulong long_query_count, what_to_log,flush_time,opt_sql_mode;
+extern ulong long_query_count, what_to_log,flush_time;
extern ulong query_buff_size, thread_stack,thread_stack_min;
extern ulong binlog_cache_size, max_binlog_cache_size, open_files_limit;
extern ulong max_binlog_size, rpl_recovery_rank, thread_cache_size;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 86ec00e1e92..019a3388341 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -208,9 +208,9 @@ const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
const char *sql_mode_names[] =
{
"REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
- "SERIALIZE", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
+ "?", "ONLY_FULL_GROUP_BY", "NO_UNSIGNED_SUBTRACTION",
"POSTGRESQL", "ORACLE", "MSSQL", "DB2", "SAPDB", "NO_KEY_OPTIONS",
- "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40",
+ "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
NullS
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
@@ -324,6 +324,9 @@ MY_TMPDIR mysql_tmpdir_list;
DATE_FORMAT dayord;
MY_BITMAP temp_pool;
+CHARSET_INFO *system_charset_info, *files_charset_info ;
+CHARSET_INFO *national_charset_info, *table_alias_charset;
+
SHOW_COMP_OPTION have_berkeley_db, have_innodb, have_isam;
SHOW_COMP_OPTION have_raid, have_openssl, have_symlink, have_query_cache;
SHOW_COMP_OPTION have_crypt, have_compress;
@@ -2281,9 +2284,7 @@ static void handle_connections_methods()
#endif /* __NT__ */
if (have_tcpip && !opt_disable_networking)
{
-#ifdef __NT__
handler_count++;
-#endif
if (pthread_create(&hThread,&connection_attrib,
handle_connections_sockets, 0))
{
@@ -2294,9 +2295,7 @@ static void handle_connections_methods()
#ifdef HAVE_SMEM
if (opt_enable_shared_memory)
{
-#ifdef __NT__
handler_count++;
-#endif
if (pthread_create(&hThread,&connection_attrib,
handle_connections_shared_memory, 0))
{
@@ -2311,6 +2310,16 @@ static void handle_connections_methods()
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
}
+
+void decrement_handler_count()
+{
+ pthread_mutex_lock(&LOCK_thread_count);
+ handler_count--;
+ pthread_mutex_unlock(&LOCK_thread_count);
+ pthread_cond_signal(&COND_handler_count);
+}
+#else
+#define decrement_handler_count()
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
@@ -2428,7 +2437,7 @@ The server will not act as a slave.");
#endif
/* init_slave() must be called after the thread keys are created */
init_slave();
-
+
if (opt_bootstrap)
{
int error=bootstrap(stdin);
@@ -3019,13 +3028,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets,
// kill server must be invoked from thread 1!
kill_server(MYSQL_KILL_SIGNAL);
#endif
-
-#ifdef __NT__
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
-#endif
+ decrement_handler_count();
DBUG_RETURN(0);
}
@@ -3105,10 +3108,7 @@ extern "C" pthread_handler_decl(handle_connections_namedpipes,arg)
create_new_thread(thd);
}
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
+ decrement_handler_count();
DBUG_RETURN(0);
}
#endif /* __NT__ */
@@ -3322,12 +3322,8 @@ error:
if (!handle_connect_file_map) CloseHandle(handle_connect_file_map);
if (!event_connect_answer) CloseHandle(event_connect_answer);
if (!event_connect_request) CloseHandle(event_connect_request);
-#ifdef __NT__
- pthread_mutex_lock(&LOCK_thread_count);
- handler_count--;
- pthread_mutex_unlock(&LOCK_thread_count);
- pthread_cond_signal(&COND_handler_count);
-#endif
+
+ decrement_handler_count();
DBUG_RETURN(0);
}
#endif /* HAVE_SMEM */
@@ -3921,7 +3917,7 @@ replicating a LOAD DATA INFILE command",
(gptr*) &opt_sql_bin_update, (gptr*) &opt_sql_bin_update, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"sql-mode", OPT_SQL_MODE,
- "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
+ "Syntax: sql-mode=option[,option[,option...]] where option can be one of: REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES, IGNORE_SPACE, ONLY_FULL_GROUP_BY, NO_UNSIGNED_SUBTRACTION.",
(gptr*) &sql_mode_str, (gptr*) &sql_mode_str, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
#ifdef HAVE_OPENSSL
@@ -4634,6 +4630,12 @@ static void mysql_init_variables(void)
bzero((gptr) &mysql_tmpdir_list, sizeof(mysql_tmpdir_list));
bzero((gptr) &com_stat, sizeof(com_stat));
+ /* Character sets */
+ system_charset_info= &my_charset_utf8_general_ci;
+ files_charset_info= &my_charset_utf8_general_ci;
+ national_charset_info= &my_charset_utf8_general_ci;
+ table_alias_charset= &my_charset_bin;
+
/* Things with default values that are not zero */
delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
opt_specialflag= SPECIAL_ENGLISH;
@@ -4684,6 +4686,7 @@ static void mysql_init_variables(void)
sys_charset.value= (char*) MYSQL_CHARSET;
sys_charset_system.value= (char*) system_charset_info->csname;
+
/* Set default values for some option variables */
global_system_variables.character_set_results= NULL;
global_system_variables.character_set_client= default_charset_info;
@@ -4789,10 +4792,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_endinfo=1; /* unireg: memory allocation */
break;
case 'a':
- global_system_variables.sql_mode=
- (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
- MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE |
- MODE_ONLY_FULL_GROUP_BY);
+ global_system_variables.sql_mode= fix_sql_mode(MODE_ANSI);
global_system_variables.tx_isolation= ISO_SERIALIZABLE;
break;
case 'b':
@@ -5270,11 +5270,8 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
fprintf(stderr, "Unknown option to sql-mode: %s\n", argument);
exit(1);
}
- global_system_variables.tx_isolation=
- ((global_system_variables.sql_mode & MODE_SERIALIZABLE) ?
- ISO_SERIALIZABLE :
- ISO_REPEATABLE_READ);
- break;
+ global_system_variables.sql_mode= fix_sql_mode(global_system_variables.
+ sql_mode);
}
case OPT_MASTER_PASSWORD:
master_password=argument;
@@ -5332,6 +5329,9 @@ static void get_options(int argc,char **argv)
/* Set global variables based on startup options */
myisam_block_size=(uint) 1 << my_bit_log2(opt_myisam_block_size);
+ table_alias_charset= (lower_case_table_names ?
+ files_charset_info :
+ &my_charset_bin);
}
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index 8271d971782..621fa5f6334 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -15,6 +15,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
+ This file is the net layer API for the MySQL client/server protocol,
+ which is a tightly coupled, proprietary protocol owned by MySQL AB.
+ Any re-implementations of this protocol must also be under GPL
+ unless one has got an license from MySQL AB stating otherwise.
+*/
+
+/*
Write and read of logical packets to/from socket
Writes are cached into net_buffer_length big packets.
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 848321c1576..dc61046aa20 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -102,7 +102,8 @@ void send_error(THD *thd, uint sql_errno, const char *err)
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
/* The first # is to make the protocol backward compatible */
- strmov(buff+2, "#000000");
+ buff[2]= '#';
+ strmov(buff+3, mysql_errno_to_sqlstate(sql_errno));
pos= buff + 2 + SQLSTATE_LENGTH +1;
}
length= (uint) (strmake(pos, err, MYSQL_ERRMSG_SIZE-1) - buff);
@@ -222,8 +223,8 @@ net_printf(THD *thd, uint errcode, ...)
int2store(pos, errcode);
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
- /* The first # is to make the protocol backward compatible */
- memcpy(pos+2, "#000000", SQLSTATE_LENGTH +1);
+ pos[2]= '#'; /* To make the protocol backward compatible */
+ memcpy(pos+3, mysql_errno_to_sqlstate(errcode), SQLSTATE_LENGTH);
}
}
VOID(net_real_write(net,(char*) net->buff,length+head_length+1+offset));
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 3145504951d..42ea92825d1 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -89,6 +89,7 @@ static void fix_query_cache_min_res_unit(THD *thd, enum_var_type type);
static void fix_key_buffer_size(THD *thd, enum_var_type type);
static void fix_myisam_max_extra_sort_file_size(THD *thd, enum_var_type type);
static void fix_myisam_max_sort_file_size(THD *thd, enum_var_type type);
+void fix_sql_mode_var(THD *thd, enum_var_type type);
static byte *get_error_count(THD *thd);
static byte *get_warning_count(THD *thd);
@@ -1164,40 +1165,6 @@ byte *sys_var_thd_enum::value_ptr(THD *thd, enum_var_type type)
}
-byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
-{
- ulong val;
- char buff[256];
- String tmp(buff, sizeof(buff), &my_charset_latin1);
- my_bool found= 0;
-
- tmp.length(0);
- val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
- thd->variables.*offset);
- for (uint i= 0; val; val>>= 1, i++)
- {
- if (val & 1)
- {
- tmp.append(enum_names->type_names[i]);
- tmp.append(',');
- }
- }
- if (tmp.length())
- tmp.length(tmp.length() - 1);
- return (byte*) thd->strmake(tmp.ptr(), tmp.length());
-}
-
-
-void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
-{
- if (type == OPT_GLOBAL)
- global_system_variables.*offset= 0;
- else
- thd->variables.*offset= global_system_variables.*offset;
-}
-
-
-
bool sys_var_thd_bit::update(THD *thd, set_var *var)
{
int res= (*update_func)(thd, var);
@@ -1803,7 +1770,105 @@ int set_var_password::update(THD *thd)
1 : 0);
}
+/****************************************************************************
+ Functions to handle sql_mode
+****************************************************************************/
+byte *sys_var_thd_sql_mode::value_ptr(THD *thd, enum_var_type type)
+{
+ ulong val;
+ char buff[256];
+ String tmp(buff, sizeof(buff), &my_charset_latin1);
+ my_bool found= 0;
+
+ tmp.length(0);
+ val= ((type == OPT_GLOBAL) ? global_system_variables.*offset :
+ thd->variables.*offset);
+ for (uint i= 0; val; val>>= 1, i++)
+ {
+ if (val & 1)
+ {
+ tmp.append(enum_names->type_names[i]);
+ tmp.append(',');
+ }
+ }
+ if (tmp.length())
+ tmp.length(tmp.length() - 1);
+ return (byte*) thd->strmake(tmp.ptr(), tmp.length());
+}
+
+
+void sys_var_thd_sql_mode::set_default(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.*offset= 0;
+ else
+ thd->variables.*offset= global_system_variables.*offset;
+}
+
+void fix_sql_mode_var(THD *thd, enum_var_type type)
+{
+ if (type == OPT_GLOBAL)
+ global_system_variables.sql_mode=
+ fix_sql_mode(global_system_variables.sql_mode);
+ else
+ thd->variables.sql_mode= fix_sql_mode(thd->variables.sql_mode);
+}
+
+/* Map database specific bits to function bits */
+
+ulong fix_sql_mode(ulong sql_mode)
+{
+ /*
+ Note that we dont set
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | MODE_NO_FIELD_OPTIONS
+ to allow one to get full use of MySQL in this mode.
+ */
+
+ if (sql_mode & MODE_ANSI)
+ sql_mode|= (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE | MODE_ONLY_FULL_GROUP_BY);
+ if (sql_mode & MODE_ORACLE)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MSSQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MSSQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_POSTGRESQL)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_DB2)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_DB2)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_SAPDB)
+ sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES |
+ MODE_IGNORE_SPACE |
+ MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
+ MODE_NO_FIELD_OPTIONS);
+ if (sql_mode & MODE_MYSQL40)
+ sql_mode|= MODE_NO_FIELD_OPTIONS;
+ if (sql_mode & MODE_MYSQL323)
+ sql_mode|= MODE_NO_FIELD_OPTIONS;
+ return sql_mode;
+}
diff --git a/sql/set_var.h b/sql/set_var.h
index f501426e553..8646668a236 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -309,11 +309,14 @@ public:
};
+extern void fix_sql_mode_var(THD *thd, enum_var_type type);
+
class sys_var_thd_sql_mode :public sys_var_thd_enum
{
public:
sys_var_thd_sql_mode(const char *name_arg, ulong SV::*offset_arg)
- :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib)
+ :sys_var_thd_enum(name_arg, offset_arg, &sql_mode_typelib,
+ fix_sql_mode_var)
{}
bool check(THD *thd, set_var *var)
{
@@ -605,6 +608,7 @@ void set_var_free();
sys_var *find_sys_var(const char *str, uint length=0);
int sql_set_variables(THD *thd, List<set_var_base> *var_list);
void fix_delay_key_write(THD *thd, enum_var_type type);
+ulong fix_sql_mode(ulong sql_mode);
extern sys_var_str sys_charset;
extern sys_var_str sys_charset_system;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index eeaf560693e..0741dd1e32f 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -544,7 +544,8 @@ TABLE_LIST * find_table_in_list(TABLE_LIST *table,
{
for (; table; table= table->next)
if ((!db_name || !strcmp(table->db, db_name)) &&
- (!table_name || !strcmp(table->alias, table_name)))
+ (!table_name || !my_strcasecmp(table_alias_charset,
+ table->alias, table_name)))
break;
return table;
}
@@ -1739,7 +1740,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
bool found_table=0;
for (; tables ; tables=tables->next)
{
- if (!strcmp(tables->alias,table_name) &&
+ if (!my_strcasecmp(table_alias_charset, tables->alias, table_name) &&
(!db || !tables->db || !tables->db[0] || !strcmp(db,tables->db)))
{
found_table=1;
@@ -1868,20 +1869,22 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
{
List_iterator<Item> li(items);
Item **found=0,*item;
+ const char *db_name=0;
const char *field_name=0;
const char *table_name=0;
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)
{
field_name= ((Item_ident*) find)->field_name;
table_name= ((Item_ident*) find)->table_name;
+ db_name= ((Item_ident*) find)->db_name;
}
for (uint i= 0; (item=li++); i++)
{
if (field_name && item->type() == Item::FIELD_ITEM)
{
- if (!my_strcasecmp(system_charset_info,
- ((Item_field*) item)->name,field_name))
+ Item_field *item_field= (Item_field*) item;
+ if (!my_strcasecmp(system_charset_info, item_field->name, field_name))
{
if (!table_name)
{
@@ -1897,11 +1900,16 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
found= li.ref();
*counter= i;
}
- else if (!strcmp(((Item_field*) item)->table_name,table_name))
+ else
{
- found= li.ref();
- *counter= i;
- break;
+ if (!strcmp(item_field->table_name,table_name) &&
+ (!db_name || (db_name && item_field->db_name &&
+ !strcmp(item_field->table_name,table_name))))
+ {
+ found= li.ref();
+ *counter= i;
+ break;
+ }
}
}
}
@@ -2094,7 +2102,8 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
for (; tables ; tables=tables->next)
{
TABLE *table=tables->table;
- if (!table_name || (!strcmp(table_name,tables->alias) &&
+ if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
+ tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
{
/* Ensure that we have access right to all columns */
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index adc3d177fdf..7a154d206ef 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1432,7 +1432,8 @@ ulong Query_cache::init_cache()
#else
// windows, OS/2 or other case insensitive file names work around
VOID(hash_init(&tables,
- lower_case_table_names ? &my_charset_bin : system_charset_info,
+ lower_case_table_names ? &my_charset_bin :
+ system_charset_info,
def_table_hash_size, 0, 0,query_cache_table_get_key, 0, 0));
#endif
diff --git a/sql/sql_list.h b/sql/sql_list.h
index ff21663576a..2450b2051f2 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -33,6 +33,8 @@ public:
{
return (void*) sql_alloc((uint) size);
}
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr, size_t size) {} /*lint -e715 */
static void operator delete[](void *ptr, size_t size) {}
#ifdef HAVE_purify
@@ -190,6 +192,7 @@ public:
inline void *replace(void *element)
{ // Return old element
void *tmp=current->info;
+ DBUG_ASSERT(current->info != 0);
current->info=element;
return tmp;
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 95ac57013da..fcddc2d2252 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -663,7 +663,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
thd->protocol_simple.send_fields(&fields, 0) ||
send_item_params(stmt))
DBUG_RETURN(1);
- join->cleanup(thd);
+ join->cleanup();
}
DBUG_RETURN(0);
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4167da5802a..61a64573eaa 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -138,7 +138,6 @@ static bool test_if_subpart(ORDER *a,ORDER *b);
static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
static bool alloc_group_fields(JOIN *join,ORDER *group);
-static bool make_sum_func_list(JOIN *join,List<Item> &fields);
// Create list for using with tempory table
static bool change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
List<Item> &new_list1,
@@ -153,7 +152,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
-static void init_sum_functions(Item_sum **func);
+static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
bool distinct, const char *message=NullS);
@@ -313,9 +312,11 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having->with_sum_func)
having->split_sum_func(ref_pointer_array, all_fields);
}
-
+
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);
+
+
/*
Check if one one uses a not constant column with group functions
and no GROUP BY.
@@ -345,45 +346,47 @@ JOIN::prepare(Item ***rref_pointer_array,
for (table=tables_list ; table ; table=table->next)
tables++;
}
+ {
+ /* Caclulate the number of groups */
+ send_group_parts= 0;
+ for (ORDER *group= group_list ; group ; group= group->next)
+ send_group_parts++;
+ }
+
procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
if (error)
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
if (procedure)
{
if (setup_new_fields(thd, tables_list, fields_list, all_fields,
procedure->param_fields))
- { /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
if (procedure->group)
{
if (!test_if_subpart(procedure->group,group_list))
{ /* purecov: inspected */
my_message(0,"Can't handle procedures with differents groups yet",
MYF(0)); /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
#ifdef NOT_NEEDED
else if (!group_list && procedure->flags & PROC_GROUP)
{
my_message(0,"Select must have a group with this procedure",MYF(0));
- delete procedure;
- DBUG_RETURN(-1);
+ goto err;
}
#endif
if (order && (procedure->flags & PROC_NO_SORT))
- { /* purecov: inspected */
+ { /* purecov: inspected */
my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
- delete procedure; /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ goto err; /* purecov: inspected */
}
}
/* Init join struct */
count_field_types(&tmp_table_param, all_fields, 0);
+ ref_pointer_array_size= all_fields.elements*sizeof(Item*);
this->group= group_list != 0;
row_limit= ((select_distinct || order || group_list) ? HA_POS_ERROR :
unit->select_limit_cnt);
@@ -398,15 +401,23 @@ JOIN::prepare(Item ***rref_pointer_array,
if (sum_func_count && !group_list && (func_count || field_count))
{
my_message(ER_WRONG_SUM_SELECT,ER(ER_WRONG_SUM_SELECT),MYF(0));
- delete procedure;
- DBUG_RETURN(-1);
+ goto err;
}
#endif
if (!procedure && result->prepare(fields_list, unit))
- { /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
- }
+ goto err; /* purecov: inspected */
+
+ if (select_lex->olap == ROLLUP_TYPE && rollup_init())
+ goto err;
+ if (alloc_func_list())
+ goto err;
+
DBUG_RETURN(0); // All OK
+
+err:
+ delete procedure; /* purecov: inspected */
+ procedure= 0;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
/*
@@ -638,7 +649,9 @@ JOIN::optimize()
else if (thd->is_fatal_error) // End of memory
DBUG_RETURN(1);
}
- group_list= remove_const(this, group_list, conds, &simple_group);
+ simple_group= 0;
+ if (rollup.state == ROLLUP::STATE_NONE)
+ group_list= remove_const(this, group_list, conds, &simple_group);
if (!group_list && group)
{
order=0; // The output has only one row
@@ -788,14 +801,14 @@ JOIN::optimize()
thd->proc_info="Sorting for group";
if (create_sort_index(thd, &join_tab[const_tables], group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
- make_sum_func_list(this, all_fields) ||
- alloc_group_fields(this, group_list))
+ alloc_group_fields(this, group_list) ||
+ make_sum_func_list(all_fields, fields_list, 1))
DBUG_RETURN(1);
group_list=0;
}
else
{
- if (make_sum_func_list(this, all_fields))
+ if (make_sum_func_list(all_fields, fields_list, 0))
DBUG_RETURN(1);
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
@@ -862,7 +875,7 @@ int
JOIN::reinit()
{
DBUG_ENTER("JOIN::reinit");
- //TODO move to unit reinit
+ /* TODO move to unit reinit */
unit->offset_limit_cnt =select_lex->offset_limit;
unit->select_limit_cnt =select_lex->select_limit+select_lex->offset_limit;
if (unit->select_limit_cnt < select_lex->select_limit)
@@ -873,7 +886,7 @@ JOIN::reinit()
if (setup_tables(tables_list))
DBUG_RETURN(1);
- // Reset of sum functions
+ /* Reset of sum functions */
first_record= 0;
if (sum_funcs)
{
@@ -897,7 +910,7 @@ JOIN::reinit()
filesort_free_buffers(exec_tmp_table2);
}
if (items0)
- memcpy(ref_pointer_array, items0, ref_pointer_array_size);
+ set_items_ref_array(items0);
if (tmp_join)
restore_tmp();
@@ -977,9 +990,6 @@ JOIN::exec()
DBUG_VOID_RETURN;
}
- /* Perform FULLTEXT search before all regular searches */
- //init_ftfuncs(thd, select_lex, test(order));
-
JOIN *curr_join= this;
List<Item> *curr_all_fields= &all_fields;
List<Item> *curr_fields_list= &fields_list;
@@ -1030,7 +1040,7 @@ JOIN::exec()
}
curr_all_fields= &tmp_all_fields1;
curr_fields_list= &tmp_fields_list1;
- memcpy(ref_pointer_array, items1, ref_pointer_array_size);
+ set_items_ref_array(items1);
if (sort_and_group || curr_tmp_table->group)
{
@@ -1079,7 +1089,8 @@ JOIN::exec()
if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
calc_group_buffer(curr_join, group_list);
- count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1,
+ count_field_types(&curr_join->tmp_table_param,
+ curr_join->tmp_all_fields1,
curr_join->select_distinct && !curr_join->group_list);
curr_join->tmp_table_param.hidden_field_count=
(curr_join->tmp_all_fields1.elements-
@@ -1117,7 +1128,8 @@ JOIN::exec()
thd->proc_info="Copying to group table";
tmp_error= -1;
- if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
+ 1) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0)))
{
@@ -1141,7 +1153,7 @@ JOIN::exec()
}
curr_fields_list= &curr_join->tmp_fields_list2;
curr_all_fields= &curr_join->tmp_all_fields2;
- memcpy(ref_pointer_array, items2, ref_pointer_array_size);
+ set_items_ref_array(items2);
curr_join->tmp_table_param.field_count+=
curr_join->tmp_table_param.sum_func_count;
curr_join->tmp_table_param.sum_func_count= 0;
@@ -1169,9 +1181,7 @@ JOIN::exec()
}
if (procedure)
- {
count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
- }
if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
@@ -1201,10 +1211,10 @@ JOIN::exec()
}
curr_fields_list= &tmp_fields_list3;
curr_all_fields= &tmp_all_fields3;
- memcpy(ref_pointer_array, items3, ref_pointer_array_size);
+ set_items_ref_array(items3);
- if (make_sum_func_list(curr_join, *curr_all_fields) ||
- thd->is_fatal_error)
+ if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
+ 1) || thd->is_fatal_error)
DBUG_VOID_RETURN;
}
if (curr_join->group_list || curr_join->order)
@@ -1291,7 +1301,7 @@ JOIN::exec()
*/
int
-JOIN::cleanup(THD *thd)
+JOIN::cleanup()
{
DBUG_ENTER("JOIN::cleanup");
select_lex->join= 0;
@@ -1312,7 +1322,7 @@ JOIN::cleanup(THD *thd)
}
}
tmp_join->tmp_join= 0;
- DBUG_RETURN(tmp_join->cleanup(thd));
+ DBUG_RETURN(tmp_join->cleanup());
}
lock=0; // It's faster to unlock later
@@ -1396,7 +1406,7 @@ err:
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
thd->proc_info="end";
- err= join->cleanup(thd);
+ err= join->cleanup();
if (thd->net.report_error)
err= -1;
delete join;
@@ -2916,7 +2926,6 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tmp_table_param.func_count=0;
join->tmp_table_param.copy_field=join->tmp_table_param.copy_field_end=0;
join->first_record=join->sort_and_group=0;
- join->sum_funcs=0;
join->send_records=(ha_rows) 0;
join->group=0;
join->row_limit=join->unit->select_limit_cnt;
@@ -5715,8 +5724,12 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
- else if (join->do_send_rows)
- error=join->procedure->send_row(*join->fields) ? 1 : 0;
+ else
+ {
+ if (join->do_send_rows)
+ error=join->procedure->send_row(*join->fields) ? 1 : 0;
+ join->send_records++;
+ }
if (end_of_records && join->procedure->end_of_records())
error= 1; // Fatal error
}
@@ -5730,17 +5743,23 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
}
if (join->having && join->having->val_int() == 0)
error= -1; // Didn't satisfy having
- else if (join->do_send_rows)
- error=join->result->send_data(*join->fields) ? 1 : 0;
+ else
+ {
+ if (join->do_send_rows)
+ error=join->result->send_data(*join->fields) ? 1 : 0;
+ join->send_records++;
+ }
+ if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
+ {
+ if (join->rollup_send_data((uint) (idx+1)))
+ error= 1;
+ }
}
if (error > 0)
DBUG_RETURN(-1); /* purecov: inspected */
if (end_of_records)
- {
- join->send_records++;
DBUG_RETURN(0);
- }
- if (!error && ++join->send_records >= join->unit->select_limit_cnt &&
+ if (join->send_records >= join->unit->select_limit_cnt &&
join->do_send_rows)
{
if (!(join->select_options & OPTION_FOUND_ROWS))
@@ -5760,7 +5779,8 @@ end_send_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
if (idx < (int) join->send_group_parts)
{
copy_fields(&join->tmp_table_param);
- init_sum_functions(join->sum_funcs);
+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
+ DBUG_RETURN(-1);
if (join->procedure)
join->procedure->add();
DBUG_RETURN(0);
@@ -6016,7 +6036,8 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
copy_fields(&join->tmp_table_param);
copy_funcs(join->tmp_table_param.items_to_copy);
- init_sum_functions(join->sum_funcs);
+ if (init_sum_functions(join->sum_funcs, join->sum_funcs_end[idx+1]))
+ DBUG_RETURN(-1);
if (join->procedure)
join->procedure->add();
DBUG_RETURN(0);
@@ -7674,7 +7695,10 @@ err2:
/*
- Copy fields and null values between two tables
+ Make a copy of all simple SELECT'ed items
+
+ This is done at the start of a new group so that we can retrieve
+ these later when the group changes.
*/
void
@@ -7694,33 +7718,76 @@ copy_fields(TMP_TABLE_PARAM *param)
}
-/*****************************************************************************
- Make an array of pointer to sum_functions to speed up sum_func calculation
-*****************************************************************************/
+/*
+ Make an array of pointers to sum_functions to speed up sum_func calculation
-static bool
-make_sum_func_list(JOIN *join,List<Item> &fields)
+ SYNOPSIS
+ alloc_func_list()
+
+ RETURN
+ 0 ok
+ 1 Error
+*/
+
+bool JOIN::alloc_func_list()
{
+ uint func_count, group_parts;
+ DBUG_ENTER("alloc_func_list");
+
+ func_count= tmp_table_param.sum_func_count;
+ /*
+ If we are using rollup, we need a copy of the summary functions for
+ each level
+ */
+ if (rollup.state != ROLLUP::STATE_NONE)
+ func_count*= (send_group_parts+1);
+
+ group_parts= send_group_parts;
+ /*
+ If distinct, reserve memory for possible
+ disctinct->group_by optimization
+ */
+ if (select_distinct)
+ group_parts+= fields_list.elements;
+
+ /* This must use calloc() as rollup_make_fields depends on this */
+ sum_funcs= (Item_sum**) thd->calloc(sizeof(Item_sum**) * (func_count+1) +
+ sizeof(Item_sum***) * (group_parts+1));
+ sum_funcs_end= (Item_sum***) (sum_funcs+func_count+1);
+ DBUG_RETURN(sum_funcs == 0);
+}
+
+
+bool JOIN::make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
+ bool before_group_by)
+{
+ List_iterator_fast<Item> it(all_fields);
+ Item_sum **func;
+ Item *item;
DBUG_ENTER("make_sum_func_list");
- Item_sum **func =
- (Item_sum**) sql_alloc(sizeof(Item_sum*)*
- (join->tmp_table_param.sum_func_count+1));
- if (!func)
- DBUG_RETURN(TRUE);
- List_iterator<Item> it(fields);
- join->sum_funcs=func;
- Item *field;
- while ((field=it++))
+ func= sum_funcs;
+ while ((item=it++))
{
- if (field->type() == Item::SUM_FUNC_ITEM && !field->const_item())
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
{
- *func++=(Item_sum*) field;
+ *func++= (Item_sum*) item;
/* let COUNT(DISTINCT) create the temporary table */
- if (((Item_sum*) field)->setup(join->thd))
+ if (((Item_sum*) item)->setup(thd))
DBUG_RETURN(TRUE);
}
}
+ if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
+ {
+ rollup.state= ROLLUP::STATE_READY;
+ if (rollup_make_fields(all_fields, send_fields, &func))
+ DBUG_RETURN(TRUE); // Should never happen
+ }
+ else if (rollup.state == ROLLUP::STATE_NONE)
+ {
+ for (uint i=0 ; i <= send_group_parts ;i++)
+ sum_funcs_end[i]= func;
+ }
*func=0; // End marker
DBUG_RETURN(FALSE);
}
@@ -7816,8 +7883,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
all_fields - all fields list
RETURN
- 0 - ok
- !=0 - error
+ 0 ok
+ 1 error
*/
static bool
@@ -7886,12 +7953,21 @@ copy_sum_funcs(Item_sum **func_ptr)
}
-static void
-init_sum_functions(Item_sum **func_ptr)
+static bool
+init_sum_functions(Item_sum **func_ptr, Item_sum **end_ptr)
{
- Item_sum *func;
- for (; (func= (Item_sum*) *func_ptr) ; func_ptr++)
- func->reset();
+ for (; func_ptr != end_ptr ;func_ptr++)
+ {
+ if ((*func_ptr)->reset())
+ return 1;
+ }
+ /* If rollup, calculate the upper sum levels */
+ for ( ; *func_ptr ; func_ptr++)
+ {
+ if ((*func_ptr)->add())
+ return 1;
+ }
+ return 0;
}
@@ -7916,10 +7992,10 @@ copy_funcs(Item **func_ptr)
}
-/*****************************************************************************
+/*
Create a condition for a const reference and add this to the
currenct select for the table
-*****************************************************************************/
+*/
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
{
@@ -7935,7 +8011,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
for (uint i=0 ; i < join_tab->ref.key_parts ; i++)
{
- Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].fieldnr-1];
+ Field *field=table->field[table->key_info[join_tab->ref.key].key_part[i].
+ fieldnr-1];
Item *value=join_tab->ref.items[i];
cond->add(new Item_func_equal(new Item_field(field),value));
}
@@ -7958,7 +8035,241 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
DBUG_RETURN(error ? TRUE : FALSE);
}
+
+/*
+ Free joins of subselect of this select.
+
+ free_underlaid_joins()
+ thd - THD pointer
+ select - pointer to st_select_lex which subselects joins we will free
+*/
+
+void free_underlaid_joins(THD *thd, SELECT_LEX *select)
+{
+ for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ unit->cleanup();
+}
+
+/****************************************************************************
+ ROLLUP handling
+****************************************************************************/
+
+/* Allocate memory needed for other rollup functions */
+
+bool JOIN::rollup_init()
+{
+ uint i,j;
+ ORDER *group;
+ Item **ref_array;
+
+ tmp_table_param.quick_group= 0; // Can't create groups in tmp table
+ rollup.state= ROLLUP::STATE_INITED;
+
+ /*
+ Create pointers to the different sum function groups
+ These are updated by rollup_make_fields()
+ */
+ tmp_table_param.group_parts= send_group_parts;
+
+ if (!(rollup.fields= (List<Item>*) thd->alloc((sizeof(Item*) +
+ sizeof(List<Item>) +
+ ref_pointer_array_size)
+ * send_group_parts)))
+ return 1;
+ rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
+ ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
+ rollup.item_null= new (&thd->mem_root) Item_null();
+
+ /*
+ Prepare space for field list for the different levels
+ These will be filled up in rollup_make_fields()
+ */
+ for (i= 0 ; i < send_group_parts ; i++)
+ {
+ List<Item> *fields= &rollup.fields[i];
+ fields->empty();
+ rollup.ref_pointer_arrays[i]= ref_array;
+ ref_array+= all_fields.elements;
+ for (j=0 ; j < fields_list.elements ; j++)
+ fields->push_back(rollup.item_null);
+ }
+ return 0;
+}
+
+
+/*
+ Fill up rollup structures with pointers to fields to use
+
+ SYNOPSIS
+ rollup_make_fields()
+ all_fields List of all fields (hidden and real ones)
+ fields Pointer to selected fields
+ func Store here a pointer to all fields
+
+ IMPLEMENTATION:
+ Creates copies of item_sum items for each sum level
+
+ RETURN
+ 0 if ok
+ In this case func is pointing to next not used element.
+ 1 on error
+*/
+
+bool JOIN::rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
+ Item_sum ***func)
+{
+ List_iterator_fast<Item> it(all_fields);
+ Item *first_field= fields.head();
+ uint level;
+
+ /*
+ Create field lists for the different levels
+
+ The idea here is to have a separate field list for each rollup level to
+ avoid all runtime checks of which columns should be NULL.
+
+ The list is stored in reverse order to get sum function in such an order
+ in func that it makes it easy to reset them with init_sum_functions()
+
+ Assuming: SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
+
+ rollup.fields[0] will contain list where a,b,c is NULL
+ rollup.fields[1] will contain list where b,c is NULL
+ ...
+ rollup.ref_pointer_array[#] points to fields for rollup.fields[#]
+ ...
+ sum_funcs_end[0] points to all sum functions
+ sum_funcs_end[1] points to all sum functions, except grand totals
+ ...
+ */
+
+ for (level=0 ; level < send_group_parts > 0 ; level++)
+ {
+ uint i;
+ uint pos= send_group_parts - level -1;
+ bool real_fields= 0;
+ Item *item;
+ List_iterator<Item> new_it(rollup.fields[pos]);
+ Item **ref_array_start= rollup.ref_pointer_arrays[pos];
+ ORDER *start_group;
+
+ /* Point to first hidden field */
+ Item **ref_array= ref_array_start + all_fields.elements-1;
+
+ /* Remember where the sum functions ends for the previous level */
+ sum_funcs_end[pos+1]= *func;
+
+ /* Find the start of the group for this level */
+ for (i= 0, start_group= group_list ;
+ i++ < pos ;
+ start_group= start_group->next)
+ ;
+
+ it.rewind();
+ while ((item= it++))
+ {
+ if (item == first_field)
+ {
+ real_fields= 1; // End of hidden fields
+ ref_array= ref_array_start;
+ }
+
+ if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
+ {
+ /*
+ This is a top level summary function that must be replaced with
+ a sum function that is reset for this level.
+
+ NOTE: This code creates an object which is not that nice in a
+ sub select. Fortunately it's not common to have rollup in
+ sub selects.
+ */
+ item= item->copy_or_same(thd);
+ ((Item_sum*) item)->make_unique();
+ if (((Item_sum*) item)->setup(thd))
+ return 1;
+ *(*func)= (Item_sum*) item;
+ (*func)++;
+ }
+ else if (real_fields)
+ {
+ /* Check if this is something that is part of this group by */
+ ORDER *group;
+ for (group= start_group ; group ; group= group->next)
+ {
+ if (*group->item == item)
+ {
+ /*
+ This is an element that is used by the GROUP BY and should be
+ set to NULL in this level
+ */
+ item->maybe_null= 1; // Value will be null sometimes
+ item= rollup.item_null;
+ break;
+ }
+ }
+ }
+ *ref_array= item;
+ if (real_fields)
+ {
+ (void) new_it++; // Point to next item
+ new_it.replace(item); // Replace previous
+ ref_array++;
+ }
+ else
+ ref_array--;
+ }
+ }
+ sum_funcs_end[0]= *func; // Point to last function
+ return 0;
+}
+
+/*
+ Send all rollup levels higher than the current one to the client
+
+ SYNOPSIS:
+ rollup_send_data()
+ idx Level we are on:
+ 0 = Total sum level
+ 1 = First group changed (a)
+ 2 = Second group changed (a,b)
+
+ SAMPLE
+ SELECT a, b, c SUM(b) FROM t1 GROUP BY a,b WITH ROLLUP
+
+ RETURN
+ 0 ok
+ 1 If send_data_failed()
+*/
+
+int JOIN::rollup_send_data(uint idx)
+{
+ uint i;
+ for (i= send_group_parts ; i-- > idx ; )
+ {
+ /* Get reference pointers to sum functions in place */
+ memcpy((char*) ref_pointer_array,
+ (char*) rollup.ref_pointer_arrays[i],
+ ref_pointer_array_size);
+ if ((!having || having->val_int()))
+ {
+ if (send_records < unit->select_limit_cnt &&
+ result->send_data(rollup.fields[i]))
+ return 1;
+ send_records++;
+ }
+ }
+ /* Restore ref_pointer_array */
+ set_items_ref_array(current_ref_pointer_array);
+ return 0;
+}
+
+
/****************************************************************************
+ EXPLAIN handling
+
Send a description about what how the select will be done to stdout
****************************************************************************/
@@ -8198,19 +8509,3 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
result, unit, select_lex, 0);
DBUG_RETURN(res);
}
-
-/*
- Free joins of subselect of this select.
-
- free_underlaid_joins()
- thd - THD pointer
- select - pointer to st_select_lex which subselects joins we will free
-*/
-
-void free_underlaid_joins(THD *thd, SELECT_LEX *select)
-{
- for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
- unit;
- unit= unit->next_unit())
- unit->cleanup();
-}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 7f3669f7478..df21d337b54 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -106,12 +106,22 @@ typedef struct st_join_table {
} JOIN_TAB;
-typedef struct st_position { /* Used in find_best */
+typedef struct st_position /* Used in find_best */
+{
double records_read;
JOIN_TAB *table;
KEYUSE *key;
} POSITION;
+typedef struct st_rollup
+{
+ enum State { STATE_NONE, STATE_INITED, STATE_READY };
+ State state;
+ Item *item_null;
+ Item ***ref_pointer_arrays;
+ List<Item> *fields;
+} ROLLUP;
+
class JOIN :public Sql_alloc
{
@@ -132,7 +142,7 @@ class JOIN :public Sql_alloc
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
- Item_sum **sum_funcs;
+ Item_sum **sum_funcs, ***sum_funcs_end;
Procedure *procedure;
Item *having;
Item *tmp_having; // To store Having when processed temporary table
@@ -146,6 +156,7 @@ class JOIN :public Sql_alloc
SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
+ ROLLUP rollup; // Used with rollup
bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group,
@@ -159,7 +170,7 @@ class JOIN :public Sql_alloc
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
- List<Item> & fields_list; // hold field list passed to mysql_select
+ List<Item> &fields_list; // hold field list passed to mysql_select
int error;
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
@@ -168,15 +179,15 @@ class JOIN :public Sql_alloc
SQL_SELECT *select; //created in optimisation phase
Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
- Item **items0, **items1, **items2, **items3;
+ Item **items0, **items1, **items2, **items3, **current_ref_pointer_array;
uint ref_pointer_array_size; // size of above in bytes
const char *zero_result_cause; // not 0 if exec must return zero result
bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
- JOIN(THD *thd, List<Item> &fields,
- ulong select_options, select_result *result):
+ JOIN(THD *thd_arg, List<Item> &fields, ulong select_options_arg,
+ select_result *result_arg):
join_tab(0),
table(0),
tables(0), const_tables(0),
@@ -184,13 +195,13 @@ class JOIN :public Sql_alloc
do_send_rows(1),
send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
- thd(thd),
+ thd(thd_arg),
sum_funcs(0),
procedure(0),
having(0), tmp_having(0),
- select_options(select_options),
- result(result),
- lock(thd->lock),
+ select_options(select_options_arg),
+ result(result_arg),
+ lock(thd_arg->lock),
select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)),
@@ -212,6 +223,7 @@ class JOIN :public Sql_alloc
bzero((char*) &keyuse,sizeof(keyuse));
tmp_table_param.copy_field=0;
tmp_table_param.end_write_records= HA_POS_ERROR;
+ rollup.state= ROLLUP::STATE_NONE;
}
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
@@ -221,15 +233,28 @@ class JOIN :public Sql_alloc
int optimize();
int reinit();
void exec();
- int cleanup(THD *thd);
+ int cleanup();
void restore_tmp();
+ bool alloc_func_list();
+ bool make_sum_func_list(List<Item> &all_fields, List<Item> &send_fields,
+ bool before_group_by);
+ inline void set_items_ref_array(Item **ptr)
+ {
+ memcpy((char*) ref_pointer_array, (char*) ptr, ref_pointer_array_size);
+ current_ref_pointer_array= ptr;
+ }
inline void init_items_ref_array()
{
items0= ref_pointer_array + all_fields.elements;
- ref_pointer_array_size= all_fields.elements*sizeof(Item*);
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
+ current_ref_pointer_array= items0;
}
+
+ bool rollup_init();
+ bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
+ Item_sum ***func);
+ int JOIN::rollup_send_data(uint idx);
};
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 16934e33798..cfe392dae7d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1004,12 +1004,7 @@ static void
append_identifier(THD *thd, String *packet, const char *name)
{
char qtype;
- if ((thd->variables.sql_mode & MODE_ANSI_QUOTES) ||
- (thd->variables.sql_mode & MODE_POSTGRESQL) ||
- (thd->variables.sql_mode & MODE_ORACLE) ||
- (thd->variables.sql_mode & MODE_MSSQL) ||
- (thd->variables.sql_mode & MODE_DB2) ||
- (thd->variables.sql_mode & MODE_SAPDB))
+ if (thd->variables.sql_mode & MODE_ANSI_QUOTES)
qtype= '\"';
else
qtype= '`';
@@ -1031,16 +1026,16 @@ append_identifier(THD *thd, String *packet, const char *name)
static int
store_create_info(THD *thd, TABLE *table, String *packet)
{
- my_bool foreign_db_mode= ((thd->variables.sql_mode & MODE_POSTGRESQL) ||
- (thd->variables.sql_mode & MODE_ORACLE) ||
- (thd->variables.sql_mode & MODE_MSSQL) ||
- (thd->variables.sql_mode & MODE_DB2) ||
- (thd->variables.sql_mode & MODE_SAPDB));
- my_bool limited_mysql_mode= ((thd->variables.sql_mode &
- MODE_NO_FIELD_OPTIONS) ||
- (thd->variables.sql_mode & MODE_MYSQL323) ||
- (thd->variables.sql_mode & MODE_MYSQL40));
-
+ my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
+ MODE_ORACLE |
+ MODE_MSSQL |
+ MODE_DB2 |
+ MODE_SAPDB |
+ MODE_ANSI)) != 0;
+ my_bool limited_mysql_mode= (thd->variables.sql_mode &
+ (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 |
+ MODE_MYSQL40)) != 0;
+
DBUG_ENTER("store_create_info");
DBUG_PRINT("enter",("table: %s",table->real_name));
diff --git a/sql/sql_state.c b/sql/sql_state.c
new file mode 100644
index 00000000000..355b847f239
--- /dev/null
+++ b/sql/sql_state.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 2000-2003 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 */
+
+/* Functions to map mysqld errno to sql_state */
+
+#include <my_global.h>
+#include <mysqld_error.h>
+
+struct st_map_errno_to_sqlstate
+{
+ uint mysql_errno;
+ const char *odbc_state;
+ const char *jdbc_state;
+};
+
+struct st_map_errno_to_sqlstate sqlstate_map[]=
+{
+#include <sql_state.h>
+};
+
+const char *mysql_errno_to_sqlstate(uint mysql_errno)
+{
+ uint first=0, end= array_elements(sqlstate_map)-1;
+ struct st_map_errno_to_sqlstate *map;
+
+ /* Do binary search in the sorted array */
+ while (first != end)
+ {
+ uint mid= (first+end)/2;
+ map= sqlstate_map+mid;
+ if (map->mysql_errno < mysql_errno)
+ first= mid+1;
+ else
+ end= mid;
+ }
+ map= sqlstate_map+first;
+ if (map->mysql_errno == mysql_errno)
+ return map->odbc_state;
+ return "HY000"; /* General error */
+}
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 6077c42bd1d..b4fad0dbebf 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -28,10 +28,6 @@
#include <floatingpoint.h>
#endif
-CHARSET_INFO *system_charset_info= &my_charset_utf8_general_ci;
-CHARSET_INFO *files_charset_info= &my_charset_utf8_general_ci;
-CHARSET_INFO *national_charset_info= &my_charset_utf8_general_ci;
-
extern gptr sql_alloc(unsigned size);
extern void sql_element_free(void *ptr);
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 8212bd0a2bd..d9b780ada5d 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -69,7 +69,10 @@ public:
Alloced_length=str.Alloced_length; alloced=0;
str_charset=str.str_charset;
}
- static void *operator new(size_t size) { return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ { return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size, MEM_ROOT *mem_root)
+ { return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr_arg,size_t size) /*lint -e715 */
{ sql_element_free(ptr_arg); }
~String() { free(); }
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index ea3b30d24e8..7cadf187181 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1731,10 +1731,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
fn_same(new_name_buff,table_name,3);
if (lower_case_table_names)
my_casedn_str(system_charset_info,new_name);
- if ((lower_case_table_names &&
- !my_strcasecmp(system_charset_info, new_name_buff,table_name)) ||
- (!lower_case_table_names &&
- !strcmp(new_name_buff,table_name)))
+ if (!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
new_name=table_name; // No. Make later check easier
else
{
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 1d0f37f0042..f47900d8276 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -389,7 +389,7 @@ int st_select_lex_unit::cleanup()
JOIN *join;
if ((join= sl->join))
{
- error|= sl->join->cleanup(thd);
+ error|= sl->join->cleanup();
delete join;
}
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1d735730801..efb5e42626d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -2971,7 +2971,7 @@ olap_opt:
}
lex->current_select->select_lex()->olap= CUBE_TYPE;
net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
- YYABORT; /* To be deleted in 4.1 */
+ YYABORT; /* To be deleted in 5.1 */
}
| WITH ROLLUP_SYM
{
@@ -2983,8 +2983,6 @@ olap_opt:
YYABORT;
}
lex->current_select->select_lex()->olap= ROLLUP_TYPE;
- net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "ROLLUP");
- YYABORT; /* To be deleted in 4.1 */
}
;
@@ -3039,20 +3037,7 @@ opt_limit_clause:
;
limit_clause:
- LIMIT
- {
- LEX *lex= Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->select_lex()->olap !=
- UNSPECIFIED_OLAP_TYPE)
- {
- net_printf(lex->thd, ER_WRONG_USAGE, "CUBE/ROLLUP",
- "LIMIT");
- YYABORT;
- }
- }
- limit_options
- {}
+ LIMIT limit_options {}
;
limit_options:
diff --git a/sql/unireg.h b/sql/unireg.h
index 6ddd9856724..cd459dfc783 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -106,8 +106,8 @@
#define SPECIAL_SAFE_MODE 2048
/* Extern defines */
-#define store_record(A,B) bmove_allign((A)->B,(A)->record[0],(size_t) (A)->reclength)
-#define restore_record(A,B) bmove_allign((A)->record[0],(A)->B,(size_t) (A)->reclength)
+#define store_record(A,B) bmove_align((A)->B,(A)->record[0],(size_t) (A)->reclength)
+#define restore_record(A,B) bmove_align((A)->record[0],(A)->B,(size_t) (A)->reclength)
#define cmp_record(A,B) memcmp((A)->record[0],(A)->B,(size_t) (A)->reclength)
#define empty_record(A) { \
restore_record((A),default_values); \