Merge work:/home/bk/mysql-4.0

into mysql.sashanet.com:/home/sasha/src/bk/mysql-4.0
This commit is contained in:
sasha@mysql.sashanet.com 2001-08-03 16:09:36 -06:00
commit a98a7ffe7e
57 changed files with 823 additions and 475 deletions

View File

@ -45712,6 +45712,10 @@ Our TODO section contains what we plan to have in 4.0. @xref{TODO MySQL 4.0}.
@itemize @bullet
@item
Speed up all internal list handling.
@item
Added support for @code{UNION}.
@item
Allow ANSI SQL syntax @code{X'hexadecimal-number'}
@item
Tree-like cache to speed up bulk inserts and

View File

@ -210,7 +210,10 @@
#define ER_READ_ONLY_TRANSACTION 1207
#define ER_DROP_DB_WITH_READ_LOCK 1208
#define ER_CREATE_DB_WITH_READ_LOCK 1209
#define ER_CONNECT_TO_MASTER 1210
#define ER_QUERY_ON_MASTER 1211
#define ER_ERROR_WHEN_EXECUTING_COMMAND 1212
#define ER_ERROR_MESSAGES 213
#define ER_WRONG_ARGUMENTS 1210
#define ER_CONNECT_TO_MASTER 1211
#define ER_QUERY_ON_MASTER 1212
#define ER_ERROR_WHEN_EXECUTING_COMMAND 1213
#define ER_WRONG_USAGE 1214
#define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1215
#define ER_ERROR_MESSAGES 216

60
mysql-test/r/union.result Normal file
View File

@ -0,0 +1,60 @@
a b
1 a
2 b
3 c
4 d
5 f
6 e
a b
1 a
2 b
3 c
3 c
3 c
4 d
5 f
6 e
a b
1 a
2 b
3 c
3 c
3 c
4 d
6 e
5 f
a b
1 a
2 b
3 c
3 c
3 c
4 d
5 f
6 e
7 g
0 #
0 #
1 a
2 b
3 c
3 c
3 c
4 d
5 f
6 e
7 g
a b
1 a
2 b
3 c
t1 b count(*)
t1 a 1
t1 b 1
t1 c 2
t2 c 1
t2 d 1
t2 e 1
t2 f 1
table type possible_keys key key_len ref rows Extra
t2 ALL NULL NULL NULL NULL 4

View File

@ -1,15 +0,0 @@
a b
1 a
2 b
3 c
4 d
5 e
6 f
a b
1 a
2 b
3 c
3 c
4 d
5 e
6 f

View File

@ -2,6 +2,7 @@
# Test of procedure analyse
#
drop table if exists t1,t2;
create table t1 (i int, j int);
insert into t1 values (1,2), (3,4), (5,6), (7,8);
select * from t1 procedure analyse();

29
mysql-test/t/union.test Normal file
View File

@ -0,0 +1,29 @@
#
# Test of unions
#
drop table if exists t1,t2;
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,'a'),(2,'b'),(3,'c'),(3,'c');
CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,'c'),(4,'d'),(5,'f'),(6,'e');
select a,b from t1 union select a,b from t2;
select a,b from t1 union all select a,b from t2;
select a,b from t1 union all select a,b from t2 order by b;
select a,b from t1 union all select a,b from t2 union select 7,'g';
select 0,'#' union select a,b from t1 union all select a,b from t2 union select 7,'gg';
select a,b from t1 union select a,b from t1;
select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 group by b;
explain select a,b from t1 union all select a,b from t2;
# Test some error conditions with UNION
--error 1213
select a,b from t1 into outfile 'skr' union select a,b from t2;
--error 1213
select a,b from t1 order by a union select a,b from t2;
--error 1214
select a,b from t1 union select a from t2;
drop table t1,t2;

View File

@ -1,16 +0,0 @@
#
# Test of unions
#
drop table if exists t1,t2;
CREATE TABLE t1 (a int not null, b char (10) not null);
insert into t1 values(1,"a"),(2,"b"),(3,"c");
CREATE TABLE t2 (a int not null, b char (10) not null);
insert into t2 values (3,"c"),(4,"d"),(5,"e"),(6,"f");
select a,b from t1 union select a,b from t2;
select a,b from t1 union all select a,b from t2;
drop table t1,t2;

View File

@ -83,7 +83,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
slave.cc sql_repl.cc \
mini_client.cc mini_client_errors.c \
md5.c stacktrace.c sql_unions.cc
md5.c stacktrace.c sql_union.cc
gen_lex_hash_SOURCES = gen_lex_hash.cc
gen_lex_hash_LDADD = $(LDADD) $(CXXLDFLAGS)
mysqlbinlog_SOURCES = mysqlbinlog.cc mini_client.cc net_serv.cc \

View File

@ -677,5 +677,6 @@ bool field_is_equal_to_item(Field *field,Item *item)
#ifdef __GNUC__
template class List<Item>;
template class List_iterator<Item>;
template class List_iterator_fast<Item>;
template class List<List_item>;
#endif

View File

