summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSinisa@sinisa.nasamreza.org <>2003-01-21 15:54:36 +0200
committerSinisa@sinisa.nasamreza.org <>2003-01-21 15:54:36 +0200
commit74f478f9a5571556eacf0a2922d32f282520d301 (patch)
tree12b636bd4e539bd743ac707375d81f309509f79c /sql
parentfe5e05cd90d4c07b815b3250164cf739039fa48a (diff)
parentff4ef4c4e7d51421cfde0016148eda935f65cd4e (diff)
downloadmariadb-git-74f478f9a5571556eacf0a2922d32f282520d301.tar.gz
Merge sinisa@work.mysql.com:/home/bk/mysql-4.0
into sinisa.nasamreza.org:/mnt/work/mysql-4.0
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_innodb.cc10
-rw-r--r--sql/log_event.cc10
-rw-r--r--sql/slave.cc21
-rw-r--r--sql/sql_acl.cc1
-rw-r--r--sql/sql_db.cc23
-rw-r--r--sql/sql_parse.cc3
-rw-r--r--sql/sql_select.cc98
-rw-r--r--sql/sql_table.cc9
8 files changed, 113 insertions, 62 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b4fe6130e9b..b1cb45be6b3 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -4166,6 +4166,16 @@ ha_innobase::store_lock(
lock_type = TL_WRITE_ALLOW_WRITE;
}
+ /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
+ MySQL would use the lock TL_READ_NO_INSERT on t2, and that
+ would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
+ to t2. Convert the lock to a normal read lock to allow
+ concurrent inserts to t2. */
+
+ if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables) {
+ lock_type = TL_READ;
+ }
+
lock.type=lock_type;
}
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 45f54e420de..e243a953c63 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -1702,10 +1702,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
- thd->query = (char*)query;
thd->set_time((time_t)when);
thd->current_tablenr = 0;
+ thd->query_length= q_len;
VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query = (char*)query;
thd->query_id = query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->query_error = 0; // clear error
@@ -1760,7 +1761,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
else
{
// master could be inconsistent, abort and tell DBA to check/fix it
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db = thd->query = 0;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->variables.convert_set = 0;
close_thread_tables(thd);
free_root(&thd->mem_root,0);
@@ -1768,7 +1771,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
}
}
thd->db= 0; // prevent db from being freed
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query= 0; // just to be sure
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
// assume no convert for next query unless set explictly
thd->variables.convert_set = 0;
close_thread_tables(thd);
@@ -1816,7 +1821,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
{
init_sql_alloc(&thd->mem_root, 8192,0);
thd->db = rewrite_db((char*)db);
- thd->query = 0;
+ DBUG_ASSERT(thd->query == 0);
+ thd->query = 0; // Should not be needed
thd->query_error = 0;
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
diff --git a/sql/slave.cc b/sql/slave.cc
index b8689a28a54..30c345f8030 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -867,6 +867,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
const char* table_name)
{
ulong packet_len = my_net_read(net); // read create table statement
+ char *query;
Vio* save_vio;
HA_CHECK_OPT check_opt;
TABLE_LIST tables;
@@ -886,15 +887,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db,
return 1;
}
thd->command = COM_TABLE_DUMP;
- thd->query = sql_alloc(packet_len + 1);
- if (!thd->query)
+ /* Note that we should not set thd->query until the area is initalized */
+ if (!(query = sql_alloc(packet_len + 1)))
{
sql_print_error("create_table_from_dump: out of memory");
net_printf(&thd->net, ER_GET_ERRNO, "Out of memory");
return 1;
}
- memcpy(thd->query, net->read_pos, packet_len);
- thd->query[packet_len] = 0;
+ memcpy(query, net->read_pos, packet_len);
+ query[packet_len]= 0;
+ thd->query_length= packet_len;
+ /*
+ We make the following lock in an attempt to ensure that the compiler will
+ not rearrange the code so that thd->query is set too soon
+ */
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query= query;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->current_tablenr = 0;
thd->query_error = 0;
thd->net.no_send_ok = 1;
@@ -2049,7 +2058,9 @@ err:
// print the current replication position
sql_print_error("Slave I/O thread exiting, read up to log '%s', position %s",
IO_RPL_LOG_NAME, llstr(mi->master_log_pos,llbuff));
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (mysql)
{
mc_mysql_close(mysql);
@@ -2183,7 +2194,9 @@ the slave SQL thread with \"SLAVE START\". We stopped at log \
RPL_LOG_NAME, llstr(rli->master_log_pos,llbuff));
err:
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query = thd->db = 0; // extra safety
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->proc_info = "Waiting for slave mutex on exit";
pthread_mutex_lock(&rli->run_lock);
DBUG_ASSERT(rli->slave_running == 1); // tracking buffer overrun
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index a9bb22fb8f7..9091784bbf3 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2322,6 +2322,7 @@ my_bool grant_init(THD *org_thd)
if (t_table->file->index_first(t_table->record[0]))
{
t_table->file->index_end();
+ return_val= 0;
goto end_unlock;
}
grant_option= TRUE;
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index e805cf74f19..4cb46c00bed 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -78,9 +78,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
if (!thd->query)
{
/* The client used the old obsolete mysql_create_db() call */
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"create database `", db, "`",
- NullS) - path);
+ thd->query_length= (uint) (strxmov(path,"create database `", db, "`",
+ NullS) - path);
+ thd->query= path;
}
{
mysql_update_log.write(thd,thd->query, thd->query_length);
@@ -92,8 +92,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent)
}
if (thd->query == path)
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query= 0;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
}
send_ok(&thd->net, result);
}
@@ -167,9 +168,10 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
if (!thd->query)
{
- thd->query = path;
- thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)-
- path);
+ thd->query_length= (uint) (strxmov(path,"drop database `", db, "`",
+ NullS)-
+ path);
+ thd->query= path;
}
mysql_update_log.write(thd, thd->query, thd->query_length);
if (mysql_bin_log.is_open())
@@ -179,8 +181,9 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
if (thd->query == path)
{
- thd->query = 0; // just in case
- thd->query_length = 0;
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ thd->query= 0;
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
}
send_ok(&thd->net,(ulong) deleted);
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 5bf3a1c0bcd..0b6170f1e37 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -852,7 +852,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
goto err;
}
net_flush(&thd->net);
- if ((error = table->file->dump(thd,fd)))
+ if ((error= table->file->dump(thd,fd)))
my_error(ER_GET_ERRNO, MYF(0));
err:
@@ -958,7 +958,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
tbl_name[tbl_len] = 0;
if (mysql_table_dump(thd, db, tbl_name, -1))
send_error(&thd->net); // dump to NET
-
break;
}
case COM_CHANGE_USER:
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 237197ba6be..e811c55ed1b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+/* Copyright (C) 2000-2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1009,7 +1009,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
table_map found_const_table_map,all_table_map;
TABLE **table_vector;
JOIN_TAB *stat,*stat_end,*s,**stat_ref;
- SQL_SELECT *select;
KEYUSE *keyuse,*start_keyuse;
table_map outer_join=0;
JOIN_TAB *stat_vector[MAX_TABLES+1];
@@ -1021,7 +1020,6 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
table_vector=(TABLE**) join->thd->alloc(sizeof(TABLE*)*(table_count*2));
if (!stat || !stat_ref || !table_vector)
DBUG_RETURN(1); // Eom /* purecov: inspected */
- select=0;
join->best_ref=stat_vector;
@@ -1205,7 +1203,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
{ // Found everything for ref.
int tmp;
ref_changed = 1;
- s->type=JT_CONST;
+ s->type= JT_CONST;
join->const_table_map|=table->map;
set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse,
@@ -1256,23 +1254,44 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->const_keys)
{
ha_rows records;
- if (!select)
- select=make_select(s->table, found_const_table_map,
- found_const_table_map,
- and_conds(conds,s->on_expr),&error);
- records=get_quick_record_count(select,s->table, s->const_keys,
- join->row_limit);
+ SQL_SELECT *select;
+ select= make_select(s->table, found_const_table_map,
+ found_const_table_map,
+ s->on_expr ? s->on_expr : conds,
+ &error);
+ records= get_quick_record_count(select,s->table, s->const_keys,
+ join->row_limit);
s->quick=select->quick;
s->needed_reg=select->needed_reg;
select->quick=0;
+ if (records == 0 && s->table->reginfo.impossible_range)
+ {
+ /*
+ Impossible WHERE or ON expression
+ In case of ON, we mark that the we match one empty NULL row.
+ In case of WHERE, don't set found_const_table_map to get the
+ caller to abort with a zero row result.
+ */
+ join->const_table_map|= s->table->map;
+ set_position(join,const_count++,s,(KEYUSE*) 0);
+ s->type= JT_CONST;
+ if (s->on_expr)
+ {
+ /* Generate empty row */
+ s->info= "Impossible ON condition";
+ found_const_table_map|= s->table->map;
+ s->type= JT_CONST;
+ mark_as_null_row(s->table); // All fields are NULL
+ }
+ }
if (records != HA_POS_ERROR)
{
s->found_records=records;
s->read_time= (ha_rows) (s->quick ? s->quick->read_time : 0.0);
}
+ delete select;
}
}
- delete select;
/* Find best combination and return it */
join->join_tab=stat;
@@ -2367,7 +2386,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
keyparts != keyinfo->key_parts)
j->type=JT_REF; /* Must read with repeat */
else if (ref_key == j->ref.key_copy)
- { /* Should never be reached */
+ {
/*
This happen if we are using a constant expression in the ON part
of an LEFT JOIN.
@@ -7333,36 +7352,39 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
if (tab->info)
item_list.push_back(new Item_string(tab->info,strlen(tab->info)));
- else if (tab->select)
+ else
{
- if (tab->use_quick == 2)
+ if (tab->select)
{
- sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
- tab->keys);
- buff_ptr=strend(buff_ptr);
+ if (tab->use_quick == 2)
+ {
+ sprintf(buff_ptr,"; Range checked for each record (index map: %u)",
+ tab->keys);
+ buff_ptr=strend(buff_ptr);
+ }
+ else
+ buff_ptr=strmov(buff_ptr,"; Using where");
}
- else
- buff_ptr=strmov(buff_ptr,"; Using where");
- }
- if (key_read)
- buff_ptr= strmov(buff_ptr,"; Using index");
- if (table->reginfo.not_exists_optimize)
- buff_ptr= strmov(buff_ptr,"; Not exists");
- if (need_tmp_table)
- {
- need_tmp_table=0;
- buff_ptr= strmov(buff_ptr,"; Using temporary");
- }
- if (need_order)
- {
- need_order=0;
- buff_ptr= strmov(buff_ptr,"; Using filesort");
+ if (key_read)
+ buff_ptr= strmov(buff_ptr,"; Using index");
+ if (table->reginfo.not_exists_optimize)
+ buff_ptr= strmov(buff_ptr,"; Not exists");
+ if (need_tmp_table)
+ {
+ need_tmp_table=0;
+ buff_ptr= strmov(buff_ptr,"; Using temporary");
+ }
+ if (need_order)
+ {
+ need_order=0;
+ buff_ptr= strmov(buff_ptr,"; Using filesort");
+ }
+ if (distinct && test_all_bits(used_tables,thd->used_tables))
+ buff_ptr= strmov(buff_ptr,"; Distinct");
+ if (buff_ptr == buff)
+ buff_ptr+= 2;
+ item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2));
}
- if (distinct && test_all_bits(used_tables,thd->used_tables))
- buff_ptr= strmov(buff_ptr,"; Distinct");
- if (buff_ptr == buff)
- buff_ptr+= 2;
- item_list.push_back(new Item_string(buff+2,(uint) (buff_ptr - buff)-2));
// For next iteration
used_tables|=table->map;
if (result->send_data(item_list))
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 266bf8aefa9..c04b4871b4d 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1771,12 +1771,9 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
/* We changed a temporary table */
if (error)
{
- /*
- * The following function call will also free a
- * new_table pointer.
- * Therefore, here new_table pointer is not free'd as it is
- * free'd in close_temporary() which is called by by the
- * close_temporary_table() function.
+ /*
+ The following function call will free the new_table pointer,
+ in close_temporary_table(), so we can safely directly jump to err
*/
close_temporary_table(thd,new_db,tmp_name);
goto err;