diff options
author | unknown <monty@hundin.mysql.fi> | 2001-08-14 20:33:49 +0300 |
---|---|---|
committer | unknown <monty@hundin.mysql.fi> | 2001-08-14 20:33:49 +0300 |
commit | 410dd0779c32b1975eceeab92a1e62ff099f37db (patch) | |
tree | 63b1bcf87d376e768395f4a058416187ee0aad95 | |
parent | 97250b9c40a378659c6c4423461021231a3b551d (diff) | |
download | mariadb-git-410dd0779c32b1975eceeab92a1e62ff099f37db.tar.gz |
Remove warnings and portability fixes
New global read lock code
Fixed bug in DATETIME with WHERE optimization
Made UNION code more general.
include/global.h:
Remove warning on Linux Alpha
include/mysql_com.h:
Move some C variables inside extern "C" block.
include/mysqld_error.h:
New error mesages
myisam/mi_write.c:
cleanup
mysql-test/r/select.result:
Fix because of table lists now always has a database argument.
mysql-test/r/type_datetime.result:
Test for bug with datetime and where optimization
mysql-test/r/union.result:
Updated result
mysql-test/t/type_datetime.test:
New test for datetime
mysql-test/t/union.test:
More testing of error conditions
sql/item_sum.cc:
Remove warnings on Linux Alpha
sql/item_sum.h:
Cleanup
sql/lock.cc:
Cleaned up global lock handling
sql/log_event.cc:
Removed default arguments from declarations (not allowed in cxx)
sql/mysql_priv.h:
New prototypes
sql/mysqld.cc:
Fix for global locks
sql/opt_range.cc:
Cleanup
sql/share/czech/errmsg.txt:
New errors
sql/share/danish/errmsg.txt:
New errors
sql/share/dutch/errmsg.txt:
New errors
sql/share/english/errmsg.txt:
New errors
sql/share/estonian/errmsg.txt:
New errors
sql/share/french/errmsg.txt:
New errors
sql/share/german/errmsg.txt:
New errors
sql/share/greek/errmsg.txt:
New errors
sql/share/hungarian/errmsg.txt:
New errors
sql/share/italian/errmsg.txt:
New errors
sql/share/japanese/errmsg.txt:
New errors
sql/share/korean/errmsg.txt:
New errors
sql/share/norwegian-ny/errmsg.txt:
New errors
sql/share/norwegian/errmsg.txt:
New errors
sql/share/polish/errmsg.txt:
New errors
sql/share/portuguese/errmsg.txt:
New errors
sql/share/romanian/errmsg.txt:
New errors
sql/share/russian/errmsg.txt:
New errors
sql/share/slovak/errmsg.txt:
New errors
sql/share/spanish/errmsg.txt:
New errors
sql/share/swedish/errmsg.OLD:
New errors
sql/share/swedish/errmsg.txt:
New errors
sql/sql_acl.cc:
Use thd->host_or_ip
sql/sql_class.cc:
Use new global lock code
sql/sql_class.h:
host_or_ip
sql/sql_db.cc:
host_or_ip
sql/sql_delete.cc:
Use now global lock code
sql/sql_lex.h:
Cleanup of not used states and variables
sql/sql_parse.cc:
Use now global locks.
Made UNION code more general.
Change to use thd->hosts_or_ip.
TABLE_LIST now always has 'db' set.
sql/sql_repl.cc:
Portability fixes.
Changed wrong usage of my_vsnprintf -> my_snprintf
sql/sql_select.cc:
Changes for UNION
sql/sql_show.cc:
Cleanup
sql/sql_union.cc:
Handle 'select_result' outside of mysql_union().
sql/sql_yacc.yy:
Fixes for union
50 files changed, 543 insertions, 549 deletions
diff --git a/include/global.h b/include/global.h index c7a3498b76a..d40c5373812 100644 --- a/include/global.h +++ b/include/global.h @@ -781,9 +781,9 @@ typedef union { *((uchar*) (T))= (uchar)(def_temp); \ *((uchar*) (T+1))=(uchar)((def_temp >> 8)); } #define int3store(T,A) { /*lint -save -e734 */\ - *((T))=(char) ((A));\ - *((T)+1)=(char) (((A) >> 8));\ - *((T)+2)=(char) (((A) >> 16)); \ + *((uchar*)(T))=(uchar) ((A));\ + *((uchar*) (T)+1)=(uchar) (((A) >> 8));\ + *((uchar*)(T)+2)=(uchar) (((A) >> 16)); \ /*lint -restore */} #define int4store(T,A) { *(T)=(char) ((A));\ *((T)+1)=(char) (((A) >> 8));\ diff --git a/include/mysql_com.h b/include/mysql_com.h index 2d1c5017922..126bb454501 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -146,15 +146,15 @@ enum enum_field_types { FIELD_TYPE_DECIMAL, FIELD_TYPE_TINY, #define FIELD_TYPE_CHAR FIELD_TYPE_TINY /* For compability */ #define FIELD_TYPE_INTERVAL FIELD_TYPE_ENUM /* For compability */ -extern unsigned long max_allowed_packet; -extern unsigned long net_buffer_length; - #define net_new_transaction(net) ((net)->pkt_nr=0) #ifdef __cplusplus extern "C" { #endif +extern unsigned long max_allowed_packet; +extern unsigned long net_buffer_length; + int my_net_init(NET *net, Vio* vio); void net_end(NET *net); void net_clear(NET *net); diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 22fbbeb0367..ab37065b761 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -217,4 +217,5 @@ #define ER_ERROR_WHEN_EXECUTING_COMMAND 1214 #define ER_WRONG_USAGE 1215 #define ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT 1216 -#define ER_ERROR_MESSAGES 217 +#define ER_CANT_UPDATE_WITH_READLOCK 1217 +#define ER_ERROR_MESSAGES 218 diff --git a/myisam/mi_write.c b/myisam/mi_write.c index 132083ae1aa..81064dd1d6a 100644 --- a/myisam/mi_write.c +++ b/myisam/mi_write.c @@ -35,7 +35,10 @@ static int _mi_balance_page(MI_INFO *info,MI_KEYDEF *keyinfo,uchar *key, static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page, uchar *key, uint *return_key_length, uchar **after_key); - +int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key, + uint key_length); +int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key, + uint key_length); /* Write new record to database */ @@ -214,7 +217,7 @@ int _mi_ck_write(MI_INFO *info, uint keynr, uchar *key, uint key_length) **********************************************************************/ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key, - uint key_length) + uint key_length) { int error; DBUG_ENTER("_mi_ck_write_btree"); @@ -710,7 +713,7 @@ typedef struct { } bulk_insert_param; int _mi_ck_write_tree(register MI_INFO *info, uint keynr, uchar *key, - uint key_length) + uint key_length) { int error; DBUG_ENTER("_mi_ck_write_tree"); diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 413b03130f6..33cd9048774 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -1210,7 +1210,7 @@ fld1 fld1 companynr companyname table type possible_keys key key_len ref rows Extra t2 ALL NULL NULL NULL NULL 1199 -t4 eq_ref PRIMARY PRIMARY 1 t2.companynr 1 where used; Not exists +t4 eq_ref PRIMARY PRIMARY 1 test.t2.companynr 1 where used; Not exists table type possible_keys key key_len ref rows Extra t4 ALL NULL NULL NULL NULL 12 t2 ALL NULL NULL NULL NULL 1199 where used; Not exists diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 7028b5ffe33..97365811785 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -33,3 +33,5 @@ date_format(a,"%Y-%m-%d")=b right(a,6)=c+0 a=d+0 1 1 1 a 0000-00-00 00:00:00 +id dt +1 2001-08-14 00:00:00 diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index a25ea3f4dcd..4e87d9880e5 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -56,5 +56,3 @@ 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 diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 1e7bd11bab1..857937fd90e 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -30,3 +30,12 @@ CREATE TABLE t1 (a datetime not null); insert into t1 values (0); select * from t1 where a is null; drop table t1; + +# +# Test with bug when propagating DATETIME to integer and WHERE optimization +# + +create table t1 (id int, dt datetime); +insert into t1 values (1,"2001-08-14 00:00:00"),(2,"2001-08-15 00:00:00"),(3,"2001-08-16 00:00:00"); +select * from t1 where dt='2001-08-14 00:00:00' and dt = if(id=1,'2001-08-14 00:00:00','1999-08-15'); +drop table t1; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 36b14fa6bec..d6672185917 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -16,9 +16,10 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select 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; +# Test some error conditions with UNION +--error 1215 explain select a,b from t1 union all select a,b from t2; -# Test some error conditions with UNION --error 1215 select a,b from t1 into outfile 'skr' union select a,b from t2; @@ -26,7 +27,17 @@ select a,b from t1 into outfile 'skr' union select a,b from t2; select a,b from t1 order by a union select a,b from t2; --error 1216 +create table t3 select a,b from t1 union select a from t2; + +--error 1215 +insert into t3 select a from t1 order by a union select a from t2; + +--error 1216 select a,b from t1 union select a from t2; + +# Test CREATE, INSERT and REPLACE create table t3 select a,b from t1 union all select a,b from t2; insert into t3 select a,b from t1 union all select a,b from t2; +replace into t3 select a,b as c from t1 union all select a,b from t2; + drop table t1,t2,t3; diff --git a/sql/item_sum.cc b/sql/item_sum.cc index c79e909658c..a7e608855ee 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -790,12 +790,12 @@ 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, *(uint*) 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, *(uint*) arg); } /* @@ -904,7 +904,6 @@ bool Item_sum_count_distinct::setup(THD *thd) { 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); @@ -937,7 +936,8 @@ bool Item_sum_count_distinct::setup(THD *thd) compare_key = (qsort_cmp2)simple_raw_key_cmp; break; } - cmp_arg = (void*)(key_len = field->pack_length()); + key_length = field->pack_length(); + cmp_arg = (void*) &key_length; rec_offset = 1; } else // too bad, cannot cheat - there is more than one field @@ -950,38 +950,38 @@ bool Item_sum_count_distinct::setup(THD *thd) (uint32*) thd->alloc(sizeof(uint32) * table->fields))) return 1; - for (key_len = 0, lengths=field_lengths; field < field_end; ++field) + for (key_length = 0, lengths=field_lengths; field < field_end; ++field) { uint32 length= (*field)->pack_length(); - key_len += length; + key_length += length; *lengths++ = length; if (!(*field)->binary()) all_binary = 0; // Can't break loop here } - rec_offset = table->reclength - key_len; + rec_offset = table->reclength - key_length; if (all_binary) { compare_key = (qsort_cmp2)simple_raw_key_cmp; - cmp_arg = (void*)key_len; + cmp_arg = (void*) &key_length; } else { compare_key = (qsort_cmp2) composite_key_cmp ; - cmp_arg = (void*)this; + cmp_arg = (void*) this; } } init_tree(&tree, min(max_heap_table_size, sortbuff_size/16), 0, - key_len, compare_key, 0, NULL, cmp_arg); + key_length, compare_key, 0, NULL, cmp_arg); use_tree = 1; /* - The only time key_len could be 0 is if someone does + The only time key_length 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 : + max_elements_in_tree = ((key_length) ? max_heap_table_size/key_length : 1); } return 0; diff --git a/sql/item_sum.h b/sql/item_sum.h index 5500afa43ca..7356eeda28c 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -149,6 +149,7 @@ class Item_sum_count_distinct :public Item_sum_int uint32 *field_lengths; TMP_TABLE_PARAM *tmp_table_param; TREE tree; + uint key_length; // calculated based on max_heap_table_size. If reached, // walk the tree and dump it into MyISAM table @@ -169,7 +170,7 @@ class Item_sum_count_distinct :public Item_sum_int friend int composite_key_cmp(void* arg, byte* key1, byte* key2); friend int dump_leaf(byte* key, uint32 count __attribute__((unused)), - Item_sum_count_distinct* item); + Item_sum_count_distinct* item); public: Item_sum_count_distinct(List<Item> &list) diff --git a/sql/lock.cc b/sql/lock.cc index 1d9aca66e74..561ce94f88b 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -55,35 +55,13 @@ MYSQL_LOCK *mysql_lock_tables(THD *thd,TABLE **tables,uint count) Someone has issued LOCK ALL TABLES FOR READ and we want a write lock Wait until the lock is gone */ - if (thd->global_read_lock) // This thread had the read locks + if (wait_if_global_read_lock(thd, 1)) { - my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0), - write_lock_used->table_name); my_free((gptr) sql_lock,MYF(0)); sql_lock=0; break; } - - pthread_mutex_lock(&LOCK_open); - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex= &LOCK_open; - thd->mysys_var->current_cond= &COND_refresh; - thd->proc_info="Waiting for table"; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - while (global_read_lock && ! thd->killed && - thd->version == refresh_version) - { - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - } - pthread_mutex_unlock(&LOCK_open); - pthread_mutex_lock(&thd->mysys_var->mutex); - thd->mysys_var->current_mutex= 0; - thd->mysys_var->current_cond= 0; - thd->proc_info= 0; - pthread_mutex_unlock(&thd->mysys_var->mutex); - - if (thd->version != refresh_version || thd->killed) + if (thd->version != refresh_version) { my_free((gptr) sql_lock,MYF(0)); goto retry; @@ -502,3 +480,94 @@ static void print_lock_error(int error) DBUG_VOID_RETURN; } + +/**************************************************************************** + Handling of global read locks + + The global locks are handled through the global variables: + global_read_lock + waiting_for_read_lock + protect_against_global_read_lock +****************************************************************************/ + +volatile uint global_read_lock=0; +static volatile uint protect_against_global_read_lock=0; +static volatile uint waiting_for_read_lock=0; + +bool lock_global_read_lock(THD *thd) +{ + DBUG_ENTER("lock_global_read_lock"); + + if (!thd->global_read_lock) + { + (void) pthread_mutex_lock(&LOCK_open); + const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open, + "Waiting to get readlock"); + waiting_for_read_lock++; + while (protect_against_global_read_lock && !thd->killed) + pthread_cond_wait(&COND_refresh, &LOCK_open); + waiting_for_read_lock--; + if (thd->killed) + { + (void) pthread_mutex_unlock(&LOCK_open); + DBUG_RETURN(1); + } + thd->global_read_lock=1; + global_read_lock++; + (void) pthread_mutex_unlock(&LOCK_open); + } + DBUG_RETURN(0); +} + +void unlock_global_read_lock(THD *thd) +{ + uint tmp; + thd->global_read_lock=0; + pthread_mutex_lock(&LOCK_open); + tmp= --global_read_lock; + pthread_mutex_unlock(&LOCK_open); + /* Send the signal outside the mutex to avoid a context switch */ + if (!tmp) + pthread_cond_broadcast(&COND_refresh); +} + + +bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh) +{ + const char *old_message; + bool result=0; + DBUG_ENTER("wait_if_global_read_lock"); + + (void) pthread_mutex_lock(&LOCK_open); + if (global_read_lock) + { + if (thd->global_read_lock) // This thread had the read locks + { + my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0)); + DBUG_RETURN(1); + } + old_message=thd->enter_cond(&COND_refresh, &LOCK_open, + "Waiting for release of readlock"); + while (global_read_lock && ! thd->killed && + (!abort_on_refresh || thd->version == refresh_version)) + (void) pthread_cond_wait(&COND_refresh,&LOCK_open); + if (thd->killed) + result=1; + thd->exit_cond(old_message); + } + if (!abort_on_refresh && !result) + protect_against_global_read_lock++; + pthread_mutex_unlock(&LOCK_open); + DBUG_RETURN(result); +} + + +void start_waiting_global_read_lock(THD *thd) +{ + bool tmp; + (void) pthread_mutex_lock(&LOCK_open); + tmp= (!--protect_against_global_read_lock && waiting_for_read_lock); + (void) pthread_mutex_unlock(&LOCK_open); + if (tmp) + pthread_cond_broadcast(&COND_refresh); +} diff --git a/sql/log_event.cc b/sql/log_event.cc index ca01e418992..4d6dfe74934 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1054,8 +1054,7 @@ Slave_log_event::~Slave_log_event() #ifdef MYSQL_CLIENT -void Slave_log_event::print(FILE* file, bool short_form = 0, - char* last_db = 0) +void Slave_log_event::print(FILE* file, bool short_form, char* last_db) { char llbuff[22]; if(short_form) @@ -1167,8 +1166,8 @@ Create_file_log_event::Create_file_log_event(const char* buf, int len): block_len = len - block_offset; } #ifdef MYSQL_CLIENT -void Create_file_log_event::print(FILE* file, bool short_form = 0, - char* last_db = 0) +void Create_file_log_event::print(FILE* file, bool short_form, + char* last_db) { if (short_form) return; @@ -1224,8 +1223,8 @@ int Append_block_log_event::write_data(IO_CACHE* file) } #ifdef MYSQL_CLIENT -void Append_block_log_event::print(FILE* file, bool short_form = 0, - char* last_db = 0) +void Append_block_log_event::print(FILE* file, bool short_form, + char* last_db) { if (short_form) return; @@ -1273,8 +1272,8 @@ int Delete_file_log_event::write_data(IO_CACHE* file) } #ifdef MYSQL_CLIENT -void Delete_file_log_event::print(FILE* file, bool short_form = 0, - char* last_db = 0) +void Delete_file_log_event::print(FILE* file, bool short_form, + char* last_db) { if (short_form) return; @@ -1320,8 +1319,8 @@ int Execute_load_log_event::write_data(IO_CACHE* file) } #ifdef MYSQL_CLIENT -void Execute_load_log_event::print(FILE* file, bool short_form = 0, - char* last_db = 0) +void Execute_load_log_event::print(FILE* file, bool short_form, + char* last_db) { if (short_form) return; @@ -1757,7 +1756,7 @@ int Execute_load_log_event::exec_event(struct st_master_info* mi) // can preserve ascending order of log sequence numbers - needed // to handle failover save_options = thd->options; - thd->options &= ~OPTION_BIN_LOG; + thd->options &= ~ (ulong) OPTION_BIN_LOG; lev->thd = thd; if (lev->exec_event(0,0)) { diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index ffa980013ab..dbc8f1a06cd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -285,7 +285,6 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, HA_CHECK_OPT* check_opt); /* net_pkg.c */ -void send_error(NET *net,uint sql_errno=0, const char *err=0); void send_warning(NET *net, uint sql_errno, const char *err=0); void net_printf(NET *net,uint sql_errno, ...); void send_ok(NET *net,ha_rows affected_rows=0L,ulonglong id=0L, @@ -312,11 +311,12 @@ SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, List <Item> &all_fields, ORDER *order); +int handle_select(THD *thd, LEX *lex, select_result *result); 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, ulong select_type,select_result *result); -int mysql_union(THD *thd,LEX *lex,select_result *create_insert=(select_result *)NULL); +int mysql_union(THD *thd,LEX *lex,select_result *result); Field *create_tmp_field(TABLE *table,Item *item, Item::Type type, Item_result_field ***copy_func, Field **from_field, bool group,bool modify_item); @@ -586,6 +586,10 @@ void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count); void mysql_lock_remove(THD *thd, MYSQL_LOCK *locked,TABLE *table); void mysql_lock_abort(THD *thd, TABLE *table); MYSQL_LOCK *mysql_lock_merge(MYSQL_LOCK *a,MYSQL_LOCK *b); +bool lock_global_read_lock(THD *thd); +void unlock_global_read_lock(THD *thd); +bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh); +void start_waiting_global_read_lock(THD *thd); /* Lock based on name */ int lock_table_name(THD *thd, TABLE_LIST *table_list); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5efeb59c17e..1cba564d6e5 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -262,7 +262,7 @@ bool server_id_supplied = 0; uint mysql_port; uint test_flags = 0, select_errors=0, dropping_tables=0,ha_open_options=0; uint volatile thread_count=0, thread_running=0, kill_cached_threads=0, - wake_thread=0, global_read_lock=0; + wake_thread=0; ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL | OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE ); uint protocol_version=PROTOCOL_VERSION; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 0b3ac27d1f6..c1911e002a3 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2637,7 +2637,6 @@ int QUICK_SELECT_DESC::get_next() } range = 0; // To next range } - DBUG_RETURN(HA_ERR_END_OF_FILE); } /* diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 79de8d07cd8..39c9fb8f030 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -227,3 +227,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 03cf6f202ea..70f9e0f1088 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -221,3 +221,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index ad58b31b378..bd19abe99b1 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -222,3 +222,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index d8e3ed1d538..8a9e246c3e2 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 27eb20e9369..a4f9fa2223f 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -222,3 +222,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 3eca90eb01f..edc24953296 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 671758cf35f..43f77d698f4 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -221,3 +221,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index d565484e087..7466abea5b4 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 60bb63e166d..6eabaf1fbd9 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -220,3 +220,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index b0d17d2c63b..036b59fe320 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 7443fffca47..0ee0e80a541 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -220,3 +220,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index f13db8d160b..8864acb5e7e 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 9594a8f211e..29b9c260fb9 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -220,3 +220,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 2e1d403dd30..c2cad5de067 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -220,3 +220,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index f70c86013d8..38515256a3c 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -222,3 +222,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 29173b5a772..0d907aa4f14 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -218,3 +218,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 90ccfcb399a..3c47a149e3a 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -222,3 +222,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index c184a10b821..e030072c686 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -221,3 +221,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index f57ebbee2c4..22360c08c9b 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -226,3 +226,4 @@ "Error when executing command %s: %-.128s", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index d80370ed1d6..237e1d2716f 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -219,3 +219,4 @@ "Error de %s: %-128%", "Wrong usage of %s and %s", "The used SELECT statements have a different number of columns", +"Can't execute the query because you have a conflicting read lock", diff --git a/sql/share/swedish/errmsg.OLD b/sql/share/swedish/errmsg.OLD index 227a02ac873..3dd14c8b613 100644 --- a/sql/share/swedish/errmsg.OLD +++ b/sql/share/swedish/errmsg.OLD @@ -205,9 +205,17 @@ "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", -"Tiden att få ett lås var för lång", -"Antal lås är större än vad som ryms i lock tabellen", -"Du kan inte låsa tabeller/poster under READ UNCOMMITTED", -"Fick fel vid inloggning till master: %-.128s", -"Fick fel vid exekvering av fråga på master: %-.128s", +"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", +"%-.32s@%-.64s har inte rättigheter att skapa nya användare", +"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" +"Kan inte utföra kommandot emedan du har ett READ lås", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 535b04fe514..3dd14c8b613 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -218,3 +218,4 @@ "Fick fel vid utförande av %s: %-.128s", "Felaktig använding av %s and %s", "SELECT kommandona har olika antal kolumner" +"Kan inte utföra kommandot emedan du har ett READ lås", diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5fc3d32b817..4adc93b7aa4 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1006,7 +1006,7 @@ static int replace_user_table(TABLE *table, const LEX_USER &combo, my_printf_error(ER_NO_PERMISSION_TO_CREATE_USER, ER(ER_NO_PERMISSION_TO_CREATE_USER), MYF(0),thd->user, - thd->host ? thd->host : thd->ip ? thd->ip: ""); + thd->host_or_ip); error= -1; goto end; } @@ -1503,8 +1503,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, uint store_table_rights,store_col_rights; DBUG_ENTER("replace_table_table"); - strxmov(grantor,thd->user,"@",thd->host ? thd->host : thd->ip ? thd->ip :"", - NullS); + strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS); // The following should always succeed as new users are created before // this function is called! @@ -2091,7 +2090,7 @@ bool check_grant(THD *thd, uint want_access, TABLE_LIST *tables, net_printf(&thd->net,ER_TABLEACCESS_DENIED_ERROR, command, thd->priv_user, - thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, table ? table->real_name : "unknown"); } return 1; @@ -2154,7 +2153,7 @@ bool check_grant_column (THD *thd,TABLE *table, const char *name, MYF(0), command, thd->priv_user, - thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, name, table ? table->real_name : "unknown"); } @@ -2212,7 +2211,7 @@ bool check_grant_all_columns(THD *thd,uint want_access, TABLE *table) MYF(0), command, thd->priv_user, - thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, field ? field->field_name : "unknown", table->real_name); return 1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 13c673fdb33..13c60641db0 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -82,6 +82,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0), global_read_lock(0),bootstrap(0) { host=user=priv_user=db=query=ip=0; + host_or_ip="unknown ip"; locked=killed=count_cuted_fields=some_tables_deleted=no_errors=password= query_start_used=0; query_length=col_access=0; @@ -183,12 +184,7 @@ THD::~THD() } #endif if (global_read_lock) - { - pthread_mutex_lock(&LOCK_open); - ::global_read_lock--; - pthread_cond_broadcast(&COND_refresh); - pthread_mutex_unlock(&LOCK_open); - } + unlock_global_read_lock(this); if (ull) { pthread_mutex_lock(&LOCK_user_locks); diff --git a/sql/sql_class.h b/sql/sql_class.h index d149f087c1f..adbf3bd8008 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -239,7 +239,7 @@ public: struct rand_struct rand; char *query,*thread_stack; char *host,*user,*priv_user,*db,*ip; - const char *proc_info; + const char *proc_info, *host_or_ip; uint client_capabilities,sql_mode,max_packet_length; uint master_access,db_access; TABLE *open_tables,*temporary_tables, *handler_tables; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 85d3f0a344c..21d44d3b41d 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -348,11 +348,11 @@ bool mysql_change_db(THD *thd,const char *name) { net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, thd->priv_user, - thd->host ? thd->host : thd->ip ? thd->ip : "unknown", + thd->host_or_ip, dbname); mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), thd->priv_user, - thd->host ? thd->host : thd->ip ? thd->ip : "unknown", + thd->host_or_ip, dbname); my_free(dbname,MYF(0)); DBUG_RETURN(1); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d14201822e0..2fb9e3780a1 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -35,26 +35,10 @@ int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table) TABLE **table_ptr; DBUG_ENTER("generate_table"); + if (wait_if_global_read_lock(thd,0)) + DBUG_RETURN(1); thd->proc_info="generate_table"; - - if (global_read_lock) - { - if(thd->global_read_lock) - { - my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0), - table_list->real_name); - DBUG_RETURN(-1); - } - pthread_mutex_lock(&LOCK_open); - while (global_read_lock && ! thd->killed || - thd->version != refresh_version) - { - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - } - pthread_mutex_unlock(&LOCK_open); - } - - + /* If it is a temporary table, close and regenerate it */ if ((table_ptr=find_temporary_table(thd,table_list->db, table_list->real_name))) @@ -91,6 +75,7 @@ int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table) if (!locked_table) { VOID(pthread_mutex_unlock(&LOCK_open)); + start_waiting_global_read_lock(thd); DBUG_RETURN(1); // We must get a lock on table } } @@ -118,6 +103,7 @@ int generate_table(THD *thd, TABLE_LIST *table_list, TABLE *locked_table) } send_ok(&thd->net); // This should return record count } + start_waiting_global_read_lock(thd); DBUG_RETURN(error ? -1 : 0); } @@ -298,7 +284,7 @@ int mysql_delete(THD *thd, int refposcmp2(void* arg, const void *a,const void *b) { - return memcmp(a,b,(int) arg); + return memcmp(a,b, *(int*) arg); } multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, @@ -321,7 +307,7 @@ multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt, (void) dt->table->file->extra(HA_EXTRA_NO_READCHECK); (void) dt->table->file->extra(HA_EXTRA_NO_KEYREAD); tempfiles[counter] = new Unique (refposcmp2, - (void *) table->file->ref_length, + (void *) &table->file->ref_length, table->file->ref_length, MEM_STRIP_BUF_SIZE); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index ef32dca6fc8..4d2441da246 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -55,8 +55,8 @@ enum enum_sql_command { SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_SHOW_BINLOGS, SQLCOM_SHOW_OPEN_TABLES, SQLCOM_LOAD_MASTER_DATA, SQLCOM_HA_OPEN, SQLCOM_HA_CLOSE, SQLCOM_HA_READ, - SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_MULTI_DELETE, SQLCOM_UNION_SELECT, - SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_NONE + SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_MULTI_DELETE, + SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, }; enum lex_states { STATE_START, STATE_CHAR, STATE_IDENT, @@ -106,7 +106,6 @@ enum sub_select_type {UNSPECIFIED_TYPE,UNION_TYPE, INTERSECT_TYPE, EXCEPT_TYPE}; typedef struct st_select_lex { enum sub_select_type linkage; - uint select_number; /* For Item_select */ char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ Item *where,*having; ha_rows select_limit,offset_limit; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3eefef070da..494af89cc5b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -47,8 +47,7 @@ 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 create_total_list_and_check_acl(THD *thd, LEX *lex, - TABLE_LIST **result, bool skip_first = false); +static int create_total_list(THD *thd, LEX *lex, TABLE_LIST **result); static int handle_create_select(THD *thd, LEX *lex, select_result *c_i); const char *any_db="*any*"; // Special symbol for check_access @@ -120,18 +119,18 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, DBUG_PRINT("general", ("Capabilities: %d packet_length: %d Host: '%s' User: '%s' Using password: %s Access: %u db: '%s'", thd->client_capabilities, thd->max_packet_length, - thd->host ? thd->host : thd->ip, thd->priv_user, + thd->host_or_ip, thd->priv_user, passwd[0] ? "yes": "no", thd->master_access, thd->db ? thd->db : "*none*")); if (thd->master_access & NO_ACCESS) { net_printf(net, ER_ACCESS_DENIED_ERROR, thd->user, - thd->host ? thd->host : thd->ip, + thd->host_or_ip, passwd[0] ? ER(ER_YES) : ER(ER_NO)); mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR), thd->user, - thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip", + thd->host_or_ip, passwd[0] ? ER(ER_YES) : ER(ER_NO)); return(1); // Error already given } @@ -152,7 +151,7 @@ static bool check_user(THD *thd,enum_server_command command, const char *user, (char*) "%s@%s on %s" : (char*) "%s@%s as anonymous on %s"), user, - thd->host ? thd->host : thd->ip ? thd->ip : "unknown ip", + thd->host_or_ip, db ? db : (char*) ""); thd->db_access=0; if (max_user_connections && @@ -331,6 +330,7 @@ check_connections(THD *thd) return (ER_BAD_HOST_ERROR); if (!(thd->ip = my_strdup(ip,MYF(0)))) return (ER_OUT_OF_RESOURCES); + thd->host_or_ip=thd->ip; #if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread) /* Fast local hostname resolve for Win32 */ if (!strcmp(thd->ip,"127.0.0.1")) @@ -353,6 +353,7 @@ check_connections(THD *thd) else /* Hostname given means that the connection was on a socket */ { DBUG_PRINT("general",("Host: %s",thd->host)); + thd->host_or_ip=thd->host; thd->ip=0; bzero((char*) &thd->remote,sizeof(struct sockaddr)); } @@ -531,7 +532,7 @@ pthread_handler_decl(handle_one_connection,arg) if ((error=check_connections(thd))) { // Wrong permissions if (error > 0) - net_printf(net,error,thd->host ? thd->host : thd->ip); + net_printf(net,error,thd->host_or_ip); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) sleep(1); /* must wait after eof() */ @@ -562,7 +563,7 @@ pthread_handler_decl(handle_one_connection,arg) sql_print_error(ER(ER_NEW_ABORTING_CONNECTION), thd->thread_id,(thd->db ? thd->db : "unconnected"), thd->user ? thd->user : "unauthenticated", - (thd->host ? thd->host : thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); send_error(net,net->last_errno,NullS); @@ -694,9 +695,8 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) goto err; } net_flush(&thd->net); - error = table->file->dump(thd,fd); - if(error) - my_error(ER_GET_ERRNO, MYF(0)); + if ((error = table->file->dump(thd,fd))) + my_error(ER_GET_ERRNO, MYF(0)); err: @@ -763,7 +763,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thread_running++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->set_time(); - thd->lex.select_lex.options=0; // We store status here + thd->lex.select_lex.options=0; // We store status here switch (command) { case COM_INIT_DB: if (!mysql_change_db(thd,packet)) @@ -1073,10 +1073,13 @@ mysql_execute_command(void) SELECT_LEX *select_lex = lex->select; DBUG_ENTER("mysql_execute_command"); - if(table_rules_on && thd->slave_thread && tables && !tables_ok(thd,tables)) - DBUG_VOID_RETURN; // skip if we are in the slave thread, some table - // rules have been given and the table list says the query should not be - // replicated + /* + Skip if we are in the slave thread, some table rules have been given + and the table list says the query should not be replicated + TODO: UPDATE this for UNION + */ + if (table_rules_on && thd->slave_thread && tables && !tables_ok(thd,tables)) + DBUG_VOID_RETURN; switch (lex->sql_command) { case SQLCOM_SELECT: @@ -1084,6 +1087,9 @@ mysql_execute_command(void) select_result *result; if (select_lex->options & SELECT_DESCRIBE) lex->exchange=0; + /* Save a call, as it's very uncomon that we use unions */ + if (lex->select_lex.next && (res = create_total_list(thd,lex,&tables))) + break; if (tables) { res=check_table_access(thd, @@ -1148,33 +1154,18 @@ mysql_execute_command(void) } if (!(res=open_and_lock_tables(thd,tables))) - { - res=mysql_select(thd,tables,select_lex->item_list, - select_lex->where, - select_lex->ftfunc_list, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, - select_lex->having, - (ORDER*) lex->proc_list.first, - select_lex->options | thd->options, - result); - if (res) - result->abort(); - } - delete result; -#ifdef DELETE_ITEMS - delete select_lex->having; - delete select_lex->where; -#endif + res=handle_select(thd, lex, result); + else + delete result; break; } case SQLCOM_PURGE: - { - if (check_process_priv(thd)) - goto error; - res = purge_master_logs(thd, lex->to_log); - break; - } + { + if (check_process_priv(thd)) + goto error; + res = purge_master_logs(thd, lex->to_log); + break; + } case SQLCOM_SHOW_NEW_MASTER: { if(check_access(thd, FILE_ACL, any_db)) @@ -1197,45 +1188,45 @@ mysql_execute_command(void) break; } case SQLCOM_BACKUP_TABLE: - { - if (check_db_used(thd,tables) || - check_table_access(thd,SELECT_ACL, tables) || - check_access(thd, FILE_ACL, any_db)) - goto error; /* purecov: inspected */ - res = mysql_backup_table(thd, tables); + { + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL, tables) || + check_access(thd, FILE_ACL, any_db)) + goto error; /* purecov: inspected */ + res = mysql_backup_table(thd, tables); - break; - } + break; + } case SQLCOM_RESTORE_TABLE: - { - if (check_db_used(thd,tables) || - check_table_access(thd,INSERT_ACL, tables) || - check_access(thd, FILE_ACL, any_db)) - goto error; /* purecov: inspected */ - res = mysql_restore_table(thd, tables); - break; - } + { + if (check_db_used(thd,tables) || + check_table_access(thd,INSERT_ACL, tables) || + check_access(thd, FILE_ACL, any_db)) + goto error; /* purecov: inspected */ + res = mysql_restore_table(thd, tables); + break; + } case SQLCOM_CHANGE_MASTER: - { - if(check_access(thd, PROCESS_ACL, any_db)) - goto error; - res = change_master(thd); - break; - } + { + if(check_access(thd, PROCESS_ACL, any_db)) + goto error; + res = change_master(thd); + break; + } case SQLCOM_SHOW_SLAVE_STAT: - { - if (check_process_priv(thd)) - goto error; - res = show_master_info(thd); - break; - } + { + if (check_process_priv(thd)) + goto error; + res = show_master_info(thd); + break; + } case SQLCOM_SHOW_MASTER_STAT: - { - if (check_process_priv(thd)) - goto error; - res = show_binlog_info(thd); - break; - } + { + if (check_process_priv(thd)) + goto error; + res = show_binlog_info(thd); + break; + } case SQLCOM_LOAD_MASTER_DATA: // sync with master if(check_process_priv(thd)) @@ -1257,7 +1248,7 @@ mysql_execute_command(void) bool error=check_grant(thd,CREATE_ACL,tables); tables->next=tmp_table_list; if (error) - goto error; + goto error; } if (strlen(tables->name) > NAME_LEN) { @@ -1304,6 +1295,8 @@ mysql_execute_command(void) if (select_lex->item_list.elements) // With select { select_result *result; + if ((res = create_total_list(thd,lex,&tables))) + break; if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) && check_dup(thd,tables->db,tables->real_name,tables->next)) @@ -1323,15 +1316,22 @@ mysql_execute_command(void) thd->select_limit=select_lex->select_limit+select_lex->offset_limit; if (thd->select_limit < select_lex->select_limit) thd->select_limit= HA_POS_ERROR; // No limit - if ((result=new select_create(tables->db ? tables->db : thd->db, - tables->real_name, &lex->create_info, - lex->create_list, - lex->key_list, - select_lex->item_list,lex->duplicates))) - res=handle_create_select(thd,lex,result); - else - res= -1; - } + + /* Skip first table, which is the table we are creating */ + lex->select_lex.table_list.first= + (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next); + if (!(res=open_and_lock_tables(thd,tables->next))) + { + if ((result=new select_create(tables->db ? tables->db : thd->db, + tables->real_name, &lex->create_info, + lex->create_list, + lex->key_list, + select_lex->item_list,lex->duplicates))) + res=handle_select(thd, lex, result); + else + res= -1; + } + } else // regular create { res = mysql_create_table(thd,tables->db ? tables->db : thd->db, @@ -1438,7 +1438,7 @@ mysql_execute_command(void) old_list.next=new_list.next=0; if (check_grant(thd,ALTER_ACL,&old_list) || (!test_all_bits(table->next->grant.privilege, - INSERT_ACL | CREATE_ACL) && + INSERT_ACL | CREATE_ACL) && check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list))) goto error; } @@ -1476,21 +1476,21 @@ mysql_execute_command(void) } #endif case SQLCOM_REPAIR: - { - if (check_db_used(thd,tables) || - check_table_access(thd,SELECT_ACL | INSERT_ACL, tables)) - goto error; /* purecov: inspected */ - res = mysql_repair_table(thd, tables, &lex->check_opt); - break; - } + { + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL | INSERT_ACL, tables)) + goto error; /* purecov: inspected */ + res = mysql_repair_table(thd, tables, &lex->check_opt); + break; + } case SQLCOM_CHECK: - { - if (check_db_used(thd,tables) || - check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables)) - goto error; /* purecov: inspected */ - res = mysql_check_table(thd, tables, &lex->check_opt); - break; - } + { + if (check_db_used(thd,tables) || + check_table_access(thd, SELECT_ACL | EXTRA_ACL , tables)) + goto error; /* purecov: inspected */ + res = mysql_check_table(thd, tables, &lex->check_opt); + break; + } case SQLCOM_ANALYZE: { if (check_db_used(thd,tables) || @@ -1574,6 +1574,9 @@ mysql_execute_command(void) case SQLCOM_REPLACE_SELECT: case SQLCOM_INSERT_SELECT: { + if ((res = create_total_list(thd,lex,&tables))) + break; + // Check that we have modify privileges for the first table and // select privileges for the rest { @@ -1596,81 +1599,30 @@ mysql_execute_command(void) if (thd->select_limit < select_lex->select_limit) thd->select_limit= HA_POS_ERROR; // No limit - if (lex->select_lex.next) - { - TABLE_LIST *total; - if ((res = create_total_list_and_check_acl(thd,lex,&total))) - goto error; - if (check_dup(thd,total->db,total->real_name,total->next)) - { - net_printf(&thd->net,ER_INSERT_TABLE_USED,total->real_name); - DBUG_VOID_RETURN; - } - total->lock_type=TL_WRITE; // update first table - { - TABLE_LIST *table; - for (table = total->next ; table ; table=table->next) - table->lock_type= lex->lock_option; - } - if (!(res=open_and_lock_tables(thd, total))) - { - if ((result=new select_insert(total->table,&lex->field_list, - lex->sql_command == SQLCOM_REPLACE_SELECT ? - DUP_REPLACE : DUP_IGNORE))) - { - - for (SELECT_LEX *sl=&lex->select_lex; sl; sl=sl->next) - { - TABLE_LIST *help=(TABLE_LIST *)sl->table_list.first; - if (sl==&lex->select_lex) help=help->next; - for (TABLE_LIST *cursor= help; - cursor; - cursor=cursor->next) - cursor->table= ((TABLE_LIST*) cursor->table)->table; - } - res=mysql_union(thd,lex,result); - } - close_thread_tables(thd); - } - } - else - { - if (check_dup(thd,tables->db,tables->real_name,tables->next)) - { - net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); - DBUG_VOID_RETURN; - } - tables->lock_type=TL_WRITE; // update first table - { - TABLE_LIST *table; - for (table = tables->next ; table ; table=table->next) - table->lock_type= lex->lock_option; - } - if (!(res=open_and_lock_tables(thd,tables))) - { - if ((result=new select_insert(tables->table,&lex->field_list, - lex->sql_command == SQLCOM_REPLACE_SELECT ? - DUP_REPLACE : DUP_IGNORE))) - { - res=mysql_select(thd,tables->next,select_lex->item_list, - select_lex->where, - select_lex->ftfunc_list, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, - select_lex->having, - (ORDER*) lex->proc_list.first, - select_lex->options | thd->options, - result); - delete result; - } - else - res= -1; - } + if (check_dup(thd,tables->db,tables->real_name,tables->next)) + { + net_printf(&thd->net,ER_INSERT_TABLE_USED,tables->real_name); + DBUG_VOID_RETURN; } -#ifdef DELETE_ITEMS - delete select_lex->having; - delete select_lex->where; -#endif + tables->lock_type=TL_WRITE; // update first table + { + TABLE_LIST *table; + for (table = tables->next ; table ; table=table->next) + table->lock_type= lex->lock_option; + } + + /* Skip first table, which is the table we are inserting in */ + lex->select_lex.table_list.first= + (byte*) (((TABLE_LIST *) lex->select_lex.table_list.first)->next); + if (!(res=open_and_lock_tables(thd, tables))) + { + if ((result=new select_insert(tables->table,&lex->field_list, + lex->sql_command == SQLCOM_REPLACE_SELECT ? + DUP_REPLACE : DUP_IGNORE))) + res=handle_select(thd,lex,result); + } + else + res= -1; break; } case SQLCOM_TRUNCATE: @@ -1760,39 +1712,6 @@ mysql_execute_command(void) close_thread_tables(thd); break; } - case SQLCOM_UNION_SELECT: - { - TABLE_LIST *total; - if (select_lex->options & SELECT_DESCRIBE) - lex->exchange=0; - if ((res = create_total_list_and_check_acl(thd,lex,&total)) == -1) - { - res=0; - break; - } - if (res && - (res=check_access(thd, - lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL, - any_db))) - { - res=0; - break; - } - 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)) @@ -1952,7 +1871,7 @@ mysql_execute_command(void) else { if (check_access(thd,privilege,tables->db,&tables->grant.privilege) || - grant_option && check_grant(thd,privilege,tables)) + grant_option && check_grant(thd,privilege,tables)) goto error; } res=mysql_load(thd, lex->exchange, tables, lex->field_list, @@ -2006,13 +1925,7 @@ mysql_execute_command(void) end_active_trans(thd); } if (thd->global_read_lock) - { - thd->global_read_lock=0; - pthread_mutex_lock(&LOCK_open); - global_read_lock--; - pthread_cond_broadcast(&COND_refresh); - pthread_mutex_unlock(&LOCK_open); - } + unlock_global_read_lock(thd); send_ok(&thd->net); break; case SQLCOM_LOCK_TABLES: @@ -2036,30 +1949,30 @@ mysql_execute_command(void) thd->in_lock_tables=0; break; case SQLCOM_CREATE_DB: + { + if (!stripp_sp(lex->name) || check_db_name(lex->name)) { - if (!stripp_sp(lex->name) || check_db_name(lex->name)) - { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); - break; - } - if (check_access(thd,CREATE_ACL,lex->name,0,1)) - break; - mysql_create_db(thd,lex->name,lex->create_info.options); + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); break; } + if (check_access(thd,CREATE_ACL,lex->name,0,1)) + break; + mysql_create_db(thd,lex->name,lex->create_info.options); + break; + } case SQLCOM_DROP_DB: + { + if (!stripp_sp(lex->name) || check_db_name(lex->name)) { - if (!stripp_sp(lex->name) || check_db_name(lex->name)) - { - net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); - break; - } - if (check_access(thd,DROP_ACL,lex->name,0,1) || - end_active_trans(thd)) - break; - mysql_rm_db(thd,lex->name,lex->drop_if_exists); + net_printf(&thd->net,ER_WRONG_DB_NAME, lex->name); break; } + if (check_access(thd,DROP_ACL,lex->name,0,1) || + end_active_trans(thd)) + break; + mysql_rm_db(thd,lex->name,lex->drop_if_exists); + break; + } case SQLCOM_CREATE_FUNCTION: if (check_access(thd,INSERT_ACL,"mysql",0,1)) break; @@ -2080,78 +1993,78 @@ mysql_execute_command(void) res= -1; #endif break; - case SQLCOM_REVOKE: - case SQLCOM_GRANT: - { - if (tables && !tables->db) - tables->db=thd->db; - if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, - tables && tables->db ? tables->db : select_lex->db, - tables ? &tables->grant.privilege : 0, - tables ? 0 : 1)) - goto error; - - /* Check that the user isn't trying to change a password for another - user if he doesn't have UPDATE privilege to the MySQL database */ - - if (thd->user) // If not replication - { - LEX_USER *user; - List_iterator <LEX_USER> user_list(lex->users_list); - while ((user=user_list++)) - { - if (user->password.str && - (strcmp(thd->user,user->user.str) || - user->host.str && - my_strcasecmp(user->host.str, thd->host ? thd->host : thd->ip))) - { - if (check_access(thd, UPDATE_ACL, "mysql",0,1)) - goto error; - break; // We are allowed to do changes - } - } - } - if (tables) - { - if (grant_option && check_grant(thd, - (lex->grant | lex->grant_tot_col | - GRANT_ACL), - tables)) - goto error; - res = mysql_table_grant(thd,tables,lex->users_list, lex->columns, - lex->grant, lex->sql_command == SQLCOM_REVOKE); - if(!res) - { - mysql_update_log.write(thd, thd->query,thd->query_length); - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); - } - } - } - else - { - if (lex->columns.elements) - { - net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); - res=1; - } - else - res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, - lex->sql_command == SQLCOM_REVOKE); - if (!res) - { - mysql_update_log.write(thd, thd->query,thd->query_length); - if (mysql_bin_log.is_open()) - { - Query_log_event qinfo(thd, thd->query); - mysql_bin_log.write(&qinfo); - } - } - } - break; - } + case SQLCOM_REVOKE: + case SQLCOM_GRANT: + { + if (tables && !tables->db) + tables->db=thd->db; + if (check_access(thd, lex->grant | lex->grant_tot_col | GRANT_ACL, + tables && tables->db ? tables->db : select_lex->db, + tables ? &tables->grant.privilege : 0, + tables ? 0 : 1)) + goto error; + + /* Check that the user isn't trying to change a password for another + user if he doesn't have UPDATE privilege to the MySQL database */ + + if (thd->user) // If not replication + { + LEX_USER *user; + List_iterator <LEX_USER> user_list(lex->users_list); + while ((user=user_list++)) + { + if (user->password.str && + (strcmp(thd->user,user->user.str) || + user->host.str && + my_strcasecmp(user->host.str, thd->host_or_ip))) + { + if (check_access(thd, UPDATE_ACL, "mysql",0,1)) + goto error; + break; // We are allowed to do changes + } + } + } + if (tables) + { + if (grant_option && check_grant(thd, + (lex->grant | lex->grant_tot_col | + GRANT_ACL), + tables)) + goto error; + res = mysql_table_grant(thd,tables,lex->users_list, lex->columns, + lex->grant, lex->sql_command == SQLCOM_REVOKE); + if(!res) + { + mysql_update_log.write(thd, thd->query,thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + } + } + } + else + { + if (lex->columns.elements) + { + net_printf(&thd->net,ER_ILLEGAL_GRANT_FOR_TABLE); + res=1; + } + else + res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, + lex->sql_command == SQLCOM_REVOKE); + if (!res) + { + mysql_update_log.write(thd, thd->query,thd->query_length); + if (mysql_bin_log.is_open()) + { + Query_log_event qinfo(thd, thd->query); + mysql_bin_log.write(&qinfo); + } + } + } + break; + } case SQLCOM_FLUSH: case SQLCOM_RESET: if (check_access(thd,RELOAD_ACL,any_db) || check_db_used(thd, tables)) @@ -2166,14 +2079,16 @@ mysql_execute_command(void) break; case SQLCOM_SHOW_GRANTS: res=0; - if ((thd->priv_user && !strcmp(thd->priv_user,lex->grant_user->user.str)) || + if ((thd->priv_user && + !strcmp(thd->priv_user,lex->grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql",0,1)) { res = mysql_show_grants(thd,lex->grant_user); } break; case SQLCOM_HA_OPEN: - if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL, tables)) goto error; res = mysql_ha_open(thd, tables); break; @@ -2183,11 +2098,12 @@ mysql_execute_command(void) res = mysql_ha_close(thd, tables); break; case SQLCOM_HA_READ: - if (check_db_used(thd,tables) || check_table_access(thd,SELECT_ACL, tables)) + if (check_db_used(thd,tables) || + check_table_access(thd,SELECT_ACL, tables)) goto error; res = mysql_ha_read(thd, tables, lex->ha_read_mode, lex->backup_dir, - lex->insert_list, lex->ha_rkey_mode, select_lex->where, - select_lex->select_limit, select_lex->offset_limit); + lex->insert_list, lex->ha_rkey_mode, select_lex->where, + select_lex->select_limit, select_lex->offset_limit); break; case SQLCOM_BEGIN: @@ -2278,7 +2194,7 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, { // We can never grant this net_printf(&thd->net,ER_ACCESS_DENIED_ERROR, thd->priv_user, - thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */ return TRUE; /* purecov: tested */ } @@ -2301,7 +2217,7 @@ check_access(THD *thd,uint want_access,const char *db, uint *save_priv, return FALSE; /* Ok */ net_printf(&thd->net,ER_DBACCESS_DENIED_ERROR, thd->priv_user, - thd->host ? thd->host : (thd->ip ? thd->ip : "unknown"), + thd->host_or_ip, db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */ return TRUE; /* purecov: tested */ } @@ -2458,7 +2374,6 @@ mysql_init_query(THD *thd) thd->fatal_error=0; // Safety thd->last_insert_id_used=thd->query_start_used=thd->insert_id_used=0; thd->sent_row_count=thd->examined_row_count=0; - thd->lex.sql_command=SQLCOM_NONE; DBUG_VOID_RETURN; } @@ -2470,7 +2385,7 @@ mysql_init_select(LEX *lex) select_lex->select_limit=current_thd->default_select_limit; select_lex->offset_limit=0; select_lex->options=0; select_lex->linkage=UNSPECIFIED_TYPE; - select_lex->select_number = 0; lex->exchange = 0; + lex->exchange = 0; lex->proc_list.first=0; select_lex->order_list.elements=select_lex->group_list.elements=0; select_lex->order_list.first=0; @@ -2483,12 +2398,9 @@ mysql_init_select(LEX *lex) void mysql_new_select(LEX *lex) { - uint select_no=lex->select->select_number; SELECT_LEX *select_lex = (SELECT_LEX *) lex->thd->calloc(sizeof(SELECT_LEX)); lex->select->next=select_lex; - lex->select=select_lex; select_lex->select_number = ++select_no; - select_lex->table_list.elements=0; - select_lex->table_list.first=0; + lex->select=select_lex; select_lex->table_list.next= (byte**) &select_lex->table_list.first; select_lex->item_list.empty(); select_lex->when_list.empty(); select_lex->expr_list.empty(); select_lex->interval_list.empty(); @@ -2871,7 +2783,6 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, register TABLE_LIST *ptr; THD *thd=current_thd; char *alias_str; - const char *current_db; DBUG_ENTER("add_table_to_list"); if (!table) @@ -2887,14 +2798,14 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, #ifdef FN_LOWER_CASE if (!alias) /* Alias is case sensitive */ - if (!(alias_str=sql_strmake(alias_str,table->table.length))) + if (!(alias_str=thd->memdup(alias_str,table->table.length+1))) DBUG_RETURN(0); if (lower_case_table_names) casedn_str(table->table.str); #endif if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST)))) DBUG_RETURN(0); /* purecov: inspected */ - ptr->db= table->db.str; + ptr->db= table->db.str ? table->db.str : (thd->db ? thd->db : (char*) ""); ptr->real_name=table->table.str; ptr->name=alias_str; ptr->lock_type=flags; @@ -2907,16 +2818,12 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, sizeof(*ignore_index)); /* check that used name is unique */ - current_db=thd->db ? thd->db : ""; - if (flags != TL_IGNORE) { for (TABLE_LIST *tables=(TABLE_LIST*) thd->lex.select->table_list.first ; tables ; tables=tables->next) { - if (!strcmp(alias_str,tables->name) && - !strcmp(ptr->db ? ptr->db : current_db, - tables->db ? tables->db : current_db)) + if (!strcmp(alias_str,tables->name) && !strcmp(ptr->db, tables->db)) { net_printf(&thd->net,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */ DBUG_RETURN(0); /* purecov: tested */ @@ -2934,40 +2841,37 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias, ** to the entries in this list. */ -static int create_total_list_and_check_acl(THD *thd, LEX *lex, - TABLE_LIST **result, bool skip_first = false) +static int create_total_list(THD *thd, LEX *lex, TABLE_LIST **result) { + /* Handle the case when we are not using union */ + if (!lex->select_lex.next) + { + *result= (TABLE_LIST*) lex->select_lex.table_list.first; + return 0; + } + 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 && sl->next) + if (sl->order_list.first && sl->next) { - net_printf(&thd->net,ER_WRONG_USAGE,"UNION","ORDER BY"); + my_error(ER_WRONG_USAGE,MYF(0),"UNION","ORDER BY"); return -1; } - aux= (TABLE_LIST*) sl->table_list.first; - if (skip_first && sl == &lex->select_lex) aux=aux->next; - if (aux) + if ((aux= (TABLE_LIST*) sl->table_list.first)) { TABLE_LIST *next; - if (check_table_access(thd, - lex->exchange ? - SELECT_ACL | FILE_ACL : SELECT_ACL , aux)) - return -1; for (; aux; aux=next) { 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))) + !strcmp(cursor->real_name,aux->real_name) && + !strcmp(cursor->name, aux->name)) break; if (!cursor) { @@ -2975,7 +2879,7 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex, aux->lock_type= lex->lock_option; if (!(cursor = (TABLE_LIST *) thd->memdup((byte*) aux, sizeof(*aux)))) - return 1; + return -1; *new_table_list= cursor; new_table_list= &cursor->next; *new_table_list=0; // end result list @@ -2987,51 +2891,6 @@ static int create_total_list_and_check_acl(THD *thd, LEX *lex, return 0; } -static int handle_create_select(THD *thd, LEX *lex, select_result *c_i) -{ - int res; - if (lex->select_lex.next) - { - TABLE_LIST *total; - if ((res = create_total_list_and_check_acl(thd,lex,&total,true))) - return res; - if (!(res=open_and_lock_tables(thd, total))) - { - for (SELECT_LEX *sl=&lex->select_lex; sl; sl=sl->next) - { - TABLE_LIST *help=(TABLE_LIST *)sl->table_list.first; - if (sl==&lex->select_lex) help=help->next; - for (TABLE_LIST *cursor= help; - cursor; - cursor=cursor->next) - cursor->table= ((TABLE_LIST*) cursor->table)->table; - } - res=mysql_union(thd,lex,c_i); - } - close_thread_tables(thd); - } - else - { - TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first; - SELECT_LEX *select_lex=&lex->select_lex; - if (!(res=open_and_lock_tables(thd,tables->next))) - { - res=mysql_select(thd,tables->next,select_lex->item_list, - select_lex->where, - select_lex->ftfunc_list, - (ORDER*) select_lex->order_list.first, - (ORDER*) select_lex->group_list.first, - select_lex->having, - (ORDER*) lex->proc_list.first, - select_lex->options | thd->options, - c_i); - } - } - if (res) - c_i->abort(); - delete c_i; - return res; -} void add_join_on(TABLE_LIST *b,Item *expr) { @@ -3055,10 +2914,8 @@ void add_join_natural(TABLE_LIST *a,TABLE_LIST *b) static bool check_dup(THD *thd,const char *db,const char *name, TABLE_LIST *tables) { - const char *thd_db=thd->db ? thd->db : any_db; for (; tables ; tables=tables->next) - if (!strcmp(name,tables->real_name) && - !strcmp(db ? db : thd_db, tables->db ? tables->db : thd_db)) + if (!strcmp(name,tables->real_name) && !strcmp(db,tables->db)) return 1; return 0; } @@ -3085,10 +2942,10 @@ bool reload_acl_and_cache(THD *thd, uint options, TABLE_LIST *tables) } if (options & (REFRESH_TABLES | REFRESH_READ_LOCK)) { - if ((options & REFRESH_READ_LOCK) && thd && ! thd->global_read_lock) + if ((options & REFRESH_READ_LOCK) && thd) { - thd->global_read_lock=1; - thread_safe_increment(global_read_lock,&LOCK_open); + if (lock_global_read_lock(thd)) + return 1; } result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables); } diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index cda1a8531df..1a39b305323 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -84,7 +84,9 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name, int2store(header + FLAGS_OFFSET, 0); int4store(header + LOG_SEQ_OFFSET, 0); packet->append(header, sizeof(header)); - int8store(buf, 4); // tell slave to skip magic number + /* We need to split the next statement because of problem with cxx */ + int4store(buf,4); // tell slave to skip magic number + int4store(buf+4,0); packet->append(buf, ROTATE_HEADER_LEN); packet->append(p,ident_len); if (my_net_write(net, (char*)packet->ptr(), packet->length())) @@ -1041,26 +1043,26 @@ static Slave_log_event* find_slave_event(IO_CACHE* log, Log_event* ev; if (!(ev = Log_event::read_log_event(log, 0))) { - my_vsnprintf(errmsg, SLAVE_ERRMSG_SIZE, - "Error reading start event in log '%s'", - (char*)log_file_name); + my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, + "Error reading start event in log '%s'", + (char*)log_file_name); return 0; } delete ev; if (!(ev = Log_event::read_log_event(log, 0))) { - my_vsnprintf(errmsg, SLAVE_ERRMSG_SIZE, - "Error reading slave event in log '%s'", - (char*)log_file_name); + my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, + "Error reading slave event in log '%s'", + (char*)log_file_name); return 0; } if (ev->get_type_code() != SLAVE_EVENT) { - my_vsnprintf(errmsg, SLAVE_ERRMSG_SIZE, - "Second event in log '%s' is not slave event", - (char*)log_file_name); + my_snprintf(errmsg, SLAVE_ERRMSG_SIZE, + "Second event in log '%s' is not slave event", + (char*)log_file_name); delete ev; return 0; } diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 0f87eaccd51..65d2674ba99 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -143,6 +143,34 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, bool distinct); static void describe_info(THD *thd, const char *info); +/* + This handles SELECT with and without UNION +*/ + +int handle_select(THD *thd, LEX *lex, select_result *result) +{ + int res; + register SELECT_LEX *select_lex = &lex->select_lex; + if (select_lex->next) + res=mysql_union(thd,lex,result); + else + res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first, + select_lex->item_list, + select_lex->where, + select_lex->ftfunc_list, + (ORDER*) select_lex->order_list.first, + (ORDER*) select_lex->group_list.first, + select_lex->having, + (ORDER*) lex->proc_list.first, + select_lex->options | thd->options, + result); + if (res && result) + result->abort(); + delete result; + return res; +} + + /***************************************************************************** ** check fields, find best join, do the select and output fields. ** mysql_select assumes that all tables are allready opened @@ -2985,7 +3013,9 @@ propagate_cond_constants(I_List<COND_CMP> *save_list,COND *and_level, Item_func_eq *func=(Item_func_eq*) cond; bool left_const= func->arguments()[0]->const_item(); bool right_const=func->arguments()[1]->const_item(); - if (!(left_const && right_const)) + if (!(left_const && right_const) && + (func->arguments()[0]->result_type() == + (func->arguments()[1]->result_type()))) { if (right_const) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 1409897a7f2..79a93da8c15 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -993,10 +993,13 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) thread_info *thd_info=new thread_info; thd_info->thread_id=tmp->thread_id; - thd_info->user=thd->strdup(tmp->user ? tmp->user : (tmp->system_thread ? - "system user" : "unauthenticated user")); - thd_info->host=thd->strdup(tmp->host ? tmp->host : (tmp->ip ? tmp->ip : - (tmp->system_thread ? "none" : "connecting host"))); + thd_info->user=thd->strdup(tmp->user ? tmp->user : + (tmp->system_thread ? + "system user" : "unauthenticated user")); + thd_info->host=thd->strdup(tmp->host ? tmp->host : + (tmp->ip ? tmp->ip : + (tmp->system_thread ? "none" : + "connecting host"))); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 072e867b569..c2f1dbaa401 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -25,21 +25,34 @@ #include "sql_select.h" -int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result *)NULL) +int mysql_union(THD *thd, LEX *lex,select_result *result) { 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"); + if (lex->select_lex.options & SELECT_DESCRIBE) + { + my_error(ER_WRONG_USAGE,MYF(0),"DESCRIBE","UNION"); + return -1; + } + + /* Fix tables--to-be-unioned-from list to point at opened tables */ + for (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; + } + /* 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; @@ -60,7 +73,6 @@ int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result * /* Create a list of items that will be in the result set */ first_table= (TABLE_LIST*) lex->select_lex.table_list.first; - if (create_insert) first_table=first_table->next; while ((item= it++)) if (item_list.push_back(item)) DBUG_RETURN(-1); @@ -96,8 +108,7 @@ int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result * if (thd->select_limit == HA_POS_ERROR) sl->options&= ~OPTION_FOUND_ROWS; - res=mysql_select(thd,(sl == &lex->select_lex) ? first_table : - (TABLE_LIST*) sl->table_list.first, + res=mysql_select(thd, (TABLE_LIST*) sl->table_list.first, sl->item_list, sl->where, sl->ftfunc_list, @@ -116,19 +127,9 @@ int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result * goto exit; } delete union_result; - if (create_insert) - result=create_insert; - else 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(); + + /* Send result to 'result' */ res =-1; - if (result) { /* Create a list of fields in the temporary table */ List_iterator<Item> it(item_list); @@ -146,9 +147,6 @@ int mysql_union(THD *thd, LEX *lex,select_result *create_insert=(select_result * item_list, NULL, ftfunc_list, order, (ORDER*) NULL, NULL, (ORDER*) NULL, thd->options, result); - if (res) - result->abort(); - delete result; } exit: diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3f143418a92..efc6f66fa0e 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1318,10 +1318,15 @@ table_to_table: select: SELECT_SYM { + Lex->sql_command= SQLCOM_SELECT; + } + select_part2; + +select_part2: + { LEX *lex=Lex; - if (lex->sql_command == SQLCOM_NONE) lex->sql_command= SQLCOM_SELECT; lex->lock_option=TL_READ; - mysql_init_select(lex); + mysql_init_select(lex); } select_options select_item_list select_into select_lock_type union @@ -2504,7 +2509,7 @@ describe: YYABORT; } opt_describe_column - | describe_command select { Select->options|= SELECT_DESCRIBE }; + | describe_command select { Lex->select_lex.options|= SELECT_DESCRIBE }; describe_command: @@ -3416,13 +3421,7 @@ union_list: mysql_new_select(lex); lex->select->linkage=UNION_TYPE; } - select - { - LEX *lex=Lex; - if (lex->sql_command == SQLCOM_SELECT) - lex->sql_command=SQLCOM_UNION_SELECT; - } - + SELECT_SYM select_part2 union_option: /* empty */ {} |