@ -1129,7 +1129,7 @@ void Item_cond::update_used_tables()
{
used_tables_cache=0;
const_item_cache=1;
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@ -1143,7 +1143,7 @@ void Item_cond::update_used_tables()
void Item_cond::print(String *str)
{
str->append('(');
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
if ((item=li++))
item->print(str);
@ -1160,7 +1160,7 @@ void Item_cond::print(String *str)
longlong Item_cond_and::val_int()
{
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@ -1179,7 +1179,7 @@ longlong Item_cond_and::val_int()
longlong Item_cond_or::val_int()
{
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
null_value=0;
while ((item=li++))

View File

@ -43,7 +43,7 @@ Item_func::Item_func(List<Item> &list)
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
uint i=0;
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
@ -1983,7 +1983,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
bool Item_func_match::fix_index()
{
List_iterator<Item> li(fields);
List_iterator_fast<Item> li(fields);
Item_field *item;
uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, key;

View File

@ -30,7 +30,7 @@ Item_sum::Item_sum(List<Item> &list)
if ((args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
{
uint i=0;
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
@ -790,74 +790,71 @@ String *Item_std_field::val_str(String *str)
static int simple_raw_key_cmp(void* arg, byte* key1, byte* key2)
{
return memcmp(key1, key2, (int)arg);
return memcmp(key1, key2, (int) arg);
}
static int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
{
return my_sortcmp(key1, key2, (int)arg);
return my_sortcmp(key1, key2, (int) arg);
}
// did not make this one static - at least gcc gets confused when
// I try to declare a static function as a friend. If you can figure
// out the syntax to make a static function a friend, make this one
// static
/*
Did not make this one static - at least gcc gets confused when
I try to declare a static function as a friend. If you can figure
out the syntax to make a static function a friend, make this one
static
*/
int composite_key_cmp(void* arg, byte* key1, byte* key2)
{
Item_sum_count_distinct* item = (Item_sum_count_distinct*)arg;
Field** field = item->table->field, **field_end;
field_end = field + item->table->fields;
for(; field < field_end; ++field)
{
int res;
Field* f = *field;
int len = f->pack_length();
switch((*field)->type())
{
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
res = f->key_cmp(key1, key2);
break;
default:
res = memcmp(key1, key2, len);
break;
}
if(res)
return res;
key1 += len;
key2 += len;
}
Field **field = item->table->field;
Field **field_end= field + item->table->fields;
uint32 *lengths=item->field_lengths;
for (; field < field_end; ++field)
{
Field* f = *field;
int len = *lengths++;
int res = f->key_cmp(key1, key2);
if (res)
return res;
key1 += len;
key2 += len;
}
return 0;
}
// helper function for walking the tree when we dump it to MyISAM -
// tree_walk will call it for each
// leaf
/*
helper function for walking the tree when we dump it to MyISAM -
tree_walk will call it for each leaf
*/
int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct* item)
{
char* buf = item->table->record[0];
int error;
// the first item->rec_offset bytes are taken care of with
// restore_record(table,2) in setup()
/*
The first item->rec_offset bytes are taken care of with
restore_record(table,2) in setup()
*/
memcpy(buf + item->rec_offset, key, item->tree.size_of_element);
if ((error = item->table->file->write_row(buf)))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
return 1;
if (error != HA_ERR_FOUND_DUPP_KEY &&
error != HA_ERR_FOUND_DUPP_UNIQUE)
return 1;
}
return 0;
}
Item_sum_count_distinct::~Item_sum_count_distinct()
{
if (table)
free_tmp_table(current_thd, table);
delete tmp_table_param;
if(use_tree)
if (use_tree)
delete_tree(&tree);
}
@ -895,91 +892,108 @@ bool Item_sum_count_distinct::setup(THD *thd)
tmp_table_param->cleanup();
}
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, 1,
0, 0, current_lex->select->options | thd->options)))
0, 0,
current_lex->select->options | thd->options)))
return 1;
table->file->extra(HA_EXTRA_NO_ROWS); // Don't update rows
table->no_rows=1;
if(table->db_type == DB_TYPE_HEAP) // no blobs, otherwise it would be
// MyISAM
{
qsort_cmp2 compare_key;
void* cmp_arg;
int key_len;
// no blobs, otherwise it would be MyISAM
if (table->db_type == DB_TYPE_HEAP)
{
qsort_cmp2 compare_key;
void* cmp_arg;
int key_len;
// to make things easier for dump_leaf if we ever have to dump to
// MyISAM
restore_record(table,2);
// to make things easier for dump_leaf if we ever have to dump to MyISAM
restore_record(table,2);
if(table->fields == 1) // if we have only one field, which is
// the most common use of count(distinct), it is much faster
// to use a simpler key compare method that can take advantage
// of not having to worry about other fields
{
Field* field = table->field[0];
switch(field->type())
{
// if we have a string, we must take care of charsets
// and case sensitivity
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
compare_key = (qsort_cmp2)(field->binary() ? simple_raw_key_cmp:
simple_str_key_cmp);
break;
default: // since at this point we cannot have blobs
// anything else can be compared with memcmp
compare_key = (qsort_cmp2)simple_raw_key_cmp;
break;
}
cmp_arg = (void*)(key_len = field->pack_length());
rec_offset = 1;
}
else // too bad, cannot cheat - there is more than one field
{
bool all_binary = 1;
Field** field, **field_end;
field_end = (field = table->field) + table->fields;
for(key_len = 0; field < field_end; ++field)
{
key_len += (*field)->pack_length();
if(!(*field)->binary())
all_binary = 0;
}
rec_offset = table->reclength - key_len;
if(all_binary)
{
compare_key = (qsort_cmp2)simple_raw_key_cmp;
cmp_arg = (void*)key_len;
}
else
{
compare_key = (qsort_cmp2)composite_key_cmp ;
cmp_arg = (void*)this;
}
}
init_tree(&tree, min(max_heap_table_size, sortbuff_size/16), 0,
key_len, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
// the only time key_len could be 0 is if someone does
// count(distinct) on a char(0) field - stupid thing to do,
// but this has to be handled - otherwise someone can crash
// the server with a DoS attack
max_elements_in_tree = (key_len) ? max_heap_table_size/key_len :
1;
if (table->fields == 1)
{
/*
If we have only one field, which is the most common use of
count(distinct), it is much faster to use a simpler key
compare method that can take advantage of not having to worry
about other fields
*/
Field* field = table->field[0];
switch(field->type())
{
/*
If we have a string, we must take care of charsets and case
sensitivity
*/
case FIELD_TYPE_STRING:
case FIELD_TYPE_VAR_STRING:
compare_key = (qsort_cmp2)(field->binary() ? simple_raw_key_cmp:
simple_str_key_cmp);
break;
default:
/*
Since at this point we cannot have blobs anything else can
be compared with memcmp
*/
compare_key = (qsort_cmp2)simple_raw_key_cmp;
break;
}
cmp_arg = (void*)(key_len = field->pack_length());
rec_offset = 1;
}
else // too bad, cannot cheat - there is more than one field
{
bool all_binary = 1;
Field** field, **field_end;
field_end = (field = table->field) + table->fields;
uint32 *lengths;
if (!(field_lengths=
(uint32*) thd->alloc(sizeof(uint32) * table->fields)))
return 1;
for (key_len = 0, lengths=field_lengths; field < field_end; ++field)
{
uint32 length= (*field)->pack_length();
key_len += length;
*lengths++ = length;
if (!(*field)->binary())
all_binary = 0; // Can't break loop here
}
rec_offset = table->reclength - key_len;
if (all_binary)
{
compare_key = (qsort_cmp2)simple_raw_key_cmp;
cmp_arg = (void*)key_len;
}
else
{
compare_key = (qsort_cmp2) composite_key_cmp ;
cmp_arg = (void*)this;
}
}
init_tree(&tree, min(max_heap_table_size, sortbuff_size/16), 0,
key_len, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
/*
The only time key_len could be 0 is if someone does
count(distinct) on a char(0) field - stupid thing to do,
but this has to be handled - otherwise someone can crash
the server with a DoS attack
*/
max_elements_in_tree = ((key_len) ? max_heap_table_size/key_len :
1);
}
return 0;
}
int Item_sum_count_distinct::tree_to_myisam()
{
if(create_myisam_from_heap(table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) ||
tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right))
if (create_myisam_from_heap(table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) ||
tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right))
return 1;
delete_tree(&tree);
use_tree = 0;
@ -1011,18 +1025,20 @@ bool Item_sum_count_distinct::add()
if ((*field)->is_real_null(0))
return 0; // Don't count NULL
if(use_tree)
if (use_tree)
{
/*
If the tree got too big, convert to MyISAM, otherwise insert into the
tree.
*/
if (tree.elements_in_tree > max_elements_in_tree)
{
// if the tree got too big, convert to MyISAM, otherwise
// insert into the tree
if(tree.elements_in_tree > max_elements_in_tree)
{
if(tree_to_myisam())
return 1;
}
else if(!tree_insert(&tree, table->record[0] + rec_offset, 0))
if(tree_to_myisam())
return 1;
}
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0))
return 1;
}
else if ((error=table->file->write_row(table->record[0])))
{
if (error != HA_ERR_FOUND_DUPP_KEY &&
@ -1039,7 +1055,7 @@ longlong Item_sum_count_distinct::val_int()
{
if (!table) // Empty query
return LL(0);
if(use_tree)
if (use_tree)
return tree.elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;

View File

@ -146,6 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
TABLE *table;
table_map used_table_cache;
bool fix_fields(THD *thd,TABLE_LIST *tables);
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
TREE tree;

View File

@ -250,7 +250,7 @@ void key_unpack(String *to,TABLE *table,uint idx)
bool check_if_key_used(TABLE *table, uint idx, List<Item> &fields)
{
List_iterator<Item> f(fields);
List_iterator_fast<Item> f(fields);
KEY_PART_INFO *key_part,*key_part_end;
for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
table->key_info[idx].key_parts ;

View File

@ -174,6 +174,9 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define QUERY_NO_INDEX_USED OPTION_STATUS_NO_TRANS_UPDATE*2
#define QUERY_NO_GOOD_INDEX_USED QUERY_NO_INDEX_USED*2
#define SELECT_NO_UNLOCK (QUERY_NO_GOOD_INDEX_USED*2)
#define TMP_TABLE_ALL_COLUMNS (SELECT_NO_UNLOCK*2)
#define RAID_BLOCK_SIZE 1024
/* BINLOG_DUMP options */
@ -305,8 +308,8 @@ int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
List<Item_func_match> &ftfuncs,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
uint select_type,select_result *result);
int mysql_union(THD *thd,LEX *lex, uint no);
ulong select_type,select_result *result);
int mysql_union(THD *thd,LEX *lex);
Field *create_tmp_field(TABLE *table,Item *item, Item::Type type,
Item_result_field ***copy_func, Field **from_field,
bool group,bool modify_item);
@ -422,7 +425,8 @@ bool insert_fields(THD *thd,TABLE_LIST *tables,
List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
bool set_query_id,List<Item> *sum_func_list);
bool set_query_id,List<Item> *sum_func_list,
bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(THD *thd,TABLE_LIST *tables, List<Item_func_match> &ftfuncs);
void wait_for_refresh(THD *thd);

View File

@ -32,7 +32,7 @@ static bool find_range_key(TABLE_REF *ref, Field* field,COND *cond);
int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
{
List_iterator<Item> it(all_fields);
List_iterator_fast<Item> it(all_fields);
int const_result=1;
bool recalc_const_item=0;
table_map removed_tables=0;
@ -205,7 +205,7 @@ uint count_table_entries(COND *cond,TABLE *table)
if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
return (cond->used_tables() & table->map) ? MAX_REF_PARTS+1 : 0;
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
uint count=0;
while ((item=li++))
@ -250,7 +250,7 @@ bool part_of_cond(COND *cond,Field *field)
if (((Item_cond*) cond)->functype() == Item_func::COND_OR_FUNC)
return 0; // Already checked
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
while ((item=li++))
{

View File

@ -27,5 +27,11 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/charsets/Index $(DESTDIR)$(pkgdatadir)/charsets/Index
$(INSTALL_DATA) $(srcdir)/charsets/*.conf $(DESTDIR)$(pkgdatadir)/charsets
fix_errors:
for lang in @AVAILABLE_LANGUAGES@; \
do \
../../extra/comp_err $(srcdir)/$$lang/errmsg.txt $(srcdir)/$$lang/errmsg.sys; \
done
# Don't update the files from bitkeeper
%::SCCS/s.%

View File

@ -220,6 +220,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -214,6 +214,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -215,6 +215,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -214,6 +214,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -213,6 +213,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"I lock di aggiornamento non possono essere acquisiti durante una transazione 'READ UNCOMMITTED'",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -213,6 +213,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -213,6 +213,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -213,6 +213,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -215,6 +215,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -211,6 +211,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -215,6 +215,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -214,6 +214,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -219,6 +219,9 @@
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"DROP DATABASE not allowed while thread is holding global read lock",
"CREATE DATABASE not allowed while thread is holding global read lock",
"Wrong arguments to %s",
"Error connecting to master: %-.128s",
"Error running query on master: %-.128s",
"Error when executing command %s: %-.128s",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -212,6 +212,9 @@
"Bloqueos de actualización no pueden ser adqueridos durante una transición READ UNCOMMITTED",
"DROP DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
"CREATE DATABASE no permitido mientras un thread está ejerciendo un bloqueo de lectura global",
"Wrong arguments to %s",
"Error de coneccion a master: %-128s",
"Error executando el query en master: %-128%",
"Error de %s: %-128%",
"Wrong usage of %s and %s",
"The used SELECT statements have a different number of columns",

View File

@ -205,12 +205,15 @@
"Kunde inte initializera replications-strukturerna. Kontrollera privilegerna för 'master.info'",
"Kunde inte starta en tråd för replikering",
"Användare '%-.64s' har redan 'max_user_connections' aktiva inloggningar",
"Du kan endast använda konstant-uttryck med SET",
"Lock wait timeout exceeded",
"The total number of locks exceeds the lock table size",
"Update locks cannot be acquired during a READ UNCOMMITTED transaction",
"Man kan endast använda konstant-uttryck med SET",
"Fick inte ett lås i tid",
"Antal lås överskrider antalet reserverade lås",
"Updaterings-lås kan inte göras när man använder READ UNCOMMITTED",
"DROP DATABASE är inte tillåtet när man har ett globalt läs-lås",
"CREATE DATABASE är inte tillåtet när man har ett globalt läs-lås",
"Felaktiga argument till %s",
"Fick fel vid anslutning till master: %-.128s",
"Fick fel vid utförande av command på mastern: %-.128s",
"Fick fel vid utförande av %s: %-.128s",
"Felaktig använding av %s and %s",
"SELECT kommandona har olika antal kolumner"

View File

@ -127,7 +127,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
pc->f_end = pc->f_info + field_list.elements;
pc->fields = field_list;
List_iterator<Item> it(pc->fields);
List_iterator_fast<Item> it(pc->fields);
f_info = pc->f_info;
Item *item;

View File

@ -189,7 +189,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
bool
send_fields(THD *thd,List<Item> &list,uint flag)
{
List_iterator<Item> it(list);
List_iterator_fast<Item> it(list);
Item *item;
char buff[80];
CONVERT *convert= (flag & 4) ? (CONVERT*) 0 : thd->convert_set;
@ -1738,14 +1738,15 @@ find_item_in_list(Item *find,List<Item> &items)
****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id, List<Item> *sum_func_list)
bool set_query_id, List<Item> *sum_func_list,
bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
thd->allow_sum_func= test(sum_func_list);
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
while ((item=it++))
@ -1761,7 +1762,8 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
{
if (item->fix_fields(thd,tables))
DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
}
@ -1816,7 +1818,7 @@ static key_map get_key_map_from_key_list(TABLE *table,
List<String> *index_list)
{
key_map map=0;
List_iterator<String> it(*index_list);
List_iterator_fast<String> it(*index_list);
String *name;
uint pos;
while ((name=it++))
@ -1996,7 +1998,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
int
fill_record(List<Item> &fields,List<Item> &values)
{
List_iterator<Item> f(fields),v(values);
List_iterator_fast<Item> f(fields),v(values);
Item *value;
Item_field *field;
DBUG_ENTER("fill_record");
@ -2014,7 +2016,7 @@ fill_record(List<Item> &fields,List<Item> &values)
int
fill_record(Field **ptr,List<Item> &values)
{
List_iterator<Item> v(values);
List_iterator_fast<Item> v(values);
Item *value;
DBUG_ENTER("fill_record");

View File

@ -275,7 +275,7 @@ bool select_send::send_fields(List<Item> &list,uint flag)
bool select_send::send_data(List<Item> &items)
{
List_iterator<Item> li(items);
List_iterator_fast<Item> li(items);
String *packet= &thd->packet;
DBUG_ENTER("send_data");
@ -300,12 +300,6 @@ bool select_send::send_data(List<Item> &items)
DBUG_RETURN(error);
}
void select_send::send_error(uint errcode,const char *err)
{
::send_error(&thd->net,errcode,err);
}
bool select_send::send_eof()
{
/* Unlock tables before sending packet to gain some speed */
@ -368,7 +362,7 @@ select_export::prepare(List<Item> &list)
}
/* Check if there is any blobs in data */
{
List_iterator<Item> li(list);
List_iterator_fast<Item> li(list);
Item *item;
while ((item=li++))
{
@ -415,7 +409,7 @@ bool select_export::send_data(List<Item> &items)
Item *item;
char *buff_ptr=buff;
uint used_length=0,items_left=items.elements;
List_iterator<Item> li(items);
List_iterator_fast<Item> li(items);
if (my_b_write(&cache,(byte*) exchange->line_start->ptr(),
exchange->line_start->length()))
@ -608,7 +602,7 @@ select_dump::prepare(List<Item> &list __attribute__((unused)))
bool select_dump::send_data(List<Item> &items)
{
List_iterator<Item> li(items);
List_iterator_fast<Item> li(items);
char buff[MAX_FIELD_WIDTH];
String tmp(buff,sizeof(buff)),*res;
tmp.length(0);

View File

@ -413,6 +413,8 @@ public:
class JOIN;
void send_error(NET *net,uint sql_errno=0, const char *err=0);
class select_result :public Sql_alloc {
protected:
THD *thd;
@ -423,7 +425,10 @@ public:
virtual bool send_fields(List<Item> &list,uint flag)=0;
virtual bool send_data(List<Item> &items)=0;
virtual void initialize_tables (JOIN *join=0) {}
virtual void send_error(uint errcode,const char *err)=0;
virtual void send_error(uint errcode,const char *err)
{
::send_error(&thd->net,errcode,err);
}
virtual bool send_eof()=0;
virtual void abort() {}
};
@ -434,7 +439,6 @@ public:
select_send() {}
bool send_fields(List<Item> &list,uint flag);
bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof();
};
@ -458,6 +462,7 @@ public:
bool send_eof();
};
class select_dump :public select_result {
sql_exchange *exchange;
File file;
@ -475,30 +480,31 @@ public:
void send_error(uint errcode,const char *err);
bool send_eof();
};
class select_insert :public select_result {
public:
TABLE *table;
List<Item> *fields;
uint save_time_stamp;
ulonglong last_insert_id;
COPY_INFO info;
bool unions;
uint save_time_stamp;
select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic, bool u=false)
:table(table_par),fields(fields_par), save_time_stamp(0),last_insert_id(0)
{
bzero((char*) &info,sizeof(info));
info.handle_duplicates=duplic; unions = u;
}
select_insert(TABLE *table_par,List<Item> *fields_par,enum_duplicates duplic)
:table(table_par),fields(fields_par), last_insert_id(0), save_time_stamp(0) {
bzero((char*) &info,sizeof(info));
info.handle_duplicates=duplic;
}
~select_insert();
int prepare(List<Item> &list);
bool send_fields(List<Item> &list,
uint flag) { return 0; }
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
void send_error(uint errcode,const char *err);
bool send_eof();
};
class select_create: public select_insert {
ORDER *group;
const char *db;
@ -513,8 +519,8 @@ public:
HA_CREATE_INFO *create_info_par,
List<create_field> &fields_par,
List<Key> &keys_par,
List<Item> &select_fields,enum_duplicates duplic, bool u=false)
:select_insert (NULL, &select_fields, duplic, u), db(db_name),
List<Item> &select_fields,enum_duplicates duplic)
:select_insert (NULL, &select_fields, duplic), db(db_name),
name(table_name), extra_fields(&fields_par),keys(&keys_par),
create_info(create_info_par),
lock(0)
@ -525,6 +531,22 @@ public:
void abort();
};
class select_union :public select_result {
public:
TABLE *table;
COPY_INFO info;
uint save_time_stamp;
select_union(TABLE *table_par);
~select_union();
int prepare(List<Item> &list);
bool send_fields(List<Item> &list, uint flag)
{ return 0; }
bool send_data(List<Item> &items);
bool send_eof();
bool flush();
};
/* Structs used when sorting */
typedef struct st_sort_field {

View File

@ -152,7 +152,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
MYF(0),keyinfo->key_parts);
goto err;
}
List_iterator<Item> it_ke(*key_expr);
List_iterator_fast<Item> it_ke(*key_expr);
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{

View File

@ -78,7 +78,8 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
table_list.grant=table->grant;
thd->dupp_field=0;
if (setup_tables(&table_list) || setup_fields(thd,&table_list,fields,1,0))
if (setup_tables(&table_list) ||
setup_fields(thd,&table_list,fields,1,0,0))
return -1;
if (thd->dupp_field)
{
@ -109,7 +110,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
ulonglong id;
COPY_INFO info;
TABLE *table;
List_iterator<List_item> its(values_list);
List_iterator_fast<List_item> its(values_list);
List_item *values;
char *query=thd->query;
DBUG_ENTER("mysql_insert");
@ -151,7 +152,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
save_time_stamp=table->time_stamp;
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0))
setup_tables(table_list) || setup_fields(thd,table_list,*values,0,0,0))
{
table->time_stamp=save_time_stamp;
goto abort;
@ -168,7 +169,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
table->time_stamp=save_time_stamp;
goto abort;
}
if (setup_fields(thd,table_list,*values,0,0))
if (setup_fields(thd,table_list,*values,0,0,0))
{
table->time_stamp=save_time_stamp;
goto abort;
@ -1237,14 +1238,14 @@ select_insert::prepare(List<Item> &values)
restore_record(table,2); // Get empty record
table->next_number_field=table->found_next_number_field;
thd->count_cuted_fields=1; /* calc cuted fields */
thd->count_cuted_fields=1; // calc cuted fields
thd->cuted_fields=0;
if (info.handle_duplicates != DUP_REPLACE)
table->file->extra(HA_EXTRA_WRITE_CACHE);
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->deactivate_non_unique_index((ha_rows) 0);
if (info.handle_duplicates != DUP_REPLACE)
table->file->extra(HA_EXTRA_WRITE_CACHE);
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
table->file->deactivate_non_unique_index((ha_rows) 0);
DBUG_RETURN(0);
}
@ -1319,8 +1320,7 @@ bool select_insert::send_eof()
thd->cuted_fields);
if (last_insert_id)
thd->insert_id(last_insert_id); // For update log
if (!unions)
::send_ok(&thd->net,info.copied,last_insert_id,buff);
::send_ok(&thd->net,info.copied,last_insert_id,buff);
mysql_update_log.write(thd,thd->query,thd->query_length);
if (mysql_bin_log.is_open())
{
@ -1390,6 +1390,7 @@ bool select_create::send_data(List<Item> &values)
extern HASH open_cache;
bool select_create::send_eof()
{
bool tmp=select_insert::send_eof();
@ -1403,8 +1404,7 @@ bool select_create::send_eof()
if (!table->tmp_table)
hash_delete(&open_cache,(byte*) table);
lock=0;
if (!unions)
table=0;
table=0;
VOID(pthread_mutex_unlock(&LOCK_open));
}
return tmp;
@ -1436,7 +1436,7 @@ void select_create::abort()
*****************************************************************************/
#ifdef __GNUC__
template class List_iterator<List_item>;
template class List_iterator_fast<List_item>;
template class I_List<delayed_insert>;
template class I_List_iterator<delayed_insert>;
template class I_List<delayed_row>;

View File

@ -115,7 +115,8 @@ typedef struct st_select_lex {
List<List_item> when_list;
SQL_LIST order_list,table_list,group_list;
List<Item> item_list;
List<String> interval_list,use_index, *use_index_ptr, ignore_index, *ignore_index_ptr;
List<String> interval_list,use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
List<Item_func_match> ftfunc_list;
uint in_sum_expr, sort_default;
bool create_refs;

View File

@ -20,3 +20,5 @@
#endif
#include "mysql_priv.h"
list_node end_of_list;

View File

@ -34,25 +34,40 @@ public:
/*
** basic single linked list
** Used for item and item_buffs.
** All list ends with a pointer to the 'end_of_list' element, which
** data pointer is a null pointer and the next pointer points to itself.
** This makes it very fast to traverse lists as we don't have to
** test for a specialend condition for list that can't contain a null
** pointer.
*/
class list_node :public Sql_alloc
{
public:
list_node *next;
void *info;
list_node(void *info_par,list_node *next_par)
:next(next_par),info(info_par)
{}
list_node() /* For end_of_list */
{
info=0;
next= this;
}
friend class base_list;
friend class base_list_iterator;
};
extern list_node end_of_list;
class base_list :public Sql_alloc {
protected:
class list_node :public Sql_alloc
{
public:
list_node *next;
void *info;
list_node(void *info_par,list_node *next_par) : next(next_par),info(info_par) {}
friend class base_list;
friend class base_list_iterator;
};
list_node *first,**last;
public:
uint elements;
inline void empty() { elements=0; first=0; last=&first;}
inline void empty() { elements=0; first= &end_of_list; last=&first;}
inline base_list() { empty(); }
inline base_list(const base_list &tmp) :Sql_alloc()
{
@ -62,7 +77,7 @@ public:
}
inline bool push_back(void *info)
{
if (((*last)=new list_node(info,0)))
if (((*last)=new list_node(info, &end_of_list)))
{
last= &(*last)->next;
elements++;
@ -75,7 +90,7 @@ public:
list_node *node=new list_node(info,first);
if (node)
{
if (!first)
if (last == &first)
last= &node->next;
first=node;
elements++;
@ -89,22 +104,21 @@ public:
delete *prev;
*prev=node;
if (!--elements)
{
last= &first;
first=0;
}
}
inline void *pop(void)
{
if (!first) return 0;
if (first == &end_of_list) return 0;
list_node *tmp=first;
first=first->next;
if (!--elements)
last= &first;
return tmp->info;
}
inline void *head() { return first ? first->info : 0; }
inline void **head_ref() { return first ? &first->info : 0; }
inline void *head() { return first->info; }
inline void **head_ref() { return first != &end_of_list ? &first->info : 0; }
inline bool is_empty() { return first == &end_of_list ; }
inline list_node *last_ref() { return &end_of_list; }
friend class base_list_iterator;
protected:
@ -122,7 +136,7 @@ protected:
class base_list_iterator
{
base_list *list;
base_list::list_node **el,**prev,*current;
list_node **el,**prev,*current;
public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first),
prev(0),current(0)
@ -130,16 +144,22 @@ public:
inline void *next(void)
{
prev=el;
if (!(current= *el))
return 0;
current= *el;
el= &current->next;
return current->info;
}
inline void *next_fast(void)
{
list_node *tmp;
tmp= *el;
el= &tmp->next;
return tmp->info;
}
inline void rewind(void)
{
el= &list->first;
}
void *replace(void *element)
inline void *replace(void *element)
{ // Return old element
void *tmp=current->info;
current->info=element;
@ -148,7 +168,7 @@ public:
void *replace(base_list &new_list)
{
void *ret_value=current->info;
if (new_list.first)
if (!new_list.is_empty())
{
*new_list.last=current->next;
current->info=new_list.first->info;
@ -175,7 +195,7 @@ public:
}
inline bool is_last(void)
{
return *el == 0;
return el == &list->last_ref()->next;
}
};
@ -193,7 +213,7 @@ public:
void delete_elements(void)
{
list_node *element,*next;
for (element=first; element ; element=next)
for (element=first; element != &end_of_list; element=next)
{
next=element->next;
delete (T*) element->info;
@ -208,13 +228,25 @@ template <class T> class List_iterator :public base_list_iterator
public:
List_iterator(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next(); }
inline void rewind(void) { base_list_iterator::rewind(); }
inline T *replace(T *a) { return (T*) base_list_iterator::replace(a); }
inline T *replace(List<T> &a) { return (T*) base_list_iterator::replace(a); }
inline void remove(void) { base_list_iterator::remove(); }
inline void after(T *a) { base_list_iterator::after(a); }
inline T** ref(void) { return (T**) base_list_iterator::ref(); }
inline bool is_last(void) { return base_list_iterator::is_last(); }
};
template <class T> class List_iterator_fast :public base_list_iterator
{
protected:
inline T *replace(T *a) { return (T*) 0; }
inline T *replace(List<T> &a) { return (T*) 0; }
inline void remove(void) { }
inline void after(T *a) { }
inline T** ref(void) { return (T**) 0; }
public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); }
};

View File

@ -105,7 +105,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{ // Part field list
thd->dupp_field=0;
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0))
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0))
DBUG_RETURN(-1);
if (thd->dupp_field)
{
@ -116,7 +116,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
uint tot_length=0;
bool use_blobs=0,use_timestamp=0;
List_iterator<Item> it(fields);
List_iterator_fast<Item> it(fields);
Item_field *field;
while ((field=(Item_field*) it++))
@ -313,7 +313,7 @@ static int
read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
READ_INFO &read_info)
{
List_iterator<Item> it(fields);
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
DBUG_ENTER("read_fixed_length");
@ -376,7 +376,7 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List<Item> &fields, READ_INFO &read_info,
String &enclosed)
{
List_iterator<Item> it(fields);
List_iterator_fast<Item> it(fields);
Item_field *sql_field;
uint enclosed_length;
DBUG_ENTER("read_sep_field");

View File

@ -47,7 +47,8 @@ static void mysql_init_query(THD *thd);
static void remove_escape(char *name);
static void refresh_status(void);
static bool append_file_to_dir(char **filename_ptr, char *table_name);
static int link_in_large_list_and_check_acl(THD *thd,LEX *lex,SQL_LIST *tables);
static int create_total_list_and_check_acl(THD *thd, LEX *lex,
TABLE_LIST **result);
const char *any_db="*any*"; // Special symbol for check_access
@ -1737,10 +1738,10 @@ mysql_execute_command(void)
}
case SQLCOM_UNION_SELECT:
{
SQL_LIST *total=(SQL_LIST *) thd->calloc(sizeof(SQL_LIST));
TABLE_LIST *total;
if (select_lex->options & SELECT_DESCRIBE)
lex->exchange=0;
if ((res = link_in_large_list_and_check_acl(thd,lex,total)) == -1)
if ((res = create_total_list_and_check_acl(thd,lex,&total)) == -1)
{
res=0;
break;
@ -1753,31 +1754,31 @@ mysql_execute_command(void)
res=0;
break;
}
if (!(res=open_and_lock_tables(thd,(TABLE_LIST *)total->first)))
{
/* Fix tables--to-be-unioned-from list to point at opened tables */
for (SELECT_LEX *sl=&lex->select_lex;sl;sl=sl->next)
{
for (TABLE_LIST *cursor=(TABLE_LIST *)sl->table_list.first;cursor;cursor=cursor->next)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
ha_rows save_it=thd->offset_limit; thd->offset_limit=0;
res=mysql_union(thd,lex, select_lex->select_number+1);
thd->offset_limit=save_it;
}
if (!(res=open_and_lock_tables(thd, total)))
{
/* Fix tables--to-be-unioned-from list to point at opened tables */
for (SELECT_LEX *sl=&lex->select_lex; sl; sl=sl->next)
{
for (TABLE_LIST *cursor= (TABLE_LIST *)sl->table_list.first;
cursor;
cursor=cursor->next)
cursor->table= ((TABLE_LIST*) cursor->table)->table;
}
res=mysql_union(thd,lex);
}
close_thread_tables(thd);
break;
}
case SQLCOM_DROP_TABLE:
{
if (check_table_access(thd,DROP_ACL,tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
res= -1;
else
res = mysql_rm_table(thd,tables,lex->drop_if_exists);
}
break;
{
if (check_table_access(thd,DROP_ACL,tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
res= -1;
else
res = mysql_rm_table(thd,tables,lex->drop_if_exists);
}
break;
case SQLCOM_DROP_INDEX:
if (!tables->db)
tables->db=thd->db;
@ -2901,53 +2902,66 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
DBUG_RETURN(ptr);
}
static int link_in_large_list_and_check_acl(THD *thd,LEX *lex,SQL_LIST *tables)
/*
** This is used for UNION to create a new table list of all used tables
** The table_list->table entry in all used tables are set to point
** to the entries in this list.
*/
static int create_total_list_and_check_acl(THD *thd, LEX *lex,
TABLE_LIST **result)
{
SELECT_LEX *sl; const char *current_db=thd->db ? thd->db : "";
TABLE_LIST *ptr;
for (sl=&lex->select_lex;sl;sl=sl->next)
SELECT_LEX *sl;
TABLE_LIST **new_table_list= result, *aux;
const char *current_db=thd->db ? thd->db : ""; // QQ; To be removed
*new_table_list=0; // end result list
for (sl=&lex->select_lex; sl; sl=sl->next)
{
if ((lex->sql_command == SQLCOM_UNION_SELECT) && (sl->order_list.first != (byte *)NULL) && (sl->next != (st_select_lex *)NULL))
if ((lex->sql_command == SQLCOM_UNION_SELECT) &&
sl->order_list.first && sl->next)
{
net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); // correct error message will come here; only last SELECT can have ORDER BY
net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY");
return -1;
}
if (sl->table_list.first == (byte *)NULL) continue;
TABLE_LIST *cursor,*aux=(TABLE_LIST*) sl->table_list.first;
aux= (TABLE_LIST*) sl->table_list.first;
if (aux)
{
if (check_table_access(thd, lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL , aux))
return -1;
for (;aux;aux=aux->next)
TABLE_LIST *next;
if (check_table_access(thd,
lex->exchange ?
SELECT_ACL | FILE_ACL : SELECT_ACL , aux))
return -1;
for (; aux; aux=next)
{
if (!aux->db)
aux->db=(char *)current_db;
for (cursor=(TABLE_LIST *)tables->first;cursor;cursor=cursor->next)
if (!strcmp(cursor->db,aux->db) && (!strcmp(cursor->real_name,aux->real_name)))
break;
if (!cursor || !tables->first)
{
aux->lock_type= lex->lock_option;
if (!tables->next)
tables->next= (byte**) &tables->first;
if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
return 1;
ptr->db= aux->db; ptr->real_name=aux->real_name;
ptr->name=aux->name; ptr->lock_type=aux->lock_type;
ptr->updating=aux->updating;
ptr->use_index=aux->use_index;
ptr->ignore_index=aux->use_index;
aux->table=(TABLE *)ptr;
link_in_list(tables,(byte*)ptr,(byte**) &ptr->next);
}
else
aux->table=(TABLE *)cursor;
TABLE_LIST *cursor;
next= aux->next;
if (!aux->db)
aux->db=(char *)current_db; // QQ; To be removed
for (cursor= *result; cursor; cursor=cursor->next)
if (!strcmp(cursor->db,aux->db) &&
(!strcmp(cursor->real_name,aux->real_name)))
break;
if (!cursor)
{
/* Add not used table to the total table list */
aux->lock_type= lex->lock_option;
if (!(cursor = (TABLE_LIST *) thd->memdup((byte*) aux,
sizeof(*aux))))
return 1;
*new_table_list= cursor;
new_table_list= &cursor->next;
*new_table_list=0; // end result list
}
aux->table=(TABLE *) cursor;
}
}
}
return (tables->first) ? 0 : 1;
return 0;
}
void add_join_on(TABLE_LIST *b,Item *expr)
{
if (!b->on_expr)

View File

@ -152,7 +152,7 @@ int
mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
List<Item_func_match> &ftfuncs,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
uint select_options,select_result *result)
ulong select_options,select_result *result)
{
TABLE *tmp_table;
int error,tmp;
@ -178,7 +178,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
thd->used_tables=0; // Updated by setup_fields
if (setup_tables(tables) ||
setup_fields(thd,tables,fields,1,&all_fields) ||
setup_fields(thd,tables,fields,1,&all_fields,1) ||
setup_conds(thd,tables,&conds) ||
setup_order(thd,tables,fields,all_fields,order) ||
setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields))
@ -207,7 +207,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
if (!group)
{
uint flag=0;
List_iterator<Item> it(fields);
List_iterator_fast<Item> it(fields);
Item *item;
while ((item= it++))
{
@ -373,7 +373,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error=(int) result->send_eof();
}
delete procedure;
DBUG_RETURN(0);
DBUG_RETURN(error);
}
error = -1;
@ -403,7 +403,8 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
error= 1; /* purecov: inspected */
goto err; /* purecov: inspected */
}
if (join.const_tables && !thd->locked_tables)
if (join.const_tables && !thd->locked_tables &&
!(select_options & SELECT_NO_UNLOCK))
{
TABLE **table, **end;
for (table=join.table, end=table + join.const_tables ;
@ -571,7 +572,7 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
/* Perform FULLTEXT search before all regular searches */
if (ftfuncs.elements)
{
List_iterator<Item_func_match> li(ftfuncs);
List_iterator_fast<Item_func_match> li(ftfuncs);
Item_func_match *ifm;
DBUG_PRINT("info",("Performing FULLTEXT search"));
thd->proc_info="FULLTEXT searching";
@ -1268,7 +1269,7 @@ add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
{
if (cond->type() == Item_func::COND_ITEM)
{
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
KEY_FIELD *org_key_fields= *key_fields;
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
@ -1433,7 +1434,7 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
}
else if (cond->type() == Item::COND_ITEM)
{
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
{
@ -2241,9 +2242,9 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join->tables=1;
join->const_tables=0;
join->const_table_map=0;
join->tmp_table_param.copy_field_count=join->tmp_table_param.field_count=
join->tmp_table_param.sum_func_count= join->tmp_table_param.func_count=0;
join->tmp_table_param.copy_field=0;
join->tmp_table_param.field_count= join->tmp_table_param.sum_func_count=
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;
@ -2591,7 +2592,8 @@ join_free(JOIN *join)
}
// We are not using tables anymore
// Unlock all tables. We may be in an INSERT .... SELECT statement.
if (join->lock && join->thd->lock)
if (join->lock && join->thd->lock &&
!(join->select_options & SELECT_NO_UNLOCK))
{
mysql_unlock_read_tables(join->thd, join->lock);// Don't free join->lock
join->lock=0;
@ -2949,7 +2951,7 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level,
{
bool and_level= ((Item_cond*) cond)->functype() ==
Item_func::COND_AND_FUNC;
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
I_List<COND_CMP> save;
while ((item=li++))
@ -3176,7 +3178,7 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
{
bool and_level= (((Item_cond*) cond)->functype()
== Item_func::COND_AND_FUNC);
List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *item;
while ((item=li++))
{
@ -3348,6 +3350,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
hidden_null_count, hidden_null_pack_length, hidden_field_count,
blob_count,group_null_items;
bool using_unique_constraint=0;
bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
char *tmpname,path[FN_REFLEN];
byte *pos,*group_buff;
uchar *null_flags;
@ -3438,24 +3441,27 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
param->using_indirect_summary_function=0;
List_iterator<Item> li(fields);
List_iterator_fast<Item> li(fields);
Item *item;
Field **tmp_from_field=from_field;
while ((item=li++))
{
Item::Type type=item->type();
if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
if (not_all_columns)
{
/*
Mark that the we have ignored an item that refers to a summary
function. We need to know this if someone is going to use
DISTINCT on the result.
*/
param->using_indirect_summary_function=1;
continue;
if (item->with_sum_func && type != Item::SUM_FUNC_ITEM)
{
/*
Mark that the we have ignored an item that refers to a summary
function. We need to know this if someone is going to use
DISTINCT on the result.
*/
param->using_indirect_summary_function=1;
continue;
}
if (item->const_item()) // We don't have to store this
continue;
}
if (item->const_item()) // We don't have to store this
continue;
if (type == Item::SUM_FUNC_ITEM && !group && !save_sum_fields)
{ /* Can't calc group yet */
((Item_sum*) item)->result_field=0;
@ -3466,7 +3472,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
Field *new_field=
create_tmp_field(table,arg,arg->type(),&copy_func,tmp_from_field,
group != 0,1);
group != 0,not_all_columns);
if (!new_field)
goto err; // Should be OOM
tmp_from_field++;
@ -3483,7 +3489,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
else
{
Field *new_field=create_tmp_field(table,item,type,&copy_func,
tmp_from_field, group != 0,1);
tmp_from_field, group != 0,
not_all_columns);
if (!new_field)
{
if (thd->fatal_error)
@ -3620,7 +3627,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
null_count=(null_count+7) & ~7; // move to next byte
}
param->copy_field_count=(uint) (copy - param->copy_field);
param->copy_field_end=copy;
param->recinfo=recinfo;
store_record(table,2); // Make empty default record
@ -6414,7 +6421,7 @@ setup_copy_fields(TMP_TABLE_PARAM *param,List<Item> &fields)
goto err;
}
}
param->copy_field_count= (uint) (copy - param->copy_field);
param->copy_field_end= copy;
DBUG_RETURN(0);
err:
@ -6432,17 +6439,16 @@ void
copy_fields(TMP_TABLE_PARAM *param)
{
Copy_field *ptr=param->copy_field;
Copy_field *end=ptr+param->copy_field_count;
Copy_field *end=param->copy_field_end;
for ( ; ptr != end; ptr++)
(*ptr->do_copy)(ptr);
List_iterator<Item> it(param->copy_funcs);
List_iterator_fast<Item> &it=param->copy_funcs_it;
it.rewind();
Item_copy_string *item;
while ((item = (Item_copy_string*) it++))
{
item->copy();
}
}

View File

@ -118,19 +118,21 @@ typedef struct st_position { /* Used in find_best */
class TMP_TABLE_PARAM {
public:
List<Item> copy_funcs;
Copy_field *copy_field;
List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end;
byte *group_buff;
Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo;
KEY *keyinfo;
ha_rows end_write_records;
uint copy_field_count,field_count,sum_func_count,func_count;
uint field_count,sum_func_count,func_count;
uint hidden_field_count;
uint group_parts,group_length;
uint quick_group;
bool using_indirect_summary_function;
TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0)
TMP_TABLE_PARAM()
:copy_funcs_it(copy_funcs), copy_field(0), group_parts(0), group_length(0)
{}
~TMP_TABLE_PARAM()
{

View File

@ -72,7 +72,7 @@ mysqld_show_dbs(THD *thd,const char *wild)
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
DBUG_RETURN(1);
List_iterator<char> it(files);
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
if (!opt_safe_show_db || thd->master_access ||
@ -154,7 +154,7 @@ int mysqld_show_tables(THD *thd,const char *db,const char *wild)
DBUG_RETURN(1);
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
List_iterator<char> it(files);
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
thd->packet.length(0);
@ -284,7 +284,7 @@ int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
if (mysql_find_files(thd,&files,db,path,wild,0))
DBUG_RETURN(-1);
List_iterator<char> it(files);
List_iterator_fast<char> it(files);
while ((file_name=it++))
{
TABLE_LIST table_list;
@ -1165,6 +1165,6 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables)
}
#ifdef __GNUC__
template class List_iterator<char>;
template class List_iterator_fast<char>;
template class List<char>;
#endif

View File

@ -669,7 +669,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
DBUG_ENTER("create_table_from_items");
/* Add selected items to field list */
List_iterator<Item> it(*items);
List_iterator_fast<Item> it(*items);
Item *item;
Field *tmp_field;
tmp_table.db_create_options=0;

217
sql/sql_union.cc Normal file
View File

@ -0,0 +1,217 @@
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
UNION of select's
UNION's were introduced by Monty and Sinisa <sinisa@mysql.com>
*/
#include "mysql_priv.h"
#include "sql_select.h"
int mysql_union(THD *thd, LEX *lex)
{
SELECT_LEX *sl, *last_sl;
ORDER *order;
List<Item> item_list;
/* TABLE_LIST *s=(TABLE_LIST*) lex->select_lex.table_list.first; */
TABLE *table;
TABLE_LIST *first_table, result_table_list;
TMP_TABLE_PARAM tmp_table_param;
select_result *result;
select_union *union_result;
int res;
uint elements;
DBUG_ENTER("mysql_union");
/* Find last select part as it's here ORDER BY and GROUP BY is stored */
elements= lex->select_lex.item_list.elements;
for (last_sl= &lex->select_lex;
last_sl->next;
last_sl=last_sl->next)
{
if (elements != last_sl->next->item_list.elements)
{
my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,MYF(0));
return -1;
}
}
order = (ORDER *) last_sl->order_list.first;
{
Item *item;
List_iterator<Item> it(lex->select_lex.item_list);
/* Create a list of items that will be in the result set */
first_table= (TABLE_LIST*) lex->select_lex.table_list.first;
while ((item= it++))
if (item_list.push_back(item))
DBUG_RETURN(-1);
if (setup_fields(thd,first_table,item_list,0,0,1))
DBUG_RETURN(-1);
}
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !lex->union_option,
1, 0,
(lex->select_lex.options | thd->options |
TMP_TABLE_ALL_COLUMNS))))
DBUG_RETURN(-1);
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list,sizeof(result_table_list));
result_table_list.db= (char*) "";
result_table_list.real_name=result_table_list.name=(char*) "union";
result_table_list.table=table;
if (!(union_result=new select_union(table)))
{
res= -1;
goto exit;
}
for (sl= &lex->select_lex; sl; sl=sl->next)
{
thd->offset_limit=sl->offset_limit;
thd->select_limit=sl->select_limit+sl->offset_limit;
if (thd->select_limit < sl->select_limit)
thd->select_limit= HA_POS_ERROR; // no limit
if (thd->select_limit == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS;
res=mysql_select(thd,(TABLE_LIST*) sl->table_list.first,
sl->item_list,
sl->where,
sl->ftfunc_list,
(ORDER*) 0,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
union_result);
if (res)
goto exit;
}
if (union_result->flush())
{
res= 1; // Error is already sent
goto exit;
}
delete union_result;
/*
Sinisa, we must also be able to handle
CREATE TABLE ... and INSERT ... SELECT with unions
To do this, it's probably best that we add a new handle_select() function
which takes 'select_result' as parameter and let this internally handle
SELECT with and without unions.
*/
if (lex->exchange)
{
if (lex->exchange->dumpfile)
result=new select_dump(lex->exchange);
else
result=new select_export(lex->exchange);
}
else
result=new select_send();
res =-1;
if (result)
{
/* Create a list of fields in the temporary table */
List_iterator<Item> it(item_list);
Field **field;
List<Item_func_match> ftfunc_list;
ftfunc_list.empty();
for (field=table->field ; *field ; field++)
{
(void) it++;
(void) it.replace(new Item_field(*field));
}
if (!thd->fatal_error) // Check if EOM
res=mysql_select(thd,&result_table_list,
item_list, NULL, ftfunc_list, order,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result);
if (res)
result->abort();
delete result;
}
exit:
free_tmp_table(thd,table);
DBUG_RETURN(res);
}
/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/
select_union::select_union(TABLE *table_par)
:table(table_par)
{
bzero((char*) &info,sizeof(info));
/*
We can always use DUP_IGNORE because the temporary table will only
contain a unique key if we are using not using UNION ALL
*/
info.handle_duplicates=DUP_IGNORE;
}
select_union::~select_union()
{
}
int select_union::prepare(List<Item> &list)
{
return 0;
}
bool select_union::send_data(List<Item> &values)
{
if (thd->offset_limit)
{ // using limit offset,count
thd->offset_limit--;
return 0;
}
fill_record(table->field,values);
return write_record(table,&info) ? 1 : 0;
}
bool select_union::send_eof()
{
return 0;
}
bool select_union::flush()
{
int error,error2;
error=table->file->extra(HA_EXTRA_NO_CACHE);
if (error)
{
table->file->print_error(error,MYF(0));
::send_error(&thd->net);
return 1;
}
return 0;
}

View File

@ -1,110 +0,0 @@
/* Copyright (C) 2000 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* UNION of select's */
/* UNION's were introduced by Monty and Sinisa <sinisa@mysql.com> */
#include "mysql_priv.h"
#include "sql_select.h"
/* Union of selects */
int mysql_union(THD *thd,LEX *lex,uint no_of_selects)
{
SELECT_LEX *sl, *for_order=&lex->select_lex; int res=0;
TABLE *table=(TABLE *)NULL; TABLE_LIST *resulting=(TABLE_LIST *)NULL;
for (;for_order->next;for_order=for_order->next);
ORDER *some_order = (ORDER *)for_order->order_list.first;
List<Item> list;
List_iterator<Item> it(lex->select_lex.item_list);
Item *item;
TABLE_LIST *s=(TABLE_LIST*) lex->select_lex.table_list.first;
while ((item= it++))
if (list.push_back(item))
return -1;
if (setup_fields(thd,s,list,0,0))
return -1;
TMP_TABLE_PARAM *tmp_table_param= new TMP_TABLE_PARAM;
count_field_types(tmp_table_param,list,0);
tmp_table_param->end_write_records= HA_POS_ERROR; tmp_table_param->copy_field=0;
tmp_table_param->copy_field_count=tmp_table_param->field_count=
tmp_table_param->sum_func_count= tmp_table_param->func_count=0;
if (!(table=create_tmp_table(thd, tmp_table_param, list, (ORDER*) 0, !lex->union_option,
0, 0, lex->select_lex.options | thd->options)))
return 1;
if (!(resulting = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))))
return 1;
resulting->db=s->db ? s->db : thd->db;
resulting->real_name=table->real_name;
resulting->name=table->table_name;
resulting->table=table;
for (sl=&lex->select_lex;sl;sl=sl->next)
{
TABLE_LIST *tables=(TABLE_LIST*) sl->table_list.first;
select_insert *result;
if ((result=new select_insert(table,&list, DUP_IGNORE, true)))
{
res=mysql_select(thd,tables,sl->item_list,
sl->where,
sl->ftfunc_list,
(ORDER*) some_order,
(ORDER*) sl->group_list.first,
sl->having,
(ORDER*) NULL,
sl->options | thd->options,
result);
delete result;
if (res)
return res;
}
else
return -1;
}
select_result *result;
List<Item_func_match> ftfunc_list;
ftfunc_list.empty();
if (lex->exchange)
{
if (lex->exchange->dumpfile)
result=new select_dump(lex->exchange);
else
result=new select_export(lex->exchange);
}
else result=new select_send();
if (result)
{
res=mysql_select(thd,resulting,list,
NULL,
ftfunc_list,
(ORDER*) NULL,
(ORDER*) NULL,
NULL,
(ORDER*) NULL,
thd->options,
result);
if (res)
result->abort();
delete result;
}
else
res=-1;
return res;
}

View File

@ -90,7 +90,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege;
if (setup_fields(thd,table_list,fields,1,0))
if (setup_fields(thd,table_list,fields,1,0,0))
DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field)
{
@ -103,7 +103,7 @@ int mysql_update(THD *thd,
/* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_fields(thd,table_list,values,0,0))
if (setup_fields(thd,table_list,values,0,0,0))
{
table->time_stamp=save_time_stamp; // Restore timestamp pointer
DBUG_RETURN(-1); /* purecov: inspected */

View File

@ -1319,7 +1319,7 @@ select:
SELECT_SYM
{
LEX *lex=Lex;
if (lex->sql_command!=SQLCOM_UNION_SELECT) lex->sql_command= SQLCOM_SELECT;
lex->sql_command= SQLCOM_SELECT;
lex->lock_option=TL_READ;
mysql_init_select(lex);
}
@ -3281,7 +3281,7 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
@ -3293,7 +3293,7 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
@ -3305,7 +3305,7 @@ opt_table:
lex->grant = GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
net_printf(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
send_error(&lex->thd->net,ER_ILLEGAL_GRANT_FOR_TABLE);
YYABORT;
}
}
@ -3407,11 +3407,20 @@ union_list:
UNION_SYM union_option
{
LEX *lex=Lex;
if (lex->exchange) YYABORT; /* Only the last SELECT can have INTO...... */
lex->sql_command=SQLCOM_UNION_SELECT;
mysql_new_select(lex); lex->select->linkage=UNION_TYPE;
if (lex->exchange)
{
/* Only the last SELECT can have INTO...... */
net_printf(&current_thd->net, ER_WRONG_USAGE,"UNION","INTO");
YYABORT;
}
mysql_new_select(lex);
lex->select->linkage=UNION_TYPE;
}
select
select
{
Lex->sql_command=SQLCOM_UNION_SELECT;
}
union_option:
/* empty */ {}