Commit 453c48f0 authored by unknown's avatar unknown

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

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


sql/ha_innodb.cc:
  Auto merged
parents 90f09dc5 3ebfa9c9
LIBRARY LIBMYSQL
DESCRIPTION 'MySQL 4.0 Client Library'
VERSION 4.0
EXPORTS
mysql_affected_rows
mysql_close
mysql_data_seek
mysql_debug
mysql_dump_debug_info
mysql_eof
mysql_errno
mysql_error
mysql_escape_string
mysql_fetch_field
mysql_fetch_field_direct
mysql_fetch_fields
mysql_fetch_lengths
mysql_fetch_row
mysql_field_count
mysql_field_seek
mysql_field_tell
mysql_free_result
mysql_get_client_info
mysql_get_host_info
mysql_get_proto_info
mysql_get_server_info
mysql_info
mysql_init
mysql_insert_id
mysql_kill
mysql_list_dbs
mysql_list_fields
mysql_list_processes
mysql_list_tables
mysql_num_fields
mysql_num_rows
mysql_odbc_escape_string
mysql_options
mysql_ping
mysql_query
mysql_real_connect
mysql_real_query
mysql_refresh
mysql_row_seek
mysql_row_tell
mysql_select_db
mysql_shutdown
mysql_stat
mysql_store_result
mysql_thread_id
mysql_use_result
bmove_upp
delete_dynamic
_dig_vec
init_dynamic_array
insert_dynamic
int2str
is_prefix
list_add
list_delete
max_allowed_packet
my_casecmp
my_init
my_end
my_strdup
my_malloc
my_memdup
my_no_flags_free
my_realloc
my_thread_end
my_thread_init
net_buffer_length
set_dynamic
strcend
strdup_root
strfill
strinstr
strmake
strmov
strxmov
myodbc_remove_escape
mysql_thread_safe
mysql_character_set_name
mysql_change_user
mysql_send_query
mysql_read_query_result
mysql_real_escape_string
mysql_ssl_set
mysql_real_connect
mysql_master_query
mysql_master_send_query
mysql_slave_query
mysql_slave_send_query
mysql_enable_rpl_parse
mysql_disable_rpl_parse
mysql_rpl_parse_enabled
mysql_enable_reads_from_master
mysql_disable_reads_from_master
mysql_reads_from_master_enabled
mysql_rpl_query_type
mysql_rpl_probe
mysql_set_master
mysql_add_slave
...@@ -419,13 +419,21 @@ struct row_prebuilt_struct { ...@@ -419,13 +419,21 @@ struct row_prebuilt_struct {
index where the ordering column is index where the ordering column is
the row id: in this case this flag the row id: in this case this flag
is set to TRUE */ is set to TRUE */
dict_index_t* index; /* current index for a search, if any */ dict_index_t* index; /* current index for a search, if
any */
ulint read_just_key; /* set to 1 when MySQL calls ulint read_just_key; /* set to 1 when MySQL calls
ha_innobase::extra with the ha_innobase::extra with the
argument HA_EXTRA_KEYREAD; it is enough argument HA_EXTRA_KEYREAD; it is enough
to read just columns defined in to read just columns defined in
the index (i.e., no read of the the index (i.e., no read of the
clustered index record necessary) */ clustered index record necessary) */
ibool used_in_HANDLER;/* TRUE if we have been using this
handle in a MySQL HANDLER low level
index cursor command: then we must
store the pcur position even in a
unique search from a clustered index,
because HANDLER allows NEXT and PREV
in such a situation */
ulint template_type; /* ROW_MYSQL_WHOLE_ROW, ulint template_type; /* ROW_MYSQL_WHOLE_ROW,
ROW_MYSQL_REC_FIELDS, ROW_MYSQL_REC_FIELDS,
ROW_MYSQL_DUMMY_TEMPLATE, or ROW_MYSQL_DUMMY_TEMPLATE, or
......
...@@ -323,7 +323,7 @@ row_ins_clust_index_entry_by_modify( ...@@ -323,7 +323,7 @@ row_ins_clust_index_entry_by_modify(
/************************************************************************* /*************************************************************************
Returns TRUE if in a cascaded update/delete an ancestor node of node Returns TRUE if in a cascaded update/delete an ancestor node of node
updates table. */ updates (not DELETE, but UPDATE) table. */
static static
ibool ibool
row_ins_cascade_ancestor_updates_table( row_ins_cascade_ancestor_updates_table(
...@@ -341,7 +341,7 @@ row_ins_cascade_ancestor_updates_table( ...@@ -341,7 +341,7 @@ row_ins_cascade_ancestor_updates_table(
upd_node = parent; upd_node = parent;
if (upd_node->table == table) { if (upd_node->table == table && upd_node->is_delete == FALSE) {
return(TRUE); return(TRUE);
} }
...@@ -678,14 +678,13 @@ row_ins_foreign_check_on_constraint( ...@@ -678,14 +678,13 @@ row_ins_foreign_check_on_constraint(
} }
} }
/* We do not allow cyclic cascaded updating of the same /* We do not allow cyclic cascaded updating (DELETE is allowed,
table. Check that we are not updating the same table which but not UPDATE) of the same table, as this can lead to an infinite
is already being modified in this cascade chain. We have to cycle. Check that we are not updating the same table which is
check this because the modification of the indexes of a already being modified in this cascade chain. We have to check
'parent' table may still be incomplete, and we must avoid this also because the modification of the indexes of a 'parent'
seeing the indexes of the parent table in an inconsistent table may still be incomplete, and we must avoid seeing the indexes
state! In this way we also prevent possible infinite of the parent table in an inconsistent state! */
update loops caused by cyclic cascaded updates. */
if (!cascade->is_delete if (!cascade->is_delete
&& row_ins_cascade_ancestor_updates_table(cascade, table)) { && row_ins_cascade_ancestor_updates_table(cascade, table)) {
......
...@@ -324,6 +324,9 @@ row_create_prebuilt( ...@@ -324,6 +324,9 @@ row_create_prebuilt(
prebuilt->mysql_has_locked = FALSE; prebuilt->mysql_has_locked = FALSE;
prebuilt->index = NULL; prebuilt->index = NULL;
prebuilt->used_in_HANDLER = FALSE;
prebuilt->n_template = 0; prebuilt->n_template = 0;
prebuilt->mysql_template = NULL; prebuilt->mysql_template = NULL;
......
...@@ -2685,16 +2685,31 @@ row_search_for_mysql( ...@@ -2685,16 +2685,31 @@ row_search_for_mysql(
mode = pcur->search_mode; mode = pcur->search_mode;
} }
if ((direction == ROW_SEL_NEXT || direction == ROW_SEL_PREV)
&& pcur->old_stored != BTR_PCUR_OLD_STORED) {
/* MySQL sometimes seems to do fetch next or fetch prev even
if the search condition is unique; this can, for example,
happen with the HANDLER commands; we do not always store the
pcur position in this case, so we cannot restore cursor
position, and must return immediately */
/* printf("%s record not found 1\n", index->name); */
trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
mtr_start(&mtr); mtr_start(&mtr);
/* In a search where at most one record in the index may match, we /* In a search where at most one record in the index may match, we
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete-
marked matching record. marked matching record.
Note that in a unique secondary index there may be different delete Note that in a unique secondary index there may be different delete-
marked versions of a record where only the primary key values differ: marked versions of a record where only the primary key values differ:
thus in a secondary index we must use next-key locks when locking thus in a secondary index we must use next-key locks when locking
delete marked records. */ delete-marked records. */
if (match_mode == ROW_SEL_EXACT if (match_mode == ROW_SEL_EXACT
&& index->type & DICT_UNIQUE && index->type & DICT_UNIQUE
...@@ -2715,25 +2730,9 @@ row_search_for_mysql( ...@@ -2715,25 +2730,9 @@ row_search_for_mysql(
if (unique_search if (unique_search
&& index->type & DICT_CLUSTERED && index->type & DICT_CLUSTERED
&& !prebuilt->templ_contains_blob && !prebuilt->templ_contains_blob
&& !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) { && (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
if (direction == ROW_SEL_NEXT) {
/* MySQL sometimes seems to do fetch next even
if the search condition is unique; we do not store
pcur position in this case, so we cannot
restore cursor position, and must return
immediately */
mtr_commit(&mtr);
/* printf("%s record not found 1\n", index->name); */
trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
ut_a(direction == 0); /* We cannot do fetch prev, as we have
not stored the cursor position */
mode = PAGE_CUR_GE; mode = PAGE_CUR_GE;
unique_search_from_clust_index = TRUE; unique_search_from_clust_index = TRUE;
...@@ -2785,6 +2784,10 @@ row_search_for_mysql( ...@@ -2785,6 +2784,10 @@ row_search_for_mysql(
} }
trx->op_info = (char *) ""; trx->op_info = (char *) "";
/* NOTE that we do NOT store the cursor
position */
return(DB_SUCCESS); return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) { } else if (shortcut == SEL_EXHAUSTED) {
...@@ -2804,6 +2807,10 @@ row_search_for_mysql( ...@@ -2804,6 +2807,10 @@ row_search_for_mysql(
} }
trx->op_info = (char *) ""; trx->op_info = (char *) "";
/* NOTE that we do NOT store the cursor
position */
return(DB_RECORD_NOT_FOUND); return(DB_RECORD_NOT_FOUND);
} }
...@@ -3184,6 +3191,7 @@ row_search_for_mysql( ...@@ -3184,6 +3191,7 @@ row_search_for_mysql(
&& prebuilt->select_lock_type == LOCK_NONE && prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->templ_contains_blob && !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated && !prebuilt->clust_index_was_generated
&& !prebuilt->used_in_HANDLER
&& prebuilt->template_type && prebuilt->template_type
!= ROW_MYSQL_DUMMY_TEMPLATE) { != ROW_MYSQL_DUMMY_TEMPLATE) {
...@@ -3192,7 +3200,9 @@ row_search_for_mysql( ...@@ -3192,7 +3200,9 @@ row_search_for_mysql(
update, that is why we require ...lock_type == LOCK_NONE. update, that is why we require ...lock_type == LOCK_NONE.
Since we keep space in prebuilt only for the BLOBs of Since we keep space in prebuilt only for the BLOBs of
a single row, we cannot cache rows in the case there a single row, we cannot cache rows in the case there
are BLOBs in the fields to be fetched. */ are BLOBs in the fields to be fetched. In HANDLER we do
not cache rows because there the cursor is a scrollable
cursor. */
row_sel_push_cache_row_for_mysql(prebuilt, rec); row_sel_push_cache_row_for_mysql(prebuilt, rec);
...@@ -3217,11 +3227,16 @@ row_search_for_mysql( ...@@ -3217,11 +3227,16 @@ row_search_for_mysql(
} }
} }
got_row: got_row:
/* TODO: should we in every case store the cursor position, even /* We have an optimization to save CPU time: if this is a consistent
if this is just a join, for example? */ read on a unique condition on the clustered index, then we do not
store the pcur position, because any fetch next or prev will anyway
return 'end of file'. An exception is the MySQL HANDLER command
where the user can move the cursor with PREV or NEXT even after
a unique search. */
if (!unique_search_from_clust_index if (!unique_search_from_clust_index
|| prebuilt->select_lock_type == LOCK_X) { || prebuilt->select_lock_type == LOCK_X
|| prebuilt->used_in_HANDLER) {
/* Inside an update always store the cursor position */ /* Inside an update always store the cursor position */
......
...@@ -107,6 +107,10 @@ EXPORTS ...@@ -107,6 +107,10 @@ EXPORTS
my_print_variables my_print_variables
getopt_ull_limit_value getopt_ull_limit_value
getopt_compare_strings getopt_compare_strings
load_defaults
free_defaults
my_path
......
...@@ -601,7 +601,7 @@ innobase_invalidate_query_cache( ...@@ -601,7 +601,7 @@ innobase_invalidate_query_cache(
Call this when you have opened a new table handle in HANDLER, before you Call this when you have opened a new table handle in HANDLER, before you
call index_read_idx() etc. Actually, we can let the cursor stay open even call index_read_idx() etc. Actually, we can let the cursor stay open even
over a transaction commit! Then you should call this before every operation, over a transaction commit! Then you should call this before every operation,
fecth next etc. This function inits the necessary things even after a fetch next etc. This function inits the necessary things even after a
transaction commit. */ transaction commit. */
void void
...@@ -648,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void) ...@@ -648,6 +648,8 @@ ha_innobase::init_table_handle_for_HANDLER(void)
we???? */ we???? */
prebuilt->read_just_key = FALSE; prebuilt->read_just_key = FALSE;
prebuilt->used_in_HANDLER = TRUE;
} }
/************************************************************************* /*************************************************************************
...@@ -4048,6 +4050,8 @@ ha_innobase::external_lock( ...@@ -4048,6 +4050,8 @@ ha_innobase::external_lock(
trx->mysql_n_tables_locked = 0; trx->mysql_n_tables_locked = 0;
prebuilt->used_in_HANDLER = FALSE;
/* Here we release the search latch and InnoDB /* Here we release the search latch and InnoDB
thread FIFO ticket if they were reserved. */ thread FIFO ticket if they were reserved. */
......
...@@ -486,7 +486,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) ...@@ -486,7 +486,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
param.thd = thd; param.thd = thd;
param.op_name = (char*) "repair"; param.op_name = (char*) "repair";
param.testflag = ((check_opt->flags & ~(T_EXTEND)) | param.testflag = ((check_opt->flags & ~(T_EXTEND)) |
T_SILENT | T_FORCE_CREATE | T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM |
(check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT)); (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT));
param.sort_buffer_length= check_opt->sort_buffer_size; param.sort_buffer_length= check_opt->sort_buffer_size;
start_records=file->state->records; start_records=file->state->records;
......
...@@ -180,6 +180,8 @@ class base_list_iterator ...@@ -180,6 +180,8 @@ class base_list_iterator
*new_list.last=current->next; *new_list.last=current->next;
current->info=new_list.first->info; current->info=new_list.first->info;
current->next=new_list.first->next; current->next=new_list.first->next;
if ((list->last == &current->next) && (new_list.elements > 1))
list->last= new_list.last;
list->elements+=new_list.elements-1; list->elements+=new_list.elements-1;
} }
return ret_value; // return old element return ret_value; // return old element
......
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