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:
166
sql/sql_class.h
166
sql/sql_class.h
@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user