1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Merge gbichot3.local:/home/mysql_src/mysql-5.1-interval-move-next-insert-id

into  gbichot3.local:/home/mysql_src/mysql-5.1
This commit is contained in:
guilhem@gbichot3.local
2006-07-09 22:50:02 +02:00
30 changed files with 1223 additions and 390 deletions

View File

@ -770,12 +770,14 @@ class Sub_statement_state
{
public:
ulonglong options;
ulonglong last_insert_id, next_insert_id, current_insert_id;
ulonglong first_successful_insert_id_in_prev_stmt;
ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
Discrete_interval auto_inc_interval_for_cur_row;
ulonglong limit_found_rows;
ha_rows cuted_fields, sent_row_count, examined_row_count;
ulong client_capabilities;
uint in_sub_stmt;
bool enable_slow_log, insert_id_used, clear_next_insert_id;
bool enable_slow_log;
bool last_insert_id_used;
my_bool no_send_ok;
SAVEPOINT *savepoints;
@ -1071,24 +1073,136 @@ public:
Note: in the parser, stmt_arena == thd, even for PS/SP.
*/
Query_arena *stmt_arena;
/* Tells if LAST_INSERT_ID(#) was called for the current statement */
bool arg_of_last_insert_id_function;
/*
next_insert_id is set on SET INSERT_ID= #. This is used as the next
generated auto_increment value in handler.cc
ALL OVER THIS FILE, "insert_id" means "*automatically generated* value for
insertion into an auto_increment column".
*/
ulonglong next_insert_id;
/* Remember last next_insert_id to reset it if something went wrong */
ulonglong prev_insert_id;
/*
The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
LAST_INSERT_ID()
This is the first autogenerated insert id which was *successfully*
inserted by the previous statement (exactly, if the previous statement
didn't successfully insert an autogenerated insert id, then it's the one
of the statement before, etc).
It can also be set by SET LAST_INSERT_ID=# or SELECT LAST_INSERT_ID(#).
It is returned by LAST_INSERT_ID().
*/
ulonglong last_insert_id;
ulonglong first_successful_insert_id_in_prev_stmt;
/*
Set to the first value that LAST_INSERT_ID() returned for the last
statement. When this is set, last_insert_id_used is set to true.
Variant of the above, used for storing in statement-based binlog. The
difference is that the one above can change as the execution of a stored
function progresses, while the one below is set once and then does not
change (which is the value which statement-based binlog needs).
*/
ulonglong current_insert_id;
ulonglong first_successful_insert_id_in_prev_stmt_for_binlog;
/*
This is the first autogenerated insert id which was *successfully*
inserted by the current statement. It is maintained only to set
first_successful_insert_id_in_prev_stmt when statement ends.
*/
ulonglong first_successful_insert_id_in_cur_stmt;
/*
We follow this logic:
- when stmt starts, first_successful_insert_id_in_prev_stmt contains the
first insert id successfully inserted by the previous stmt.
- as stmt makes progress, handler::insert_id_for_cur_row changes; every
time get_auto_increment() is called, auto_inc_intervals_for_binlog is
augmented with the reserved interval (if statement-based binlogging).
- at first successful insertion of an autogenerated value,
first_successful_insert_id_in_cur_stmt is set to
handler::insert_id_for_cur_row.
- when stmt goes to binlog, auto_inc_intervals_for_binlog is
binlogged if non-empty.
- when stmt ends, first_successful_insert_id_in_prev_stmt is set to
first_successful_insert_id_in_cur_stmt.
*/
/*
stmt_depends_on_first_successful_insert_id_in_prev_stmt is set when
LAST_INSERT_ID() is used by a statement.
If it is set, first_successful_insert_id_in_prev_stmt_for_binlog will be
stored in the statement-based binlog.
This variable is CUMULATIVE along the execution of a stored function or
trigger: if one substatement sets it to 1 it will stay 1 until the
function/trigger ends, thus making sure that
first_successful_insert_id_in_prev_stmt_for_binlog does not change anymore
and is propagated to the caller for binlogging.
*/
bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
/*
List of auto_increment intervals reserved by the thread so far, for
storage in the statement-based binlog.
Note that its minimum is not first_successful_insert_id_in_cur_stmt:
assuming a table with an autoinc column, and this happens:
INSERT INTO ... VALUES(3);
SET INSERT_ID=3; INSERT IGNORE ... VALUES (NULL);
then the latter INSERT will insert no rows
(first_successful_insert_id_in_cur_stmt == 0), but storing "INSERT_ID=3"
in the binlog is still needed; the list's minimum will contain 3.
*/
Discrete_intervals_list auto_inc_intervals_in_cur_stmt_for_binlog;
/* Used by replication and SET INSERT_ID */
Discrete_intervals_list auto_inc_intervals_forced;
/*
There is BUG#19630 where statement-based replication of stored
functions/triggers with two auto_increment columns breaks.
We however ensure that it works when there is 0 or 1 auto_increment
column; our rules are
a) on master, while executing a top statement involving substatements,
first top- or sub- statement to generate auto_increment values wins the
exclusive right to write them to binlog (so the losers won't write their
values to binlog).
b) on slave, while replicating a top statement involving substatements,
first top- or sub- statement to need to read auto_increment values from
the master's binlog wins the exclusive right to read them (so the losers
won't read their values from binlog but instead generate on their own).
a) implies that we mustn't backup/restore
auto_inc_intervals_in_cur_stmt_for_binlog.
b) implies that we mustn't backup/restore auto_inc_intervals_forced.
If there are more than 1 auto_increment columns, then intervals for
different columns may mix into the
auto_inc_intervals_in_cur_stmt_for_binlog list, which is logically wrong,
but there is no point in preventing this mixing by preventing intervals
from the secondly inserted column to come into the list, as such
prevention would be wrong too.
What will happen in the case of
INSERT INTO t1 (auto_inc) VALUES(NULL);
where t1 has a trigger which inserts into an auto_inc column of t2, is
that in binlog we'll store the interval of t1 and the interval of t2 (when
we store intervals, soon), then in slave, t1 will use both intervals, t2
will use none; if t1 inserts the same number of rows as on master,
normally the 2nd interval will not be used by t1, which is fine. t2's
values will be wrong if t2's internal auto_increment counter is different
from what it was on master (which is likely). In 5.1, in mixed binlogging
mode, row-based binlogging is used for such cases where two
auto_increment columns are inserted.
*/
inline void record_first_successful_insert_id_in_cur_stmt(ulonglong id)
{
if (first_successful_insert_id_in_cur_stmt == 0)
first_successful_insert_id_in_cur_stmt= id;
}
inline ulonglong read_first_successful_insert_id_in_prev_stmt(void)
{
if (!stmt_depends_on_first_successful_insert_id_in_prev_stmt)
{
/* It's the first time we read it */
first_successful_insert_id_in_prev_stmt_for_binlog=
first_successful_insert_id_in_prev_stmt;
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
}
return first_successful_insert_id_in_prev_stmt;
}
/*
Used by Intvar_log_event::exec_event() and by "SET INSERT_ID=#"
(mysqlbinlog). We'll soon add a variant which can take many intervals in
argument.
*/
inline void force_one_auto_inc_interval(ulonglong next_id)
{
auto_inc_intervals_forced.append(next_id, ULONGLONG_MAX, 0);
}
ulonglong limit_found_rows;
ulonglong options; /* Bitmap of states */
longlong row_count_func; /* For the ROW_COUNT() function */
@ -1157,7 +1271,6 @@ public:
bool last_cuted_field;
bool no_errors, password, is_fatal_error;
bool query_start_used, rand_used, time_zone_used;
bool last_insert_id_used,insert_id_used, clear_next_insert_id;
bool in_lock_tables;
bool query_error, bootstrap, cleanup_done;
bool tmp_table_used;
@ -1185,9 +1298,10 @@ public:
/* Used by the sys_var class to store temporary values */
union
{
my_bool my_bool_value;
long long_value;
ulong ulong_value;
my_bool my_bool_value;
long long_value;
ulong ulong_value;
ulonglong ulonglong_value;
} sys_var_tmp;
struct {
@ -1288,20 +1402,6 @@ public:
inline void end_time() { time(&start_time); }
inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; }
inline void lock_time() { time(&time_after_lock); }
inline void insert_id(ulonglong id_arg)
{
last_insert_id= id_arg;
insert_id_used=1;
}
inline ulonglong insert_id(void)
{
if (!last_insert_id_used)
{
last_insert_id_used=1;
current_insert_id=last_insert_id;
}
return last_insert_id;
}
inline ulonglong found_rows(void)
{
return limit_found_rows;
@ -1617,7 +1717,7 @@ class select_insert :public select_result_interceptor {
TABLE_LIST *table_list;
TABLE *table;
List<Item> *fields;
ulonglong last_insert_id;
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
COPY_INFO info;
bool insert_into_view;