Commit aee0d02a authored by unknown's avatar unknown

Auto merged


BitKeeper/etc/logging_ok:
  auto-union
parents 69b8b99a 6feda00d
...@@ -266,8 +266,5 @@ ...@@ -266,8 +266,5 @@
#define ER_SELECT_REDUCED 1247 #define ER_SELECT_REDUCED 1247
#define ER_TABLENAME_NOT_ALLOWED_HERE 1248 #define ER_TABLENAME_NOT_ALLOWED_HERE 1248
#define ER_NOT_SUPPORTED_AUTH_MODE 1249 #define ER_NOT_SUPPORTED_AUTH_MODE 1249
#define ER_SPATIAL_CANT_HAVE_NULL 1250 #define ER_CUT_VALUE_GROUP_CONCAT 1250
#define ER_COLLATION_CHARSET_MISMATCH 1251 #define ER_ERROR_MESSAGES 251
#define ER_SLAVE_WAS_RUNNING 1252
#define ER_SLAVE_WAS_NOT_RUNNING 1253
#define ER_ERROR_MESSAGES 254
drop table if exists t1;
Warnings:
Note 1051 Unknown table 't1'
create table t1 (grp int, a bigint unsigned, c char(10) not null, d char(10) not null);
insert into t1 values (1,1,"a","a");
insert into t1 values (2,2,"b","a");
insert into t1 values (2,3,"c","b");
insert into t1 values (3,4,"E","a");
insert into t1 values (3,5,"C","b");
insert into t1 values (3,6,"D","b");
insert into t1 values (3,7,"d","d");
insert into t1 values (3,8,"d","d");
insert into t1 values (3,9,"D","c");
select grp,group_concat(c) from t1 group by grp;
grp group_concat(c)
1 a
2 b c
3 E C D d d D
select grp,group_concat(a,c) from t1 group by grp;
grp group_concat(a,c)
1 1a
2 2b 3c
3 4E 5C 6D 7d 8d 9D
select grp,group_concat("(",a,":",c,")") from t1 group by grp;
grp group_concat("(",a,":",c,")")
1 (1:a)
2 (2:b) (3:c)
3 (4:E) (5:C) (6:D) (7:d) (8:d) (9:D)
select grp,group_concat(c separator ",") from t1 group by grp;
grp group_concat(c separator ",")
1 a
2 b,c
3 E,C,D,d,d,D
select grp,group_concat(c separator "---->") from t1 group by grp;
grp group_concat(c separator "---->")
1 a
2 b---->c
3 E---->C---->D---->d---->d---->D
select grp,group_concat(c order by c) from t1 group by grp;
grp group_concat(c order by c)
1 a
2 b c
3 C D d d D E
select grp,group_concat(c order by c desc) from t1 group by grp;
grp group_concat(c order by c desc)
1 a
2 c b
3 E D d d D C
select grp,group_concat(d order by a) from t1 group by grp;
grp group_concat(d order by a)
1 a
2 a b
3 a b b d d c
select grp,group_concat(d order by a desc) from t1 group by grp;
grp group_concat(d order by a desc)
1 a
2 b a
3 c d d b b a
select grp,group_concat(a order by a,d+c) from t1 group by grp;
grp group_concat(a order by a,d+c)
1 1
2 2 3
3 4 5 6 7 8 9
select grp,group_concat(c order by 1) from t1 group by grp;
grp group_concat(c order by 1)
1 a
2 b c
3 C D d d D E
select grp,group_concat(c order by "c") from t1 group by grp;
grp group_concat(c order by "c")
1 a
2 b c
3 C D d d D E
select grp,group_concat(distinct c order by c) from t1 group by grp;
grp group_concat(distinct c order by c)
1 a
2 b c
3 C D E
select grp,group_concat(distinct c order by c desc) from t1 group by grp;
grp group_concat(distinct c order by c desc)
1 a
2 c b
3 E D C
select grp,group_concat(c order by c separator ",") from t1 group by grp;
grp group_concat(c order by c separator ",")
1 a
2 b,c
3 C,D,d,d,D,E
select grp,group_concat(c order by c desc separator ",") from t1 group by grp;
grp group_concat(c order by c desc separator ",")
1 a
2 c,b
3 E,D,d,d,D,C
select grp,group_concat(distinct c order by c separator ",") from t1 group by grp;
grp group_concat(distinct c order by c separator ",")
1 a
2 b,c
3 C,D,E
select grp,group_concat(distinct c order by c desc separator ",") from t1 group by grp;
grp group_concat(distinct c order by c desc separator ",")
1 a
2 c,b
3 E,D,C
select grp,group_concat(c order by grp desc) from t1 group by grp order by grp;
grp group_concat(c order by grp desc)
1 a
2 c b
3 D d d D C E
select grp, group_concat(a separator "")+0 from t1 group by grp;
grp group_concat(a separator "")+0
1 1
2 23
3 456789
select grp, group_concat(a separator "")+0.0 from t1 group by grp;
grp group_concat(a separator "")+0.0
1 1.0
2 23.0
3 456789.0
select grp, ROUND(group_concat(a separator "")) from t1 group by grp;
grp ROUND(group_concat(a separator ""))
1 1
2 23
3 456789
drop table t1;
create table t1 (grp int, c char(10));
insert into t1 values (1,NULL);
insert into t1 values (2,"b");
insert into t1 values (2,NULL);
insert into t1 values (3,"E");
insert into t1 values (3,NULL);
insert into t1 values (3,"D");
insert into t1 values (3,NULL);
insert into t1 values (3,NULL);
insert into t1 values (3,"D");
insert into t1 values (4,"");
insert into t1 values (5,NULL);
select grp,group_concat(c order by c) from t1 group by grp;
grp group_concat(c order by c)
1 NULL
2 b
3 D D E
4
5 NULL
set group_concat_max_len = 5;
select grp,group_concat(c) from t1 group by grp;
grp group_concat(c)
1 NULL
2 b
3 E D D
4
5 NULL
Warnings:
Warning 1250 1 line(s) was(were) cut by group_concat()
show warnings;
Level Code Message
Warning 1250 1 line(s) was(were) cut by group_concat()
select group_concat(sum(a)) from t1 group by grp;
Invalid use of group function
select grp,group_concat(c order by 2) from t1 group by grp;
Unknown column '2' in 'group statement'
drop table if exists t1;
#
# simple test of group_concat function
#
drop table if exists t1;
create table t1 (grp int, a bigint unsigned, c char(10) not null, d char(10) not null);
insert into t1 values (1,1,"a","a");
insert into t1 values (2,2,"b","a");
insert into t1 values (2,3,"c","b");
insert into t1 values (3,4,"E","a");
insert into t1 values (3,5,"C","b");
insert into t1 values (3,6,"D","b");
insert into t1 values (3,7,"d","d");
insert into t1 values (3,8,"d","d");
insert into t1 values (3,9,"D","c");
# Test of MySQL simple request
select grp,group_concat(c) from t1 group by grp;
select grp,group_concat(a,c) from t1 group by grp;
select grp,group_concat("(",a,":",c,")") from t1 group by grp;
# Test of MySQL with options
select grp,group_concat(c separator ",") from t1 group by grp;
select grp,group_concat(c separator "---->") from t1 group by grp;
select grp,group_concat(c order by c) from t1 group by grp;
select grp,group_concat(c order by c desc) from t1 group by grp;
select grp,group_concat(d order by a) from t1 group by grp;
select grp,group_concat(d order by a desc) from t1 group by grp;
select grp,group_concat(a order by a,d+c) from t1 group by grp;
select grp,group_concat(c order by 1) from t1 group by grp;
select grp,group_concat(c order by "c") from t1 group by grp;
select grp,group_concat(distinct c order by c) from t1 group by grp;
select grp,group_concat(distinct c order by c desc) from t1 group by grp;
select grp,group_concat(c order by c separator ",") from t1 group by grp;
select grp,group_concat(c order by c desc separator ",") from t1 group by grp;
select grp,group_concat(distinct c order by c separator ",") from t1 group by grp;
select grp,group_concat(distinct c order by c desc separator ",") from t1 group by grp;
# Test of SQL_LIST objects
select grp,group_concat(c order by grp desc) from t1 group by grp order by grp;
# Test transfer to real values
select grp, group_concat(a separator "")+0 from t1 group by grp;
select grp, group_concat(a separator "")+0.0 from t1 group by grp;
select grp, ROUND(group_concat(a separator "")) from t1 group by grp;
# Test NULL values
drop table t1;
create table t1 (grp int, c char(10));
insert into t1 values (1,NULL);
insert into t1 values (2,"b");
insert into t1 values (2,NULL);
insert into t1 values (3,"E");
insert into t1 values (3,NULL);
insert into t1 values (3,"D");
insert into t1 values (3,NULL);
insert into t1 values (3,NULL);
insert into t1 values (3,"D");
insert into t1 values (4,"");
insert into t1 values (5,NULL);
select grp,group_concat(c order by c) from t1 group by grp;
# Test warnings
set group_concat_max_len = 5;
select grp,group_concat(c) from t1 group by grp;
show warnings;
# Test errors
--error 1111
select group_concat(sum(a)) from t1 group by grp;
--error 1054
select grp,group_concat(c order by 2) from t1 group by grp;
drop table if exists t1;
...@@ -224,6 +224,7 @@ public: ...@@ -224,6 +224,7 @@ public:
friend class Item_sum_std; friend class Item_sum_std;
friend class Item_sum_min; friend class Item_sum_min;
friend class Item_sum_max; friend class Item_sum_max;
friend class Item_func_group_concat;
}; };
......
...@@ -1329,3 +1329,459 @@ String *Item_sum_udf_str::val_str(String *str) ...@@ -1329,3 +1329,459 @@ String *Item_sum_udf_str::val_str(String *str)
} }
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */
/*****************************************************************************
GROUP_CONCAT function
Syntax:
GROUP_CONCAT([DISTINCT] expr,... [ORDER BY col [ASC|DESC],...]
[SEPARATOR str_const])
concat of values from "group by" operation
*****************************************************************************/
/*
function of sort for syntax:
GROUP_CONCAT(DISTINCT expr,...)
*/
static int group_concat_key_cmp_with_distinct(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
for (int i= 0; i<item->arg_count_field; i++)
{
Item *field_item= item->expr[i];
Field *field= field_item->tmp_table_field();
if (field)
{
uint offset= field->offset();
int res= field->key_cmp(key1 + offset, key2 + offset);
/*
if key1 and key2 is not equal than field->key_cmp return offset. This function
must return value 1 for this case.
*/
if (res)
return 1;
}
}
return 0;
}
/*
function of sort for syntax:
GROUP_CONCAT(expr,... ORDER BY col,... )
*/
static int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
for (int i=0; i<item->arg_count_order; i++)
{
ORDER *order_item= item->order[i];
Item *item= *order_item->item;
Field *field= item->tmp_table_field();
if (field)
{
uint offset= field->offset();
bool dir= order_item->asc;
int res= field->key_cmp(key1 + offset, key2 + offset);
if (res)
return dir ? res : -res;
}
}
/*
We can't return 0 becouse tree class remove this item as dubl value.
*/
return 1;
}
/*
function of sort for syntax:
GROUP_CONCAT(DISTINCT expr,... ORDER BY col,... )
*/
static int group_concat_key_cmp_with_distinct_and_order(void* arg, byte* key1, byte* key2)
{
Item_func_group_concat* item= (Item_func_group_concat*)arg;
if (!group_concat_key_cmp_with_distinct(arg,key1,key2))
return 0;
return(group_concat_key_cmp_with_order(arg,key1,key2));
}
/*
create result
item is pointer to Item_func_group_concat
*/
static int dump_leaf_key(byte* key, uint32 count __attribute__((unused)),
Item_func_group_concat *group_concat_item)
{
char buff[MAX_FIELD_WIDTH];
String tmp((char *)&buff,sizeof(buff),default_charset_info);
String tmp2((char *)&buff,sizeof(buff),default_charset_info);
tmp.length(0);
for (int i= 0; i < group_concat_item->arg_show_fields; i++)
{
Item *show_item= group_concat_item->expr[i];
if (!show_item->const_item())
{
Field *f= show_item->tmp_table_field();
uint offset= f->offset();
char *sv= f->ptr;
f->ptr= (char *)key + offset;
String *res= f->val_str(&tmp,&tmp2);
group_concat_item->result.append(*res);
f->ptr= sv;
}
else
{
String *res= show_item->val_str(&tmp);
if (res)
group_concat_item->result.append(*res);
}
}
if (group_concat_item->tree_mode) // Last item of tree
{
group_concat_item->show_elements++;
if (group_concat_item->show_elements <
group_concat_item->tree->elements_in_tree)
group_concat_item->result.append(*group_concat_item->separator);
}
else
{
group_concat_item->result.append(*group_concat_item->separator);
}
/*
if length of result more than group_concat_max_len - stop !
*/
if (group_concat_item->result.length() >
group_concat_item->group_concat_max_len)
{
group_concat_item->count_cut_values++;
group_concat_item->result.length(group_concat_item->group_concat_max_len);
group_concat_item->warning_for_row= TRUE;
return 1;
}
return 0;
}
/*
Constructor of Item_func_group_concat
is_distinct - distinct
is_select - list of expression for show values
is_order - list of sort columns
is_separator - string value of separator
*/
Item_func_group_concat::Item_func_group_concat(int is_distinct,List<Item> *is_select,
SQL_LIST *is_order,String *is_separator):
Item_sum(),
tmp_table_param(0),
warning_available(false),
separator(is_separator),
tree(&tree_base),
table(0),
distinct(is_distinct),
tree_mode(0),
count_cut_values(0)
{
original= 0;
quick_group= 0;
mark_as_sum_func();
SELECT_LEX *select_lex= current_lex->current_select->select_lex();
order= 0;
arg_show_fields= arg_count_field= is_select->elements;
arg_count_order= is_order ? is_order->elements : 0;
arg_count= arg_count_field;
/*
We need to allocate:
args - arg_count+arg_count_order (for possible order items in temporare
tables)
expr - arg_count_field
order - arg_count_order
*/
args= (Item**)sql_alloc(sizeof(Item*)*(arg_count+arg_count_order+arg_count_field)+
sizeof(ORDER*)*arg_count_order);
if (!args)
{
my_error(ER_OUTOFMEMORY,MYF(0));
}
expr= args;
expr+= arg_count+arg_count_order;
if (arg_count_order)
{
order= (ORDER**)(expr + arg_count_field);
}
/*
fill args items of show and sort
*/
int i= 0;
List_iterator_fast<Item> li(*is_select);
Item *item_select;
while ((item_select= li++))
{
args[i]= expr[i]= item_select;
i++;
}
if (order)
{
uint j= 0;
for (ORDER *order_item= (ORDER*)is_order->first;
order_item != NULL;
order_item= order_item->next)
{
order[j++]= order_item;
}
}
}
Item_func_group_concat::~Item_func_group_concat()
{
/*
Free table and tree if they belong to this item (if item have not pointer
to original item from which was made copy => it own its objects )
*/
if (!original)
{
if (warning_available)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_CUT_VALUE_GROUP_CONCAT), count_cut_values);
((MYSQL_ERROR *)warning)->set_msg((char *)&warn_buff);
}
if (table)
free_tmp_table(current_thd, table);
if (tmp_table_param)
delete tmp_table_param;
if (tree_mode)
delete_tree(tree);
}
}
void Item_func_group_concat::reset()
{
result.length(0);
result.copy();
null_value= TRUE;
warning_for_row= false;
if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
table->file->delete_all_rows();
table->file->extra(HA_EXTRA_WRITE_CACHE);
}
if (tree_mode)
reset_tree(tree);
add();
}
bool Item_func_group_concat::add()
{
copy_fields(tmp_table_param);
copy_funcs(tmp_table_param->items_to_copy);
bool record_is_null= TRUE;
for (int i= 0; i < arg_show_fields; i++)
{
Item *show_item= expr[i];
if (!show_item->const_item())
{
Field *f= show_item->tmp_table_field();
if (!f->is_null())
record_is_null= FALSE;
}
}
if (record_is_null)
return 0;
null_value= FALSE;
if (tree_mode)
{
if (!tree_insert(tree, table->record[0], 0,tree->custom_arg))
return 1;
}
else
{
if (result.length() <= group_concat_max_len && !warning_for_row)
dump_leaf_key(table->record[0],1,
(Item_func_group_concat*)this);
}
return 0;
}
void Item_func_group_concat::reset_field()
{
if (tree_mode)
reset_tree(tree);
}
bool
Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
if (!thd->allow_sum_func)
{
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
return 1;
}
thd->allow_sum_func= 0;
maybe_null= 0;
for (uint i= 0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
return 1;
maybe_null |= args[i]->maybe_null;
}
for (int i= 0 ; i < arg_count_field ; i++)
{
if (expr[i]->fix_fields(thd, tables, expr + i) || expr[i]->check_cols(1))
return 1;
maybe_null |= expr[i]->maybe_null;
}
/*
Fix fields for order clause in function:
GROUP_CONCAT(expr,... ORDER BY col,... )
*/
for (int i= 0 ; i < arg_count_order ; i++)
{
ORDER *order_item= order[i];
Item *item=*order_item->item;
if (item->fix_fields(thd, tables, &item) || item->check_cols(1))
return 1;
}
result_field= 0;
null_value= 1;
fix_length_and_dec();
thd->allow_sum_func= 1;
if (!(tmp_table_param= new TMP_TABLE_PARAM))
return 1;
tables_list= tables;
fixed= 1;
return 0;
}
bool Item_func_group_concat::setup(THD *thd)
{
List<Item> list;
SELECT_LEX *select_lex= current_lex->current_select->select_lex();
if (select_lex->linkage == GLOBAL_OPTIONS_TYPE)
return 1;
/*
all not constant fields are push to list and create temp table
*/
for (uint i= 0; i < arg_count; i++)
{
Item *item= args[i];
if (list.push_back(item))
return 1;
if (item->const_item())
{
(void) item->val_int();
if (item->null_value)
always_null= 1;
}
}
List<Item> all_fields(list);
if (arg_count_order)
{
bool hidden_group_fields;
setup_group(thd, args, tables_list, list, all_fields, *order,
&hidden_group_fields);
}
count_field_types(tmp_table_param,all_fields,0);
/*
We have to create a temporary table for that we get descriptions of fields
(types, sizes and so on).
*/
if (!(table=create_tmp_table(thd, tmp_table_param, all_fields, 0,
0, 0, 0,select_lex->options | thd->options)))
return 1;
table->file->extra(HA_EXTRA_NO_ROWS);
table->no_rows= 1;
qsort_cmp2 compare_key;
tree_mode= distinct || arg_count_order;
/*
choise function of sort
*/
if (tree_mode)
{
if (arg_count_order)
{
if (distinct)
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct_and_order;
else
compare_key= (qsort_cmp2) group_concat_key_cmp_with_order;
}
else
{
if (distinct)
compare_key= (qsort_cmp2) group_concat_key_cmp_with_distinct;
else
compare_key= NULL;
}
/*
Create a tree of sort. Tree is used for a sort and a remove dubl
values (according with syntax of the function). If function does't
contain DISTINCT and ORDER BY clauses, we don't create this tree.
*/
init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0,
table->reclength, compare_key, 0, NULL, (void*) this);
max_elements_in_tree= ((table->reclength) ?
thd->variables.max_heap_table_size/table->reclength : 1);
};
item_thd= thd;
group_concat_max_len= thd->variables.group_concat_max_len;
/*
Copy table and tree_mode if they belong to this item (if item have not
pointer to original item from which was made copy => it own its objects)
*/
if (original)
{
original->table= table;
original->tree_mode= tree_mode;
}
return 0;
}
String* Item_func_group_concat::val_str(String* str)
{
if (null_value)
return 0;
if (tree_mode)
{
show_elements= 0;
tree_walk(tree, (tree_walk_action)&dump_leaf_key, (void*)this,
left_root_right);
}
else
{
if (!warning_for_row)
result.length(result.length()-separator->length());
}
if (count_cut_values && !warning_available)
{
warning_available= TRUE;
warning= push_warning(item_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CUT_VALUE_GROUP_CONCAT, NULL);
}
return &result;
}
...@@ -28,7 +28,7 @@ class Item_sum :public Item_result_field ...@@ -28,7 +28,7 @@ class Item_sum :public Item_result_field
public: public:
enum Sumfunctype {COUNT_FUNC,COUNT_DISTINCT_FUNC,SUM_FUNC,AVG_FUNC,MIN_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, MAX_FUNC, UNIQUE_USERS_FUNC,STD_FUNC,VARIANCE_FUNC,SUM_BIT_FUNC,
UDF_SUM_FUNC }; UDF_SUM_FUNC, GROUP_CONCAT_FUNC };
Item **args,*tmp_args[2]; Item **args,*tmp_args[2];
uint arg_count; uint arg_count;
...@@ -630,3 +630,87 @@ public: ...@@ -630,3 +630,87 @@ public:
}; };
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */
class Item_func_group_concat : public Item_sum
{
THD *item_thd;
TMP_TABLE_PARAM *tmp_table_param;
uint max_elements_in_tree;
void *warning;
bool warning_available;
public:
String result;
String *separator;
uint show_elements;
TREE tree_base;
TREE *tree;
TABLE *table;
int arg_count_order;
int arg_count_field;
int arg_show_fields;
int distinct;
Item **expr;
ORDER **order;
bool tree_mode;
int count_cut_values;
ulong group_concat_max_len;
bool warning_for_row;
TABLE_LIST *tables_list;
bool always_null;
/*
Following is 0 normal object and pointer to original one for copy
(to correctly free resources)
*/
Item_func_group_concat *original;
Item_func_group_concat(int is_distinct,List<Item> *is_select,
SQL_LIST *is_order,String *is_separator);
Item_func_group_concat(THD *thd, Item_func_group_concat &item)
:Item_sum(thd, item),item_thd(thd),
tmp_table_param(item.tmp_table_param),
max_elements_in_tree(item.max_elements_in_tree),
warning(item.warning),
warning_available(item.warning_available),
separator(item.separator),
show_elements(item.show_elements),
tree(item.tree),
table(item.table),
arg_count_order(item.arg_count_order),
arg_count_field(item.arg_count_field),
arg_show_fields(item.arg_show_fields),
distinct(item.distinct),
expr(item.expr),
order(item.order),
tree_mode(0),
count_cut_values(item.count_cut_values),
group_concat_max_len(item.group_concat_max_len),
warning_for_row(item.warning_for_row),
tables_list(item.tables_list),
original(&item)
{
quick_group = 0;
};
~Item_func_group_concat();
enum Sumfunctype sum_func () const {return GROUP_CONCAT_FUNC;}
const char *func_name() const { return "group_concat"; }
enum Type type() const { return SUM_FUNC_ITEM; }
virtual Item_result result_type () const { return STRING_RESULT; }
void reset();
bool add();
void reset_field();
bool fix_fields(THD *, TABLE_LIST *, Item **);
bool setup(THD *thd);
virtual void update_field(int offset) {};
double val()
{
String *res; res=val_str(&str_value);
return res ? atof(res->c_ptr()) : 0.0;
}
longlong val_int()
{
String *res; res=val_str(&str_value);
return res ? strtoll(res->c_ptr(),(char**) 0,10) : (longlong) 0;
}
String* val_str(String* str);
};
...@@ -335,6 +335,7 @@ static SYMBOL symbols[] = { ...@@ -335,6 +335,7 @@ static SYMBOL symbols[] = {
{ "ROWS", SYM(ROWS_SYM),0,0}, { "ROWS", SYM(ROWS_SYM),0,0},
{ "RTREE", SYM(RTREE_SYM),0,0}, { "RTREE", SYM(RTREE_SYM),0,0},
{ "SECOND", SYM(SECOND_SYM),0,0}, { "SECOND", SYM(SECOND_SYM),0,0},
{ "SEPARATOR", SYM(SEPARATOR_SYM),0,0},
{ "SELECT", SYM(SELECT_SYM),0,0}, { "SELECT", SYM(SELECT_SYM),0,0},
{ "SERIAL", SYM(SERIAL_SYM),0,0}, { "SERIAL", SYM(SERIAL_SYM),0,0},
{ "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0}, { "SERIALIZABLE", SYM(SERIALIZABLE_SYM),0,0},
...@@ -503,6 +504,7 @@ static SYMBOL sql_functions[] = { ...@@ -503,6 +504,7 @@ static SYMBOL sql_functions[] = {
{ "GEOMFROMWKB", SYM(GEOMFROMWKB),0,0}, { "GEOMFROMWKB", SYM(GEOMFROMWKB),0,0},
{ "GLENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)}, { "GLENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_glength)},
{ "GREATEST", SYM(GREATEST_SYM),0,0}, { "GREATEST", SYM(GREATEST_SYM),0,0},
{ "GROUP_CONCAT", SYM(GROUP_CONCAT_SYM),0,0},
{ "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS),0,0}, { "GROUP_UNIQUE_USERS", SYM(GROUP_UNIQUE_USERS),0,0},
{ "HEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)}, { "HEX", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_hex)},
{ "IFNULL", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)}, { "IFNULL", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_ifnull)},
......
...@@ -547,8 +547,8 @@ int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, ...@@ -547,8 +547,8 @@ int check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
List<Item> &values, ulong counter); List<Item> &values, ulong counter);
/* sql_error.cc */ /* sql_error.cc */
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
const char *msg); const char *msg);
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *format, ...); uint code, const char *format, ...);
void mysql_reset_errors(THD *thd); void mysql_reset_errors(THD *thd);
......
...@@ -166,7 +166,7 @@ ...@@ -166,7 +166,7 @@
"Result string is longer than max_allowed_packet", "Result string is longer than max_allowed_packet",
"The used table type doesn't support BLOB/TEXT columns", "The used table type doesn't support BLOB/TEXT columns",
"The used table type doesn't support AUTO_INCREMENT columns", "The used table type doesn't support AUTO_INCREMENT columns",
"INSERT DELAYED can't be used with table '%-.64s' because it is locked with LOCK TABLES", "INSERT DELAYED can't be used with table '%-.64s', because it is locked with LOCK TABLES",
"Incorrect column name '%-.100s'", "Incorrect column name '%-.100s'",
"The used table handler can't index column '%-.64s'", "The used table handler can't index column '%-.64s'",
"All tables in the MERGE table are not identically defined", "All tables in the MERGE table are not identically defined",
...@@ -198,7 +198,7 @@ ...@@ -198,7 +198,7 @@
"Table '%-.64s' is marked as crashed and should be repaired", "Table '%-.64s' is marked as crashed and should be repaired",
"Table '%-.64s' is marked as crashed and last (automatic?) repair failed", "Table '%-.64s' is marked as crashed and last (automatic?) repair failed",
"Some non-transactional changed tables couldn't be rolled back", "Some non-transactional changed tables couldn't be rolled back",
"Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again", "Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage. Increase this mysqld variable and try again',
"This operation cannot be performed with a running slave, run STOP SLAVE first", "This operation cannot be performed with a running slave, run STOP SLAVE first",
"This operation requires a running slave, configure slave and do START SLAVE", "This operation requires a running slave, configure slave and do START SLAVE",
"The server is not configured as slave, fix in config file or with CHANGE MASTER TO", "The server is not configured as slave, fix in config file or with CHANGE MASTER TO",
...@@ -250,8 +250,5 @@ ...@@ -250,8 +250,5 @@
"Every derived table must have it's own alias", "Every derived table must have it's own alias",
"Select %u was reduced during optimisation", "Select %u was reduced during optimisation",
"Table '%-.64s' from one of SELECT's can not be used in %-.32s" "Table '%-.64s' from one of SELECT's can not be used in %-.32s"
"Client does not support authentication protocol requested by server. Consider upgrading MySQL client" "Client does not support authentication protocol requested by server. Consider upgrading MySQL client",
"All parts of a SPATIAL KEY must be NOT NULL" "%d line(s) was(were) cut by group_concat()"
"COLLATION '%s' is not valid for CHARACTER SET '%s'"
"The slave was already running"
"The slave was already stopped"
...@@ -34,8 +34,6 @@ enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN }; ...@@ -34,8 +34,6 @@ enum enum_log_type { LOG_CLOSED, LOG_NORMAL, LOG_NEW, LOG_BIN };
enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON, enum enum_delay_key_write { DELAY_KEY_WRITE_NONE, DELAY_KEY_WRITE_ON,
DELAY_KEY_WRITE_ALL }; DELAY_KEY_WRITE_ALL };
extern char internal_table_name[2];
// log info errors // log info errors
#define LOG_INFO_EOF -1 #define LOG_INFO_EOF -1
#define LOG_INFO_IO -2 #define LOG_INFO_IO -2
...@@ -145,9 +143,7 @@ public: ...@@ -145,9 +143,7 @@ public:
int generate_new_name(char *new_name,const char *old_name); int generate_new_name(char *new_name,const char *old_name);
void make_log_name(char* buf, const char* log_ident); void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name); bool is_active(const char* log_file_name);
int update_log_index(LOG_INFO* linfo);
int purge_logs(THD* thd, const char* to_log); int purge_logs(THD* thd, const char* to_log);
int purge_logs_before_date(THD* thd, time_t purge_time);
int purge_first_log(struct st_relay_log_info* rli); int purge_first_log(struct st_relay_log_info* rli);
bool reset_logs(THD* thd); bool reset_logs(THD* thd);
// if we are exiting, we also want to close the index file // if we are exiting, we also want to close the index file
...@@ -174,6 +170,32 @@ public: ...@@ -174,6 +170,32 @@ public:
/* character conversion tables */ /* character conversion tables */
class CONVERT;
CONVERT *get_convert_set(const char *name_ptr);
class CONVERT
{
const uchar *from_map,*to_map;
void convert_array(const uchar *mapping,uchar *buff,uint length);
public:
const char *name;
uint numb;
CONVERT(const char *name_par,uchar *from_par,uchar *to_par, uint number)
:from_map(from_par),to_map(to_par),name(name_par),numb(number) {}
friend CONVERT *get_convert_set(const char *name_ptr);
inline void convert(char *a,uint length)
{
convert_array(from_map, (uchar*) a,length);
}
char *store_dest(char *to, const char *from, uint length)
{
for (const char *end=from+length ; from != end ; from++)
*to++= to_map[(uchar) *from];
return to;
}
bool store(String *, const char *,uint);
inline uint number() { return numb; }
};
typedef struct st_copy_info { typedef struct st_copy_info {
ha_rows records; ha_rows records;
...@@ -305,7 +327,12 @@ public: ...@@ -305,7 +327,12 @@ public:
const char *msg_arg) const char *msg_arg)
:code(code_arg), level(level_arg) :code(code_arg), level(level_arg)
{ {
msg=sql_strdup(msg_arg); if (msg_arg)
msg=sql_strdup(msg_arg);
}
inline void set_msg(const char *msg_arg)
{
msg=sql_strdup(msg_arg);
} }
}; };
...@@ -333,6 +360,10 @@ class select_result; ...@@ -333,6 +360,10 @@ class select_result;
#define THD_SENTRY_MAGIC 0xfeedd1ff #define THD_SENTRY_MAGIC 0xfeedd1ff
#define THD_SENTRY_GONE 0xdeadbeef #define THD_SENTRY_GONE 0xdeadbeef
#ifdef EMBEDDED_LIBRARY
typedef struct st_mysql;
#endif
#define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC) #define THD_CHECK_SENTRY(thd) DBUG_ASSERT(thd->dbug_sentry == THD_SENTRY_MAGIC)
struct system_variables struct system_variables
...@@ -365,8 +396,7 @@ struct system_variables ...@@ -365,8 +396,7 @@ struct system_variables
ulong tmp_table_size; ulong tmp_table_size;
ulong tx_isolation; ulong tx_isolation;
ulong sql_mode; ulong sql_mode;
ulong default_week_format; ulong group_concat_max_len;
/* /*
In slave thread we need to know in behalf of which In slave thread we need to know in behalf of which
thread the query is being run to replicate temp tables properly thread the query is being run to replicate temp tables properly
...@@ -374,10 +404,9 @@ struct system_variables ...@@ -374,10 +404,9 @@ struct system_variables
ulong pseudo_thread_id; ulong pseudo_thread_id;
my_bool log_warnings; my_bool log_warnings;
my_bool low_priority_updates; my_bool low_priority_updates;
my_bool new_mode;
my_bool convert_result_charset;
CONVERT *convert_set;
CHARSET_INFO *thd_charset; CHARSET_INFO *thd_charset;
}; };
...@@ -424,9 +453,8 @@ public: ...@@ -424,9 +453,8 @@ public:
db - currently selected database db - currently selected database
ip - client IP ip - client IP
*/ */
char *host,*user,*priv_user,*db,*ip; char *host,*user,*priv_user,*db,*ip;
/* remote (peer) port */
uint16 peer_port;
/* Points to info-string that will show in SHOW PROCESSLIST */ /* Points to info-string that will show in SHOW PROCESSLIST */
const char *proc_info; const char *proc_info;
/* points to host if host is available, otherwise points to ip */ /* points to host if host is available, otherwise points to ip */
...@@ -549,7 +577,6 @@ public: ...@@ -549,7 +577,6 @@ public:
void init(void); void init(void);
void change_user(void); void change_user(void);
void init_for_queries();
void cleanup(void); void cleanup(void);
bool store_globals(); bool store_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE #ifdef SIGNAL_WITH_VIO_CLOSE
...@@ -657,9 +684,7 @@ public: ...@@ -657,9 +684,7 @@ public:
{ {
is_fatal_error= 1; is_fatal_error= 1;
net.report_error= 1; net.report_error= 1;
DBUG_PRINT("error",("Fatal error set"));
} }
inline CHARSET_INFO *charset() { return variables.thd_charset; }
}; };
/* /*
...@@ -885,11 +910,10 @@ class Table_ident :public Sql_alloc ...@@ -885,11 +910,10 @@ class Table_ident :public Sql_alloc
LEX_STRING db; LEX_STRING db;
LEX_STRING table; LEX_STRING table;
SELECT_LEX_UNIT *sel; SELECT_LEX_UNIT *sel;
inline Table_ident(THD *thd, LEX_STRING db_arg, LEX_STRING table_arg, inline Table_ident(LEX_STRING db_arg, LEX_STRING table_arg, bool force)
bool force)
:table(table_arg), sel((SELECT_LEX_UNIT *)0) :table(table_arg), sel((SELECT_LEX_UNIT *)0)
{ {
if (!force && (thd->client_capabilities & CLIENT_NO_SCHEMA)) if (!force && (current_thd->client_capabilities & CLIENT_NO_SCHEMA))
db.str=0; db.str=0;
else else
db= db_arg; db= db_arg;
...@@ -901,8 +925,7 @@ class Table_ident :public Sql_alloc ...@@ -901,8 +925,7 @@ class Table_ident :public Sql_alloc
} }
inline Table_ident(SELECT_LEX_UNIT *s) : sel(s) inline Table_ident(SELECT_LEX_UNIT *s) : sel(s)
{ {
/* We must have a table name here as this is used with add_table_to_list */ db.str=0; table.str=(char *)""; table.length=0;
db.str=0; table.str= internal_table_name; table.length=1;
} }
inline void change_db(char *db_name) inline void change_db(char *db_name)
{ {
...@@ -919,7 +942,6 @@ class user_var_entry ...@@ -919,7 +942,6 @@ class user_var_entry
ulong length, update_query_id, used_query_id; ulong length, update_query_id, used_query_id;
Item_result type; Item_result type;
CHARSET_INFO *var_charset; CHARSET_INFO *var_charset;
enum Item::coercion var_coercibility;
}; };
/* Class for unique (removing of duplicates) */ /* Class for unique (removing of duplicates) */
...@@ -978,7 +1000,7 @@ class multi_update : public select_result ...@@ -978,7 +1000,7 @@ class multi_update : public select_result
{ {
TABLE_LIST *all_tables, *update_tables, *table_being_updated; TABLE_LIST *all_tables, *update_tables, *table_being_updated;
THD *thd; THD *thd;
TABLE **tmp_tables, *main_table, *table_to_update; TABLE **tmp_tables, *main_table;
TMP_TABLE_PARAM *tmp_table_param; TMP_TABLE_PARAM *tmp_table_param;
ha_rows updated, found; ha_rows updated, found;
List <Item> *fields, *values; List <Item> *fields, *values;
......
...@@ -80,14 +80,19 @@ void mysql_reset_errors(THD *thd) ...@@ -80,14 +80,19 @@ void mysql_reset_errors(THD *thd)
level Severity of warning (note, warning, error ...) level Severity of warning (note, warning, error ...)
code Error number code Error number
msg Clear error message msg Clear error message
RETURN
pointer on MYSQL_ERROR object
*/ */
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
const char *msg) uint code, const char *msg)
{ {
if (thd->query_id != thd->warn_id) if (thd->query_id != thd->warn_id)
mysql_reset_errors(thd); mysql_reset_errors(thd);
MYSQL_ERROR *err = NULL;
if (thd->warn_list.elements < thd->variables.max_error_count) if (thd->warn_list.elements < thd->variables.max_error_count)
{ {
/* /*
...@@ -96,13 +101,14 @@ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, ...@@ -96,13 +101,14 @@ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code,
*/ */
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC, &thd->warn_root); my_pthread_setspecific_ptr(THR_MALLOC, &thd->warn_root);
MYSQL_ERROR *err= new MYSQL_ERROR(code, level, msg); err = new MYSQL_ERROR(code, level, msg);
if (err) if (err)
thd->warn_list.push_back(err); thd->warn_list.push_back(err);
my_pthread_setspecific_ptr(THR_MALLOC, old_root); my_pthread_setspecific_ptr(THR_MALLOC, old_root);
} }
thd->warn_count[(uint) level]++; thd->warn_count[(uint) level]++;
thd->total_warn_count++; thd->total_warn_count++;
return err;
} }
/* /*
......
...@@ -478,6 +478,7 @@ typedef struct st_lex ...@@ -478,6 +478,7 @@ typedef struct st_lex
uint slave_thd_opt; uint slave_thd_opt;
CHARSET_INFO *charset; CHARSET_INFO *charset;
char *help_arg; char *help_arg;
SQL_LIST *gorder_list;
inline void uncacheable() inline void uncacheable()
{ {
......
...@@ -336,6 +336,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -336,6 +336,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token ROW_SYM %token ROW_SYM
%token RTREE_SYM %token RTREE_SYM
%token SET %token SET
%token SEPARATOR_SYM
%token SERIAL_SYM %token SERIAL_SYM
%token SERIALIZABLE_SYM %token SERIALIZABLE_SYM
%token SESSION_SYM %token SESSION_SYM
...@@ -462,6 +463,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -462,6 +463,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token GEOMFROMTEXT %token GEOMFROMTEXT
%token GEOMFROMWKB %token GEOMFROMWKB
%token GEOMETRYCOLLECTION %token GEOMETRYCOLLECTION
%token GROUP_CONCAT_SYM
%token GROUP_UNIQUE_USERS %token GROUP_UNIQUE_USERS
%token HOUR_MINUTE_SYM %token HOUR_MINUTE_SYM
%token HOUR_SECOND_SYM %token HOUR_SECOND_SYM
...@@ -575,13 +577,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -575,13 +577,13 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
opt_escape opt_escape
%type <string> %type <string>
text_string text_string opt_gconcat_separator
%type <num> %type <num>
type int_type real_type order_dir opt_field_spec lock_option type int_type real_type order_dir opt_field_spec lock_option
udf_type if_exists opt_local opt_table_options table_options udf_type if_exists opt_local opt_table_options table_options
table_option opt_if_not_exists opt_var_type opt_var_ident_type table_option opt_if_not_exists opt_var_type opt_var_ident_type
delete_option opt_temporary all_or_any delete_option opt_temporary all_or_any opt_distinct
%type <ulong_num> %type <ulong_num>
ULONG_NUM raid_types merge_insert_types ULONG_NUM raid_types merge_insert_types
...@@ -2554,7 +2556,35 @@ sum_expr: ...@@ -2554,7 +2556,35 @@ sum_expr:
| VARIANCE_SYM '(' in_sum_expr ')' | VARIANCE_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_variance($3); } { $$=new Item_sum_variance($3); }
| SUM_SYM '(' in_sum_expr ')' | SUM_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_sum($3); }; { $$=new Item_sum_sum($3); }
| GROUP_CONCAT_SYM '(' opt_distinct expr_list opt_gorder_clause opt_gconcat_separator ')'
{
$$=new Item_func_group_concat($3,$4,Lex->gorder_list,$6);
$4->empty();
};
opt_distinct:
/* empty */ { $$ = 0; }
|DISTINCT { $$ = 1; };
opt_gconcat_separator:
/* empty */ { $$ = new String(" ",1,default_charset_info); }
|SEPARATOR_SYM text_string { $$ = $2; };
opt_gorder_clause:
/* empty */
{
LEX *lex=Lex;
lex->gorder_list = NULL;
}
| order_clause
{
LEX *lex=Lex;
lex->gorder_list= (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,sizeof(st_sql_list));
lex->current_select->order_list.empty();
};
in_sum_expr: in_sum_expr:
opt_all opt_all
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment