diff options
author | monty@donna.mysql.com <> | 2000-08-29 12:31:01 +0300 |
---|---|---|
committer | monty@donna.mysql.com <> | 2000-08-29 12:31:01 +0300 |
commit | 066d55c0c09d589d17bf466682134af50cb59e14 (patch) | |
tree | 8c9e3c031400ac400edcf6561fe51f4bdbd69369 /sql | |
parent | d564acf14eb07cefedf0218c90fd109c61dc6e2f (diff) | |
download | mariadb-git-066d55c0c09d589d17bf466682134af50cb59e14.tar.gz |
Bug fixes for 3.23.23
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 15 | ||||
-rw-r--r-- | sql/ha_heap.h | 5 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/handler.h | 2 | ||||
-rw-r--r-- | sql/lock.cc | 22 | ||||
-rw-r--r-- | sql/mini_client.cc | 5 | ||||
-rw-r--r-- | sql/mysql_priv.h | 5 | ||||
-rw-r--r-- | sql/mysqld.cc | 15 | ||||
-rw-r--r-- | sql/opt_range.cc | 12 | ||||
-rw-r--r-- | sql/sql_base.cc | 33 | ||||
-rw-r--r-- | sql/sql_parse.cc | 12 | ||||
-rw-r--r-- | sql/sql_select.cc | 8 | ||||
-rw-r--r-- | sql/table.h | 1 |
13 files changed, 96 insertions, 43 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 989497cee6e..591ca0bc813 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -251,6 +251,21 @@ int ha_heap::rename_table(const char * from, const char * to) } +ha_rows ha_heap::records_in_range(int inx, + const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag) +{ + KEY *pos=table->key_info+inx; + if (start_key_len != end_key_len || + start_key_len != pos->key_length || + start_search_flag != HA_READ_KEY_EXACT || + end_search_flag != HA_READ_KEY_EXACT) + return HA_POS_ERROR; // Can't only use exact keys + return 10; // Good guess +} + /* We can just delete the heap on creation */ int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info) diff --git a/sql/ha_heap.h b/sql/ha_heap.h index acbc0975f1e..b56ee84822f 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -65,7 +65,10 @@ class ha_heap: public handler int reset(void); int external_lock(THD *thd, int lock_type); int delete_all_rows(void); - + ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len, + enum ha_rkey_function start_search_flag, + const byte *end_key,uint end_key_len, + enum ha_rkey_function end_search_flag); int delete_table(const char *from); int rename_table(const char * from, const char * to); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); diff --git a/sql/handler.cc b/sql/handler.cc index 592861e176b..437b11be5bb 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -317,8 +317,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked) } if (!error) { - - if (!(ref=(byte*) my_malloc(ALIGN_SIZE(ref_length)*2,MYF(0)))) + if (!(ref=(byte*) alloc_root(&table->mem_root, + ALIGN_SIZE(ref_length)*2))) { close(); error=HA_ERR_OUT_OF_MEM; diff --git a/sql/handler.h b/sql/handler.h index 67fd99c71d7..08bf355b60e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -200,7 +200,7 @@ public: create_time(0), check_time(0), update_time(0), mean_rec_length(0), ft_handler(0) {} - virtual ~handler(void) { my_free((char*) ref,MYF(MY_ALLOW_ZERO_PTR)); } + virtual ~handler(void) {} int ha_open(const char *name, int mode, int test_if_locked); void update_timestamp(byte *record); void update_auto_increment(); diff --git a/sql/lock.cc b/sql/lock.cc index a2e4daa4590..eba1851bae0 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -407,15 +407,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) TABLE *table; char key[MAX_DBKEY_LENGTH]; uint key_length; - key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)-key)+ - 1; + DBUG_ENTER("lock_table_name"); + + key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name) + -key)+ 1; /* Only insert the table if we haven't insert it already */ for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; table ; table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) if (table->in_use == thd) - return 0; + DBUG_RETURN(0); /* Create a table entry with the right key and with an old refresh version */ /* Note that we must use my_malloc() here as this is freed by the table @@ -423,17 +425,18 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list) if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length, MYF(MY_WME | MY_ZEROFILL)))) - return -1; + DBUG_RETURN(-1); memcpy((table->table_cache_key= (char*) (table+1)), key, key_length); table->key_length=key_length; table->in_use=thd; + table->locked_by_name=1; table_list->table=table; if (hash_insert(&open_cache, (byte*) table)) - return -1; + DBUG_RETURN(-1); if (remove_table_from_cache(thd, table_list->db, table_list->name)) - return 1; // Table is in use - return 0; + DBUG_RETURN(1); // Table is in use + DBUG_RETURN(0); } void unlock_table_name(THD *thd, TABLE_LIST *table_list) @@ -446,7 +449,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list) { for ( ; table_list ; table_list=table_list->next) { - if (table_list->table && table_is_used(table_list->table)) + if (table_list->table && table_is_used(table_list->table,0)) return 1; } return 0; // All tables are locked @@ -456,6 +459,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list) bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) { bool result=0; + DBUG_ENTER("wait_for_locked_table_names"); while (locked_named_table(thd,table_list)) { @@ -467,5 +471,5 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list) wait_for_refresh(thd); pthread_mutex_lock(&LOCK_open); } - return result; + DBUG_RETURN(result); } diff --git a/sql/mini_client.cc b/sql/mini_client.cc index b9e66911475..90024f1ff47 100644 --- a/sql/mini_client.cc +++ b/sql/mini_client.cc @@ -225,7 +225,8 @@ static void mc_free_old_query(MYSQL *mysql) * Base version coded by Steve Bernacki, Jr. <steve@navinet.net> *****************************************************************************/ -static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to) +static int mc_sock_connect(my_socket s, const struct sockaddr *name, + uint namelen, uint to) { #if defined(__WIN__) return connect(s, (struct sockaddr*) name, namelen); @@ -451,7 +452,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user, uint port, const char *unix_socket,uint client_flag) { char buff[100],*end,*host_info; - int sock; + my_socket sock; ulong ip_addr; struct sockaddr_in sock_addr; uint pkt_length; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index fa61102fb57..7e3186defd3 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -319,10 +319,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias, TABLE *find_locked_table(THD *thd, const char *db,const char *table_name); bool reopen_table(TABLE *table,bool locked=0); bool reopen_tables(THD *thd,bool get_locks,bool in_refresh); -void close_old_data_files(THD *thd, TABLE *table, bool abort_locks); +void close_old_data_files(THD *thd, TABLE *table, bool abort_locks, + bool send_refresh); bool close_data_tables(THD *thd,const char *db, const char *table_name); bool wait_for_tables(THD *thd); -bool table_is_used(TABLE *table); +bool table_is_used(TABLE *table, bool wait_for_name_lock); bool drop_locked_tables(THD *thd,const char *db, const char *table_name); void abort_locked_tables(THD *thd,const char *db, const char *table_name); Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index bf0a88bb702..fbfa18ce114 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -2407,6 +2407,12 @@ static void print_version(void) server_version,SYSTEM_TYPE,MACHINE_TYPE); } +static void use_help(void) +{ + print_version(); + printf("Use %s --help for a list of available options\n",my_progname); +} + static void usage(void) { print_version(); @@ -2621,7 +2627,7 @@ static void get_options(int argc,char **argv) case 'O': if (set_changeable_var(optarg, changeable_vars)) { - usage(); + use_help(); exit(1); } break; @@ -2666,7 +2672,8 @@ static void get_options(int argc,char **argv) opt_noacl=1; else { - usage(); + fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg); + use_help(); exit(1); } break; @@ -2910,7 +2917,7 @@ static void get_options(int argc,char **argv) default: fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c); - usage(); + use_help(); exit(1); } } @@ -2920,7 +2927,7 @@ static void get_options(int argc,char **argv) if (argc != optind) { fprintf(stderr,"%s: Too many parameters\n",my_progname); - usage(); + use_help(); exit(1); } fix_paths(); diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 4f1abf9b685..25ee26dbdbd 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -14,6 +14,16 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/* + TODO: + Fix that MAYBE_KEY are stored in the tree so that we can detect use + of full hash keys for queries like: + + select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and kws.keyword_id in (204,205); + +*/ + + #ifdef __GNUC__ #pragma implementation // gcc: Class implementation @@ -557,7 +567,7 @@ SEL_ARG *SEL_ARG::clone_tree() ** Returns: ** -1 if impossible select ** 0 if can't use quick_select -** 1 if found usably range +** 1 if found usable range ** Updates the following in the select parameter: ** needed_reg ; Bits for keys with may be used if all prev regs are read ** quick ; Parameter to use when reading records. diff --git a/sql/sql_base.cc b/sql/sql_base.cc index e6468890ed6..1ccd009de07 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -582,9 +582,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh, thd->mysys_var->current_cond= &COND_refresh; thd->proc_info="Flushing tables"; pthread_mutex_unlock(&thd->mysys_var->mutex); - VOID(pthread_cond_broadcast(&COND_refresh)); // If one flush is locked - close_old_data_files(thd,thd->open_tables,1); + close_old_data_files(thd,thd->open_tables,1,1); bool found=1; /* Wait until all threads has closed all the tables we had locked */ DBUG_PRINT("info", ("Waiting for others threads to close their open tables")); @@ -921,7 +920,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name, ** There is a refresh in progress for this table ** Wait until the table is freed or the thread is killed. */ - close_old_data_files(thd,thd->open_tables,0); + close_old_data_files(thd,thd->open_tables,0,0); if (table->in_use != thd) wait_for_refresh(thd); else @@ -1216,9 +1215,11 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh) abort_locks is set if called from flush_tables. */ -void close_old_data_files(THD *thd, TABLE *table, bool abort_locks) +void close_old_data_files(THD *thd, TABLE *table, bool abort_locks, + bool send_refresh) { - bool found=0; + DBUG_ENTER("close_old_data_files"); + bool found=send_refresh; for (; table ; table=table->next) { if (table->version != refresh_version) @@ -1241,6 +1242,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks) } if (found) VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh + DBUG_VOID_RETURN; } @@ -1250,17 +1252,19 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks) if the table is closed */ -bool table_is_used(TABLE *table) +bool table_is_used(TABLE *table, bool wait_for_name_lock) { do { char *key= table->table_cache_key; uint key_length=table->key_length; - for (TABLE *search=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ; + for (TABLE *search=(TABLE*) hash_search(&open_cache, + (byte*) key,key_length) ; search ; search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length)) { if (search->locked_by_flush || + search->locked_by_name && wait_for_name_lock || search->db_stat && search->version < refresh_version) return 1; // Table is used } @@ -1278,19 +1282,14 @@ bool wait_for_tables(THD *thd) thd->proc_info="Waiting for tables"; pthread_mutex_lock(&LOCK_open); - thd->some_tables_deleted=0; - close_old_data_files(thd,thd->open_tables,0); - if (dropping_tables) - { - (void) pthread_cond_broadcast(&COND_refresh); // Signal to refresh/delete - (void) pthread_cond_wait(&COND_refresh,&LOCK_open); - } - - while (table_is_used(thd->open_tables) && ! thd->killed) + while (!thd->killed) { + thd->some_tables_deleted=0; + close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); + if (!table_is_used(thd->open_tables,1)) + break; (void) pthread_cond_wait(&COND_refresh,&LOCK_open); } - if (thd->killed) result= 1; // aborted else diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8b7e16709c0..97e67127fd0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1170,9 +1170,8 @@ mysql_execute_command(void) #endif case SQLCOM_REPAIR: { - if (!tables->db) - tables->db=thd->db; - if (check_table_access(thd,SELECT_ACL | INSERT_ACL, tables)) + 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; @@ -1695,6 +1694,10 @@ error: ** Get the user (global) and database privileges for all used tables ** Returns true (error) if we can't get the privileges and we don't use ** table/column grants. +** The idea of EXTRA_ACL is that one will be granted access to the table if +** one has the asked privilege on any column combination of the table; For +** example to be able to check a table one needs to have SELECT privilege on +** any column of the table. ****************************************************************************/ bool @@ -1760,7 +1763,8 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables) TABLE_LIST *org_tables=tables; for (; tables ; tables=tables->next) { - if ((thd->master_access & want_access) == want_access && thd->db) + if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) && + thd->db) tables->grant.privilege= want_access; else if (tables->db && tables->db == thd->db) { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index c779b9f555a..1eafa22aa1b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -800,6 +800,14 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, if ((s->on_expr=tables->on_expr)) { // table->maybe_null=table->outer_join=1; // Mark for send fields + if (!table->file->records) + { // Empty table + s->key_dependent=s->dependent=0; + s->type=JT_SYSTEM; + const_table_map|=table->map; + set_position(join,const_count++,s,(KEYUSE*) 0); + continue; + } s->key_dependent=s->dependent= s->on_expr->used_tables() & ~(table->map); s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map; diff --git a/sql/table.h b/sql/table.h index 7fe3e5de601..198e0d6e801 100644 --- a/sql/table.h +++ b/sql/table.h @@ -91,6 +91,7 @@ struct st_table { my_bool crypted; my_bool db_low_byte_first; /* Portable row format */ my_bool locked_by_flush; + my_bool locked_by_name; Field *next_number_field, /* Set if next_number is activated */ *found_next_number_field, /* Set on open */ *rowid_field; |