Commit 81ef01f9 authored by unknown's avatar unknown

Merge sinisa@work.mysql.com:/home/bk/mysql-4.0

into sinisa.nasamreza.org:/mnt/work/mysql-4.0

parents 8668c41c 92d93cae
...@@ -153,6 +153,13 @@ C_MODE_END ...@@ -153,6 +153,13 @@ C_MODE_END
#undef HAVE_INITGROUPS #undef HAVE_INITGROUPS
#endif #endif
/* gcc/egcs issues */
#if defined(__GNUC) && defined(__EXCEPTIONS)
#error "Please add -fno-exceptions to CXXFLAGS and reconfigure/recompile"
#endif
/* Fix a bug in gcc 2.8.0 on IRIX 6.2 */ /* Fix a bug in gcc 2.8.0 on IRIX 6.2 */
#if SIZEOF_LONG == 4 && defined(__LONG_MAX__) #if SIZEOF_LONG == 4 && defined(__LONG_MAX__)
#undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */ #undef __LONG_MAX__ /* Is a longlong value in gcc 2.8.0 ??? */
......
...@@ -581,9 +581,13 @@ extern int pthread_dummy(int); ...@@ -581,9 +581,13 @@ extern int pthread_dummy(int);
#define THREAD_NAME_SIZE 10 #define THREAD_NAME_SIZE 10
#if defined(__ia64__) #if defined(__ia64__)
#define DEFAULT_THREAD_STACK (128*1024) /*
MySQL can survive with 32K, but some glibc libraries require > 128K stack
To resolve hostnames
*/
#define DEFAULT_THREAD_STACK (192*1024L)
#else #else
#define DEFAULT_THREAD_STACK (64*1024) #define DEFAULT_THREAD_STACK (192*1024L)
#endif #endif
struct st_my_thread_var struct st_my_thread_var
......
...@@ -135,7 +135,7 @@ btr_page_insert_fits( ...@@ -135,7 +135,7 @@ btr_page_insert_fits(
/****************************************************************** /******************************************************************
Gets the root node of a tree and x-latches it. */ Gets the root node of a tree and x-latches it. */
static
page_t* page_t*
btr_root_get( btr_root_get(
/*=========*/ /*=========*/
...@@ -146,9 +146,6 @@ btr_root_get( ...@@ -146,9 +146,6 @@ btr_root_get(
ulint space; ulint space;
ulint root_page_no; ulint root_page_no;
page_t* root; page_t* root;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_X_LOCK)
|| mtr_memo_contains(mtr, dict_tree_get_lock(tree), MTR_MEMO_S_LOCK));
space = dict_tree_get_space(tree); space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree); root_page_no = dict_tree_get_page(tree);
...@@ -334,8 +331,6 @@ btr_page_alloc( ...@@ -334,8 +331,6 @@ btr_page_alloc(
page_t* new_page; page_t* new_page;
ulint new_page_no; ulint new_page_no;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
if (tree->type & DICT_IBUF) { if (tree->type & DICT_IBUF) {
return(btr_page_alloc_for_ibuf(tree, mtr)); return(btr_page_alloc_for_ibuf(tree, mtr));
......
...@@ -3180,7 +3180,7 @@ btr_store_big_rec_extern_fields( ...@@ -3180,7 +3180,7 @@ btr_store_big_rec_extern_fields(
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree), ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(data), ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX)); MTR_MEMO_PAGE_X_FIX));
ut_a(index->type & DICT_CLUSTERED); ut_a(index->type & DICT_CLUSTERED);
...@@ -3315,7 +3315,13 @@ void ...@@ -3315,7 +3315,13 @@ void
btr_free_externally_stored_field( btr_free_externally_stored_field(
/*=============================*/ /*=============================*/
dict_index_t* index, /* in: index of the data, the index dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */ tree MUST be X-latched; if the tree
height is 1, then also the root page
must be X-latched! (this is relevant
in the case this function is called
from purge where 'data' is located on
an undo log page, not an index
page) */
byte* data, /* in: internally stored data byte* data, /* in: internally stored data
+ reference to the externally + reference to the externally
stored part */ stored part */
......
...@@ -55,6 +55,15 @@ UNIQUE definition on secondary indexes when we decide if we can use the ...@@ -55,6 +55,15 @@ UNIQUE definition on secondary indexes when we decide if we can use the
insert buffer to speed up inserts */ insert buffer to speed up inserts */
#define BTR_IGNORE_SEC_UNIQUE 2048 #define BTR_IGNORE_SEC_UNIQUE 2048
/******************************************************************
Gets the root node of a tree and x-latches it. */
page_t*
btr_root_get(
/*=========*/
/* out: root page, x-latched */
dict_tree_t* tree, /* in: index tree */
mtr_t* mtr); /* in: mtr */
/****************************************************************** /******************************************************************
Gets a buffer page and declares its latching order level. */ Gets a buffer page and declares its latching order level. */
UNIV_INLINE UNIV_INLINE
......
...@@ -507,7 +507,13 @@ void ...@@ -507,7 +507,13 @@ void
btr_free_externally_stored_field( btr_free_externally_stored_field(
/*=============================*/ /*=============================*/
dict_index_t* index, /* in: index of the data, the index dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */ tree MUST be X-latched; if the tree
height is 1, then also the root page
must be X-latched! (this is relevant
in the case this function is called
from purge where 'data' is located on
an undo log page, not an index
page) */
byte* data, /* in: internally stored data byte* data, /* in: internally stored data
+ reference to the externally + reference to the externally
stored part */ stored part */
......
...@@ -429,7 +429,18 @@ row_purge_upd_exist_or_extern( ...@@ -429,7 +429,18 @@ row_purge_upd_exist_or_extern(
index = dict_table_get_first_index(node->table); index = dict_table_get_first_index(node->table);
mtr_x_lock(dict_tree_get_lock(index->tree), &mtr); mtr_x_lock(dict_tree_get_lock(index->tree), &mtr);
/* NOTE: we must also acquire an X-latch to the
root page of the tree. We will need it when we
free pages from the tree. If the tree is of height 1,
the tree X-latch does NOT protect the root page,
because it is also a leaf page. Since we will have a
latch on an undo log page, we would break the
latching order if we would only later latch the
root page of such a tree! */
btr_root_get(index->tree, &mtr);
/* We assume in purge of externally stored fields /* We assume in purge of externally stored fields
that the space id of the undo log record is 0! */ that the space id of the undo log record is 0! */
......
...@@ -1814,8 +1814,12 @@ srv_conc_enter_innodb( ...@@ -1814,8 +1814,12 @@ srv_conc_enter_innodb(
/* Go to wait for the event; when a thread leaves InnoDB it will /* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */ release this thread */
trx->op_info = "waiting in InnoDB queue";
os_event_wait(slot->event); os_event_wait(slot->event);
trx->op_info = "";
os_fast_mutex_lock(&srv_conc_mutex); os_fast_mutex_lock(&srv_conc_mutex);
srv_conc_n_waiting_threads--; srv_conc_n_waiting_threads--;
......
...@@ -1517,10 +1517,10 @@ trx_print( ...@@ -1517,10 +1517,10 @@ trx_print(
#ifdef UNIV_LINUX #ifdef UNIV_LINUX
buf += sprintf(buf, ", process no %lu", trx->mysql_process_no); buf += sprintf(buf, ", process no %lu", trx->mysql_process_no);
#else #endif
buf += sprintf(buf, ", OS thread id %lu", buf += sprintf(buf, ", OS thread id %lu",
os_thread_pf(trx->mysql_thread_id)); os_thread_pf(trx->mysql_thread_id));
#endif
if (ut_strlen(trx->op_info) > 0) { if (ut_strlen(trx->op_info) > 0) {
buf += sprintf(buf, " %s", trx->op_info); buf += sprintf(buf, " %s", trx->op_info);
} }
......
...@@ -129,7 +129,7 @@ int main(int argc, char **argv) ...@@ -129,7 +129,7 @@ int main(int argc, char **argv)
char buff[22],buff2[22]; char buff[22],buff2[22];
if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO) if (!(check_param.testflag & T_SILENT) || check_param.testflag & T_INFO)
puts("\n---------\n"); puts("\n---------\n");
printf("\nTotal of all %d ISAM-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff), printf("\nTotal of all %d MyISAM-files:\nData records: %9s Deleted blocks: %9s\n",check_param.total_files,llstr(check_param.total_records,buff),
llstr(check_param.total_deleted,buff2)); llstr(check_param.total_deleted,buff2));
} }
free_defaults(default_argv); free_defaults(default_argv);
...@@ -328,7 +328,7 @@ static void usage(void) ...@@ -328,7 +328,7 @@ static void usage(void)
print_version(); print_version();
puts("By Monty, for your professional use"); puts("By Monty, for your professional use");
puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n"); puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
puts("Description, check and repair of ISAM tables."); puts("Description, check and repair of MyISAM tables.");
puts("Used without options all tables on the command will be checked for errors"); puts("Used without options all tables on the command will be checked for errors");
printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname); printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname);
puts("\nGlobal options:\n\ puts("\nGlobal options:\n\
...@@ -1674,7 +1674,7 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...) ...@@ -1674,7 +1674,7 @@ void mi_check_print_error(MI_CHECK *param, const char *fmt,...)
if (!param->warning_printed && !param->error_printed) if (!param->warning_printed && !param->error_printed)
{ {
if (param->testflag & T_SILENT) if (param->testflag & T_SILENT)
fprintf(stderr,"%s: ISAM file %s\n",my_progname,param->isam_file_name); fprintf(stderr,"%s: MyISAM file %s\n",my_progname,param->isam_file_name);
param->out_flag|= O_DATA_LOST; param->out_flag|= O_DATA_LOST;
} }
param->error_printed|=1; param->error_printed|=1;
......
...@@ -258,7 +258,7 @@ t3 CREATE TABLE `t3` ( ...@@ -258,7 +258,7 @@ t3 CREATE TABLE `t3` (
`othr` int(11) NOT NULL default '0' `othr` int(11) NOT NULL default '0'
) TYPE=MRG_MyISAM UNION=(t1,t2) ) TYPE=MRG_MyISAM UNION=(t1,t2)
drop table t3,t2,t1; drop table t3,t2,t1;
create table t1 (a int not null) type=merge; create table t1 (a int not null, key(a)) type=merge;
select * from t1; select * from t1;
a a
drop table t1; drop table t1;
...@@ -536,7 +536,7 @@ INSERT INTO t2 VALUES (1,2), (2,2); ...@@ -536,7 +536,7 @@ INSERT INTO t2 VALUES (1,2), (2,2);
CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2); CREATE TABLE t ( a int(11) NOT NULL default '0', b int(11) NOT NULL default '0', KEY a (a,b)) TYPE=MRG_MyISAM UNION=(t1,t2);
select max(b) from t where a = 2; select max(b) from t where a = 2;
max(b) max(b)
NULL 2
select max(b) from t1 where a = 2; select max(b) from t1 where a = 2;
max(b) max(b)
1 1
......
...@@ -73,3 +73,39 @@ b ifnull(t2.b,"this is null") ...@@ -73,3 +73,39 @@ b ifnull(t2.b,"this is null")
NULL this is null NULL this is null
NULL this is null NULL this is null
drop table t1; drop table t1;
CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL);
INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55";
UPDATE t1 SET d=1/NULL;
UPDATE t1 SET d=NULL;
INSERT INTO t1 (a) values (null);
Column 'a' cannot be null
INSERT INTO t1 (a) values (1/null);
Column 'a' cannot be null
INSERT INTO t1 (a) values (null),(null);
INSERT INTO t1 (b) values (null);
Column 'b' cannot be null
INSERT INTO t1 (b) values (1/null);
Column 'b' cannot be null
INSERT INTO t1 (b) values (null),(null);
INSERT INTO t1 (c) values (null);
Column 'c' cannot be null
INSERT INTO t1 (c) values (1/null);
Column 'c' cannot be null
INSERT INTO t1 (c) values (null),(null);
INSERT INTO t1 (d) values (null);
Column 'd' cannot be null
INSERT INTO t1 (d) values (1/null);
Column 'd' cannot be null
INSERT INTO t1 (d) values (null),(null);
select * from t1;
a b c d
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
0 0000-00-00 00:00:00 0
drop table t1;
slave stop;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
create table t1(a int not null auto_increment, b int, primary key(a) );
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
select * from t1;
a b
1 10
2 15
drop table t1;
...@@ -105,7 +105,7 @@ drop table t3,t2,t1; ...@@ -105,7 +105,7 @@ drop table t3,t2,t1;
# #
# Test table without unions # Test table without unions
# #
create table t1 (a int not null) type=merge; create table t1 (a int not null, key(a)) type=merge;
select * from t1; select * from t1;
drop table t1; drop table t1;
......
...@@ -48,3 +48,34 @@ insert into t1 values(10,null); ...@@ -48,3 +48,34 @@ insert into t1 values(10,null);
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
t2.b=t3.a order by 1; t2.b=t3.a order by 1;
drop table t1; drop table t1;
#
# Test inserting and updating with NULL
#
CREATE TABLE t1 (a varchar(16) NOT NULL, b smallint(6) NOT NULL, c datetime NOT NULL, d smallint(6) NOT NULL);
INSERT INTO t1 SET a = "", d= "2003-01-14 03:54:55";
UPDATE t1 SET d=1/NULL;
UPDATE t1 SET d=NULL;
--error 1048
INSERT INTO t1 (a) values (null);
--error 1048
INSERT INTO t1 (a) values (1/null);
INSERT INTO t1 (a) values (null),(null);
--error 1048
INSERT INTO t1 (b) values (null);
--error 1048
INSERT INTO t1 (b) values (1/null);
INSERT INTO t1 (b) values (null),(null);
--error 1048
INSERT INTO t1 (c) values (null);
--error 1048
INSERT INTO t1 (c) values (1/null);
INSERT INTO t1 (c) values (null),(null);
--error 1048
INSERT INTO t1 (d) values (null);
--error 1048
INSERT INTO t1 (d) values (1/null);
INSERT INTO t1 (d) values (null),(null);
select * from t1;
drop table t1;
# See if replication of a "LOAD DATA in an autoincrement column"
# Honours autoincrement values
# i.e. if the master and slave have the same sequence
source include/master-slave.inc;
create table t1(a int not null auto_increment, b int, primary key(a) );
load data infile '../../std_data/rpl_loaddata.dat' into table t1;
save_master_pos;
connection slave;
sync_with_master;
select * from t1;
connection master;
drop table t1;
save_master_pos;
connection slave;
sync_with_master;
--skip-external-locking
...@@ -118,6 +118,15 @@ set_field_to_null(Field *field) ...@@ -118,6 +118,15 @@ set_field_to_null(Field *field)
field->reset(); field->reset();
return 0; return 0;
} }
field->reset();
if (current_thd->count_cuted_fields)
{
current_thd->cuted_fields++; // Increment error counter
return 0;
}
if (!current_thd->no_errors)
my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
field->field_name);
return 1; return 1;
} }
......
...@@ -2249,19 +2249,7 @@ convert_search_mode_to_innobase( ...@@ -2249,19 +2249,7 @@ convert_search_mode_to_innobase(
case HA_READ_AFTER_KEY: return(PAGE_CUR_G); case HA_READ_AFTER_KEY: return(PAGE_CUR_G);
case HA_READ_BEFORE_KEY: return(PAGE_CUR_L); case HA_READ_BEFORE_KEY: return(PAGE_CUR_L);
case HA_READ_PREFIX: return(PAGE_CUR_GE); case HA_READ_PREFIX: return(PAGE_CUR_GE);
case HA_READ_PREFIX_LAST: case HA_READ_PREFIX_LAST: return(PAGE_CUR_LE_OR_EXTENDS);
/* ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: Using HA_READ_PREFIX_LAST\n"); */
return(PAGE_CUR_LE);
/* InnoDB does not yet support ..PREFIX_LAST!
We have to add a new search flag
PAGE_CUR_LE_OR_PREFIX to InnoDB. */
/* the above PREFIX flags mean that the last
field in the key value may just be a prefix
of the complete fixed length field */
default: assert(0); default: assert(0);
} }
...@@ -2460,6 +2448,9 @@ ha_innobase::change_active_index( ...@@ -2460,6 +2448,9 @@ ha_innobase::change_active_index(
statistic_increment(ha_read_key_count, &LOCK_status); statistic_increment(ha_read_key_count, &LOCK_status);
DBUG_ENTER("change_active_index"); DBUG_ENTER("change_active_index");
ut_a(prebuilt->trx ==
(trx_t*) current_thd->transaction.all.innobase_tid);
active_index = keynr; active_index = keynr;
if (keynr != MAX_KEY && table->keys > 0) { if (keynr != MAX_KEY && table->keys > 0) {
...@@ -2487,9 +2478,9 @@ ha_innobase::change_active_index( ...@@ -2487,9 +2478,9 @@ ha_innobase::change_active_index(
/* Maybe MySQL changes the active index for a handle also /* Maybe MySQL changes the active index for a handle also
during some queries, we do not know: then it is safest to build during some queries, we do not know: then it is safest to build
the template such that all columns will be fetched */ the template such that all columns will be fetched. */
build_template(prebuilt, user_thd, table, ROW_MYSQL_WHOLE_ROW); build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2994,6 +2985,7 @@ ha_innobase::create( ...@@ -2994,6 +2985,7 @@ ha_innobase::create(
{ {
int error; int error;
dict_table_t* innobase_table; dict_table_t* innobase_table;
trx_t* parent_trx;
trx_t* trx; trx_t* trx;
int primary_key_no; int primary_key_no;
uint i; uint i;
...@@ -3005,6 +2997,16 @@ ha_innobase::create( ...@@ -3005,6 +2997,16 @@ ha_innobase::create(
DBUG_ASSERT(thd != NULL); DBUG_ASSERT(thd != NULL);
/* Get the transaction associated with the current thd, or create one
if not yet created */
parent_trx = check_trx_exists(current_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(parent_trx);
trx = trx_allocate_for_mysql(); trx = trx_allocate_for_mysql();
if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) { if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
...@@ -3165,11 +3167,22 @@ ha_innobase::delete_table( ...@@ -3165,11 +3167,22 @@ ha_innobase::delete_table(
{ {
ulint name_len; ulint name_len;
int error; int error;
trx_t* parent_trx;
trx_t* trx; trx_t* trx;
char norm_name[1000]; char norm_name[1000];
DBUG_ENTER("ha_innobase::delete_table"); DBUG_ENTER("ha_innobase::delete_table");
/* Get the transaction associated with the current thd, or create one
if not yet created */
parent_trx = check_trx_exists(current_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(parent_trx);
if (lower_case_table_names) { if (lower_case_table_names) {
srv_lower_case_table_names = TRUE; srv_lower_case_table_names = TRUE;
} else { } else {
...@@ -3224,11 +3237,22 @@ innobase_drop_database( ...@@ -3224,11 +3237,22 @@ innobase_drop_database(
the database name is 'test' */ the database name is 'test' */
{ {
ulint len = 0; ulint len = 0;
trx_t* parent_trx;
trx_t* trx; trx_t* trx;
char* ptr; char* ptr;
int error; int error;
char namebuf[10000]; char namebuf[10000];
/* Get the transaction associated with the current thd, or create one
if not yet created */
parent_trx = check_trx_exists(current_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(parent_trx);
ptr = strend(path) - 2; ptr = strend(path) - 2;
while (ptr >= path && *ptr != '\\' && *ptr != '/') { while (ptr >= path && *ptr != '\\' && *ptr != '/') {
...@@ -3280,12 +3304,23 @@ ha_innobase::rename_table( ...@@ -3280,12 +3304,23 @@ ha_innobase::rename_table(
ulint name_len1; ulint name_len1;
ulint name_len2; ulint name_len2;
int error; int error;
trx_t* parent_trx;
trx_t* trx; trx_t* trx;
char norm_from[1000]; char norm_from[1000];
char norm_to[1000]; char norm_to[1000];
DBUG_ENTER("ha_innobase::rename_table"); DBUG_ENTER("ha_innobase::rename_table");
/* Get the transaction associated with the current thd, or create one
if not yet created */
parent_trx = check_trx_exists(current_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(parent_trx);
if (lower_case_table_names) { if (lower_case_table_names) {
srv_lower_case_table_names = TRUE; srv_lower_case_table_names = TRUE;
} else { } else {
...@@ -3332,8 +3367,8 @@ Estimates the number of index records in a range. */ ...@@ -3332,8 +3367,8 @@ Estimates the number of index records in a range. */
ha_rows ha_rows
ha_innobase::records_in_range( ha_innobase::records_in_range(
/*==========================*/ /*==========================*/
/* out: estimated number of rows, /* out: estimated number of
currently 32-bit int or uint */ rows */
int keynr, /* in: index number */ int keynr, /* in: index number */
const mysql_byte* start_key, /* in: start key value of the const mysql_byte* start_key, /* in: start key value of the
range, may also be empty */ range, may also be empty */
...@@ -3364,9 +3399,18 @@ ha_innobase::records_in_range( ...@@ -3364,9 +3399,18 @@ ha_innobase::records_in_range(
DBUG_ENTER("records_in_range"); DBUG_ENTER("records_in_range");
/* Warning: since it is not sure that MySQL calls external_lock /* We do not know if MySQL can call this function before calling
before calling this function, the trx field in prebuilt can be external_lock(). To be safe, update the thd of the current table
obsolete! */ handle. */
update_thd(current_thd);
prebuilt->trx->op_info = (char*)"estimating records in index range";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(prebuilt->trx);
active_index = keynr; active_index = keynr;
...@@ -3400,6 +3444,8 @@ ha_innobase::records_in_range( ...@@ -3400,6 +3444,8 @@ ha_innobase::records_in_range(
my_free((char*) key_val_buff2, MYF(0)); my_free((char*) key_val_buff2, MYF(0));
prebuilt->trx->op_info = (char*)"";
DBUG_RETURN((ha_rows) n_rows); DBUG_RETURN((ha_rows) n_rows);
} }
...@@ -3420,11 +3466,21 @@ ha_innobase::estimate_number_of_rows(void) ...@@ -3420,11 +3466,21 @@ ha_innobase::estimate_number_of_rows(void)
ulonglong estimate; ulonglong estimate;
ulonglong local_data_file_length; ulonglong local_data_file_length;
/* Warning: since it is not sure that MySQL calls external_lock DBUG_ENTER("estimate_number_of_rows");
before calling this function, the trx field in prebuilt can be
obsolete! */
DBUG_ENTER("info"); /* We do not know if MySQL can call this function before calling
external_lock(). To be safe, update the thd of the current table
handle. */
update_thd(current_thd);
prebuilt->trx->op_info = (char*)
"calculating upper bound for table rows";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(prebuilt->trx);
index = dict_table_get_first_index_noninline(prebuilt->table); index = dict_table_get_first_index_noninline(prebuilt->table);
...@@ -3439,6 +3495,8 @@ ha_innobase::estimate_number_of_rows(void) ...@@ -3439,6 +3495,8 @@ ha_innobase::estimate_number_of_rows(void)
estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index); estimate = 2 * local_data_file_length / dict_index_calc_min_rec_len(index);
prebuilt->trx->op_info = (char*)"";
DBUG_RETURN((ha_rows) estimate); DBUG_RETURN((ha_rows) estimate);
} }
...@@ -3489,9 +3547,18 @@ ha_innobase::info( ...@@ -3489,9 +3547,18 @@ ha_innobase::info(
return; return;
} }
/* Warning: since it is not sure that MySQL calls external_lock /* We do not know if MySQL can call this function before calling
before calling this function, the trx field in prebuilt can be external_lock(). To be safe, update the thd of the current table
obsolete! */ handle. */
update_thd(current_thd);
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
prebuilt->trx->op_info = (char*)"returning various info to MySQL";
trx_search_latch_release_if_reserved(prebuilt->trx);
ib_table = prebuilt->table; ib_table = prebuilt->table;
...@@ -3499,7 +3566,12 @@ ha_innobase::info( ...@@ -3499,7 +3566,12 @@ ha_innobase::info(
/* In sql_show we call with this flag: update then statistics /* In sql_show we call with this flag: update then statistics
so that they are up-to-date */ so that they are up-to-date */
prebuilt->trx->op_info = (char*)"updating table statistics";
dict_update_statistics(ib_table); dict_update_statistics(ib_table);
prebuilt->trx->op_info = (char*)
"returning various info to MySQL";
} }
if (flag & HA_STATUS_VARIABLE) { if (flag & HA_STATUS_VARIABLE) {
...@@ -3559,12 +3631,6 @@ ha_innobase::info( ...@@ -3559,12 +3631,6 @@ ha_innobase::info(
} }
} }
/* The trx struct in InnoDB contains a pthread mutex embedded:
in the debug version of MySQL that it replaced by a 'safe mutex'
which is of a different size. We have to use a function to access
trx fields. Otherwise trx->error_info will be a random
pointer and cause a seg fault. */
if (flag & HA_STATUS_ERRKEY) { if (flag & HA_STATUS_ERRKEY) {
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N); ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
...@@ -3573,6 +3639,8 @@ ha_innobase::info( ...@@ -3573,6 +3639,8 @@ ha_innobase::info(
trx_get_error_info(prebuilt->trx)); trx_get_error_info(prebuilt->trx));
} }
prebuilt->trx->op_info = (char*)"";
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -3630,11 +3698,22 @@ ha_innobase::update_table_comment( ...@@ -3630,11 +3698,22 @@ ha_innobase::update_table_comment(
char* str = my_malloc(length + 16500, MYF(0)); char* str = my_malloc(length + 16500, MYF(0));
char* pos; char* pos;
/* Warning: since it is not sure that MySQL calls external_lock /* We do not know if MySQL can call this function before calling
before calling this function, the trx field in prebuilt can be external_lock(). To be safe, update the thd of the current table
obsolete! */ handle. */
update_thd(current_thd);
prebuilt->trx->op_info = (char*)"returning table comment";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(prebuilt->trx);
if (!str) { if (!str) {
prebuilt->trx->op_info = (char*)"";
return((char*)comment); return((char*)comment);
} }
...@@ -3658,6 +3737,8 @@ ha_innobase::update_table_comment( ...@@ -3658,6 +3737,8 @@ ha_innobase::update_table_comment(
prebuilt->table); prebuilt->table);
} }
prebuilt->trx->op_info = (char*)"";
return(str); return(str);
} }
...@@ -3673,20 +3754,30 @@ ha_innobase::get_foreign_key_create_info(void) ...@@ -3673,20 +3754,30 @@ ha_innobase::get_foreign_key_create_info(void)
{ {
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt; row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
char* str; char* str;
if (prebuilt == NULL) {
fprintf(stderr,
"InnoDB: Error: cannot get create info for foreign keys\n");
return(NULL); ut_a(prebuilt != NULL);
}
/* We do not know if MySQL can call this function before calling
external_lock(). To be safe, update the thd of the current table
handle. */
update_thd(current_thd);
prebuilt->trx->op_info = (char*)"getting info on foreign keys";
/* In case MySQL calls this in the middle of a SELECT query, release
possible adaptive hash latch to avoid deadlocks of threads */
trx_search_latch_release_if_reserved(prebuilt->trx);
str = (char*)ut_malloc(10000); str = (char*)ut_malloc(10000);
str[0] = '\0'; str[0] = '\0';
dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table); dict_print_info_on_foreign_keys(TRUE, str, 9000, prebuilt->table);
prebuilt->trx->op_info = (char*)"";
return(str); return(str);
} }
...@@ -3752,9 +3843,10 @@ ha_innobase::reset(void) ...@@ -3752,9 +3843,10 @@ ha_innobase::reset(void)
} }
/********************************************************************** /**********************************************************************
When we create a temporary table inside MySQL LOCK TABLES, MySQL will Inside LOCK TABLES MySQL will not call external_lock() between SQL
not call external_lock for the temporary table when it uses it. Instead, statements. It will call this function at the start of each SQL statement.
it will call this function. */ Note also a spacial case: if a temporary table is created inside LOCK
TABLES, MySQL has not called external_lock() at all on that table. */
int int
ha_innobase::start_stmt( ha_innobase::start_stmt(
...@@ -3892,8 +3984,8 @@ ha_innobase::external_lock( ...@@ -3892,8 +3984,8 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0; trx->mysql_n_tables_locked = 0;
/* Here we release the search latch, auto_inc_lock, /* Here we release the search latch and InnoDB
and InnoDB thread FIFO ticket if they were reserved. */ thread FIFO ticket if they were reserved. */
innobase_release_stat_resources(trx); innobase_release_stat_resources(trx);
...@@ -4209,4 +4301,4 @@ ha_innobase::get_auto_increment() ...@@ -4209,4 +4301,4 @@ ha_innobase::get_auto_increment()
} }
#endif /* HAVE_INNOBASE_DB */ #endif /* HAVE_INNOBASE_DB */
...@@ -231,7 +231,7 @@ void ha_myisammrg::info(uint flag) ...@@ -231,7 +231,7 @@ void ha_myisammrg::info(uint flag)
#endif #endif
if (flag & HA_STATUS_CONST) if (flag & HA_STATUS_CONST)
{ {
if (table->key_parts) if (table->key_parts && info.rec_per_key)
memcpy((char*) table->key_info[0].rec_per_key, memcpy((char*) table->key_info[0].rec_per_key,
(char*) info.rec_per_key, (char*) info.rec_per_key,
sizeof(table->key_info[0].rec_per_key)*table->key_parts); sizeof(table->key_info[0].rec_per_key)*table->key_parts);
......
...@@ -749,7 +749,7 @@ static void *kill_server(void *sig_ptr) ...@@ -749,7 +749,7 @@ static void *kill_server(void *sig_ptr)
#define RETURN_FROM_KILL_SERVER DBUG_RETURN(0) #define RETURN_FROM_KILL_SERVER DBUG_RETURN(0)
#else #else
static void __cdecl kill_server(int sig_ptr) static void __cdecl kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER DBUG_RETURN #define RETURN_FROM_KILL_SERVER DBUG_VOID_RETURN
#endif #endif
{ {
int sig=(int) (long) sig_ptr; // This is passed a int int sig=(int) (long) sig_ptr; // This is passed a int
......
...@@ -38,7 +38,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -38,7 +38,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
table_map removed_tables=0; table_map removed_tables=0;
Item *item; Item *item;
COND *org_conds= conds; COND *org_conds= conds;
/* Add all ON conditions to WHERE condition */ /* Add all ON conditions to WHERE condition */
for (TABLE_LIST *tl=tables; tl ; tl= tl->next) for (TABLE_LIST *tl=tables; tl ; tl= tl->next)
{ {
...@@ -165,10 +165,9 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds) ...@@ -165,10 +165,9 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
error=table->file->index_last(table->record[0]) !=0; error=table->file->index_last(table->record[0]) !=0;
else else
{ {
(void)table->file->index_read(table->record[0], key_buff, error = table->file->index_read(table->record[0], key_buff,
ref.key_length, ref.key_length,
HA_READ_AFTER_KEY); HA_READ_PREFIX_LAST) ||
error=table->file->index_prev(table->record[0]) ||
key_cmp(table,key_buff,ref.key,ref.key_length); key_cmp(table,key_buff,ref.key,ref.key_length);
} }
if (table->key_read) if (table->key_read)
......
...@@ -109,6 +109,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -109,6 +109,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (cond && cond->fix_fields(thd,tables)) if (cond && cond->fix_fields(thd,tables))
return -1; return -1;
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
if (keyname) if (keyname)
{ {
if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0) if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
...@@ -128,8 +130,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -128,8 +130,6 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
insert_fields(thd,tables,tables->db,tables->alias,&it); insert_fields(thd,tables,tables->db,tables->alias,&it);
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
select_limit+=offset_limit; select_limit+=offset_limit;
send_fields(thd,list,1); send_fields(thd,list,1);
...@@ -139,6 +139,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables, ...@@ -139,6 +139,8 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (!lock) if (!lock)
goto err0; // mysql_lock_tables() printed error message already goto err0; // mysql_lock_tables() printed error message already
table->file->init_table_handle_for_HANDLER(); // Only InnoDB requires it
for (num_rows=0; num_rows < select_limit; ) for (num_rows=0; num_rows < select_limit; )
{ {
switch(mode) { switch(mode) {
......
...@@ -357,8 +357,10 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ...@@ -357,8 +357,10 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
{ {
List_iterator_fast<Item> it(fields); List_iterator_fast<Item> it(fields);
Item_field *sql_field; Item_field *sql_field;
ulonglong id;
DBUG_ENTER("read_fixed_length"); DBUG_ENTER("read_fixed_length");
id=0;
/* No fields can be null in this format. mark all fields as not null */ /* No fields can be null in this format. mark all fields as not null */
while ((sql_field= (Item_field*) it++)) while ((sql_field= (Item_field*) it++))
sql_field->field->set_notnull(); sql_field->field->set_notnull();
...@@ -401,6 +403,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ...@@ -401,6 +403,14 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
thd->cuted_fields++; /* To long row */ thd->cuted_fields++; /* To long row */
if (write_record(table,&info)) if (write_record(table,&info))
DBUG_RETURN(1); DBUG_RETURN(1);
/*
If auto_increment values are used, save the first one
for LAST_INSERT_ID() and for the binary/update log.
We can't use insert_id() as we don't want to touch the
last_insert_id_used flag.
*/
if (!id && thd->insert_id_used)
id= thd->last_insert_id;
if (table->next_number_field) if (table->next_number_field)
table->next_number_field->reset(); // Clear for next record table->next_number_field->reset(); // Clear for next record
if (read_info.next_line()) // Skip to next line if (read_info.next_line()) // Skip to next line
...@@ -408,6 +418,8 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields, ...@@ -408,6 +418,8 @@ read_fixed_length(THD *thd,COPY_INFO &info,TABLE *table,List<Item> &fields,
if (read_info.line_cuted) if (read_info.line_cuted)
thd->cuted_fields++; /* To long row */ thd->cuted_fields++; /* To long row */
} }
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
DBUG_RETURN(test(read_info.error)); DBUG_RETURN(test(read_info.error));
} }
...@@ -421,10 +433,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ...@@ -421,10 +433,12 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
List_iterator_fast<Item> it(fields); List_iterator_fast<Item> it(fields);
Item_field *sql_field; Item_field *sql_field;
uint enclosed_length; uint enclosed_length;
ulonglong id;
DBUG_ENTER("read_sep_field"); DBUG_ENTER("read_sep_field");
enclosed_length=enclosed.length(); enclosed_length=enclosed.length();
id=0;
for (;;it.rewind()) for (;;it.rewind())
{ {
if (thd->killed) if (thd->killed)
...@@ -477,6 +491,14 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ...@@ -477,6 +491,14 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
} }
if (write_record(table,&info)) if (write_record(table,&info))
DBUG_RETURN(1); DBUG_RETURN(1);
/*
If auto_increment values are used, save the first one
for LAST_INSERT_ID() and for the binary/update log.
We can't use insert_id() as we don't want to touch the
last_insert_id_used flag.
*/
if (!id && thd->insert_id_used)
id= thd->last_insert_id;
if (table->next_number_field) if (table->next_number_field)
table->next_number_field->reset(); // Clear for next record table->next_number_field->reset(); // Clear for next record
if (read_info.next_line()) // Skip to next line if (read_info.next_line()) // Skip to next line
...@@ -484,6 +506,8 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table, ...@@ -484,6 +506,8 @@ read_sep_field(THD *thd,COPY_INFO &info,TABLE *table,
if (read_info.line_cuted) if (read_info.line_cuted)
thd->cuted_fields++; /* To long row */ thd->cuted_fields++; /* To long row */
} }
if (id && !read_info.error)
thd->insert_id(id); // For binary/update log
DBUG_RETURN(test(read_info.error)); DBUG_RETURN(test(read_info.error));
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment