summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <sasha@mysql.sashanet.com>2001-08-03 16:09:36 -0600
committerunknown <sasha@mysql.sashanet.com>2001-08-03 16:09:36 -0600
commit8d89555e4602d817b6ebc449635cca47e3380b90 (patch)
tree97ccb13c4b0a44d464a0cca69c725323df8422b9 /sql
parent0dab9f40e1c52ac00e1ca291785ae7943dea577e (diff)
parenta8f2c247ec2a915985596ef74a3804f624cdd5d3 (diff)
downloadmariadb-git-8d89555e4602d817b6ebc449635cca47e3380b90.tar.gz
Merge work:/home/bk/mysql-4.0
into mysql.sashanet.com:/home/sasha/src/bk/mysql-4.0 sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_load.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am2
-rw-r--r--sql/item.cc1
-rw-r--r--sql/item_cmpfunc.cc8
-rw-r--r--sql/item_func.cc4
-rw-r--r--sql/item_sum.cc258
-rw-r--r--sql/item_sum.h1
-rw-r--r--sql/key.cc2
-rw-r--r--sql/mysql_priv.h10
-rw-r--r--sql/opt_sum.cc6
-rw-r--r--sql/share/Makefile.am6
-rw-r--r--sql/share/czech/errmsg.txt3
-rw-r--r--sql/share/danish/errmsg.txt3
-rw-r--r--sql/share/dutch/errmsg.txt3
-rw-r--r--sql/share/english/errmsg.txt3
-rw-r--r--sql/share/estonian/errmsg.txt3
-rw-r--r--sql/share/french/errmsg.txt3
-rw-r--r--sql/share/german/errmsg.txt3
-rw-r--r--sql/share/greek/errmsg.txt3
-rw-r--r--sql/share/hungarian/errmsg.txt3
-rw-r--r--sql/share/italian/errmsg.txt3
-rw-r--r--sql/share/japanese/errmsg.txt3
-rw-r--r--sql/share/korean/errmsg.txt3
-rw-r--r--sql/share/norwegian-ny/errmsg.txt3
-rw-r--r--sql/share/norwegian/errmsg.txt3
-rw-r--r--sql/share/polish/errmsg.txt3
-rw-r--r--sql/share/portuguese/errmsg.txt3
-rw-r--r--sql/share/romanian/errmsg.txt3
-rw-r--r--sql/share/russian/errmsg.txt3
-rw-r--r--sql/share/slovak/errmsg.txt3
-rw-r--r--sql/share/spanish/errmsg.txt3
-rw-r--r--sql/share/swedish/errmsg.txt11
-rw-r--r--sql/sql_analyse.cc2
-rw-r--r--sql/sql_base.cc16
-rw-r--r--sql/sql_class.cc14
-rw-r--r--sql/sql_class.h50
-rw-r--r--sql/sql_handler.cc2
-rw-r--r--sql/sql_insert.cc32
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_list.cc2
-rw-r--r--sql/sql_list.h88
-rw-r--r--sql/sql_load.cc8
-rw-r--r--sql/sql_parse.cc130
-rw-r--r--sql/sql_select.cc72
-rw-r--r--sql/sql_select.h8
-rw-r--r--sql/sql_show.cc8
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/sql_union.cc217
-rw-r--r--sql/sql_unions.cc110
-rw-r--r--sql/sql_update.cc4
-rw-r--r--sql/sql_yacc.yy25
50 files changed, 722 insertions, 440 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 70415be03a4..02ac8aa6cc7 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -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 \
diff --git a/sql/item.cc b/sql/item.cc
index 44bbf9a9cbc..c0cdac51b1e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 373aede7b6b..b18237ca4cf 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -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++))
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e540f850063..b76bee78b2e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 8d025891877..c79e909658c 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -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;
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 753a9de8b48..5500afa43ca 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -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;
diff --git a/sql/key.cc b/sql/key.cc
index 80a33bc45d3..2c7c9361eb3 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -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 ;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 676118c1fbe..d02a2eb729e 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index df49d52d54a..c16c0d919d4 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -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++))
{
diff --git a/sql/share/Makefile.am b/sql/share/Makefile.am
index 6bc05aa33cd..cb3056b5f5a 100644
--- a/sql/share/Makefile.am
+++ b/sql/share/Makefile.am
@@ -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.%
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index 8fb28bb5aa7..d4b09dcd981 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -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",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index aa5ce318779..59dfa0b0f32 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -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",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 5aebadb910a..67f95100527 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -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",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index 975227538c5..8704a3839ac 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -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",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 33c061e1eeb..584bae5c78d 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -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",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index bbdfbf8e1b5..31c08d97b1d 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -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",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index d12dc7caedc..df4dce129c0 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -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",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index b86e34e8cc4..bfe8ecdfe53 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -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",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index 80cc9da65f0..c44b9a28c42 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -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",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index 08c91323c97..732573c3f6c 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -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",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index ffea1e1ceee..b4d0d551bcf 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -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",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index 5359ed17c69..60a3e28185b 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -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",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index cf4d0de9200..9f64e8b9e49 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -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",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 22d4e4b52bd..64806f4bd1c 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -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",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 31627a41d5c..34a4231b3a9 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -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",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 8542b661698..4a755004e0e 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -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",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index ed211d3694b..2877139aa02 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -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",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index 7965ba0b789..abeadcf5f57 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -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",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index 9504f817d1c..39435961e51 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -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",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 47565ab7358..67e7304812e 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -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",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 9e866bc510a..d74685736dc 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -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"
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 3cc53f1ef49..161e0f9b2e7 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -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;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index ea3d77c5158..31cadf6f778 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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");
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5e0c02c5d07..d0ff5d962db 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -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);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index b22404b5b17..3b7fced9bc5 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -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 {
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index a605984aef7..98cc523dc9b 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -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++)
{
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5ac55ca6eac..c21e7668a02 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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>;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 627c1a23de3..dadabe999c4 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -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;
diff --git a/sql/sql_list.cc b/sql/sql_list.cc
index 7d5fc442121..be630dfc038 100644
--- a/sql/sql_list.cc
+++ b/sql/sql_list.cc
@@ -20,3 +20,5 @@
#endif
#include "mysql_priv.h"
+
+list_node end_of_list;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index b86250f70b6..1486502148f 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -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(); }
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 999aec9b15e..5b02586a24c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -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");
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 6078d3ce22a..6c3205c2feb 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -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)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index eff200e9bdf..cd6caf213f8 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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();
- }
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 0ec1854d641..4fcffae31d2 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -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()
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 34e8985007e..2bd6e383eac 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e91a9a83e73..8dbb9710cda 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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;
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
new file mode 100644
index 00000000000..a06c8f87cf0
--- /dev/null
+++ b/sql/sql_union.cc
@@ -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;
+}
diff --git a/sql/sql_unions.cc b/sql/sql_unions.cc
deleted file mode 100644
index b480415619b..00000000000
--- a/sql/sql_unions.cc
+++ /dev/null
@@ -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;
-}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 609c2642bc6..113995b169c 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -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 */
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e9c5990fe14..c6ae2241603 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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 */ {}