mirror of
https://github.com/MariaDB/server.git
synced 2026-05-09 16:44:29 +02:00
Bug fixes for 3.23.23
myisam/mi_debug.c: ***MISSING WEAVE*** Docs/internals.texi: Added coding guidelines Docs/manual.texi: Changelog update + Win32 -> Windows client/mysql.cc: Changed --no-named-commands to be on by default client/mysqlimport.c: Bug fix include/config-win.h: Update of supported functions include/global.h: Removed compiler warning libmysql/libmysql.c: Fix for Ia64 myisam/ChangeLog: Changelog myisam/Makefile.am: Added file mi_dbug.c myisam/ft_stopwords.c: Fix for Ia64 myisam/mi_delete_table.c: Extra debugging myisam/mi_rename.c: Extra debugging myisam/mi_rnext.c: Fixed bug with MIN and concurrent insert myisam/mi_rprev.c: Fixed bug with MAX and concurrent insert myisam/mi_search.c: Fixed bug with DECIMAL/NUMERIC keys myisam/myisamdef.h: Extra debugging scripts/make_binary_distribution.sh: Added thread safe mysql library sql/ha_heap.cc: Fix of HEAP bug with range keys sql/ha_heap.h: Fix of HEAP bug with range keys sql/handler.cc: Optimizing sql/handler.h: Optimizing sql/lock.cc: More DEBUG + fix of RENAME bug sql/mini_client.cc: Fix for Ia64 sql/mysql_priv.h: Fix for name locks sql/mysqld.cc: Shorter message if wrong options sql/opt_range.cc: Added TODO sql/sql_base.cc: Fix for DROP TABLE sql/sql_parse.cc: Fix of permission checking for CHECK TABLE sql/sql_select.cc: Fix of using LEFT JOIN with empty table sql/table.h: Fix for name locks tests/fork_test.pl: Fixed typo
This commit is contained in:
parent
844c92364e
commit
52046a7ba3
33 changed files with 909 additions and 211 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
22
sql/lock.cc
22
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue