Skip to content

Commit

Permalink
Adding support for auto_increment in the partition engine.
Browse files Browse the repository at this point in the history
Contains Spiral patches:
022_mariadb-10.2.0.auto_increment.diff               MDEV-7720
030: 030_mariadb-10.2.0.partition_auto_inc_init.diff MDEV-7726

These patches have the following differences compared to the original
patches:
- Added the new #defines for the feature in spd_environ.h instead of in
  handler.h because these #defines are needed by Spider and are not needed
  by the server.
- Cleaned up code related to the removed variable m_need_info_for_auto_inc
. Changed variable assignment in lock_auto_increment() and
  unlock_auto_increment() so that the assignments are done under locks.
- Added a test case.
- Added test result changes resulting from a bug that was fixed by these
  patches.

Original author: Kentoku SHIBA
First reviewer:  Jacob Mathew
Second reviewer: Michael Widenius
  • Loading branch information
montywi committed Dec 3, 2017
1 parent 2f09b28 commit dc17ac1
Show file tree
Hide file tree
Showing 9 changed files with 532 additions and 29 deletions.
101 changes: 87 additions & 14 deletions sql/ha_partition.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4231,15 +4231,8 @@ int ha_partition::write_row(uchar * buf)
*/
if (have_auto_increment)
{
if (!part_share->auto_inc_initialized &&
!table_share->next_number_keypart)
{
/*
If auto_increment in table_share is not initialized, start by
initializing it.
*/
info(HA_STATUS_AUTO);
}
if (!table_share->next_number_keypart)
update_next_auto_inc_val();
error= update_auto_increment();

/*
Expand Down Expand Up @@ -4432,8 +4425,11 @@ int ha_partition::update_row(const uchar *old_data, const uchar *new_data)
bitmap_is_set(table->write_set,
table->found_next_number_field->field_index))
{
if (!part_share->auto_inc_initialized)
info(HA_STATUS_AUTO);
update_next_auto_inc_val();
/*
The following call is safe as part_share->auto_inc_initialized
(tested in the call) is guaranteed to be set for update statements.
*/
set_auto_increment_if_higher(table->found_next_number_field);
}
DBUG_RETURN(error);
Expand Down Expand Up @@ -8119,7 +8115,8 @@ int ha_partition::info(uint flag)
{
set_if_bigger(part_share->next_auto_inc_val,
auto_increment_value);
part_share->auto_inc_initialized= true;
if (can_use_for_auto_inc_init())
part_share->auto_inc_initialized= true;
DBUG_PRINT("info", ("initializing next_auto_inc_val to %lu",
(ulong) part_share->next_auto_inc_val));
}
Expand Down Expand Up @@ -10088,6 +10085,82 @@ int ha_partition::cmp_ref(const uchar *ref1, const uchar *ref2)
****************************************************************************/


/**
Retreive new values for part_share->next_auto_inc_val if needed
This is needed if the value has not been initialized or if one of
the underlying partitions require that the value should be re-calculated
*/

void ha_partition::update_next_auto_inc_val()
{
if (!part_share->auto_inc_initialized ||
need_info_for_auto_inc())
info(HA_STATUS_AUTO);
}


/**
Determine whether a partition needs auto-increment initialization.
@return
TRUE A partition needs auto-increment initialization
FALSE No partition needs auto-increment initialization
Resets part_share->auto_inc_initialized if next auto_increment needs to be
recalculated.
*/

bool ha_partition::need_info_for_auto_inc()
{
handler **file= m_file;
DBUG_ENTER("ha_partition::need_info_for_auto_inc");

do
{
if ((*file)->need_info_for_auto_inc())
{
/* We have to get new auto_increment values from handler */
part_share->auto_inc_initialized= FALSE;
DBUG_RETURN(TRUE);
}
} while (*(++file));
DBUG_RETURN(FALSE);
}


/**
Determine if all partitions can use the current auto-increment value for
auto-increment initialization.
@return
TRUE All partitions can use the current auto-increment
value for auto-increment initialization
FALSE All partitions cannot use the current
auto-increment value for auto-increment
initialization
Notes
This function is only called for ::info(HA_STATUS_AUTO) and is
mainly used by the Spider engine, which returns false
except in the case of DROP TABLE or ALTER TABLE when it returns TRUE.
Other engines always returns TRUE for this call.
*/

bool ha_partition::can_use_for_auto_inc_init()
{
handler **file= m_file;
DBUG_ENTER("ha_partition::can_use_for_auto_inc_init");

do
{
if (!(*file)->can_use_for_auto_inc_init())
DBUG_RETURN(FALSE);
} while (*(++file));
DBUG_RETURN(TRUE);
}


int ha_partition::reset_auto_increment(ulonglong value)
{
handler **file= m_file;
Expand Down Expand Up @@ -10177,8 +10250,8 @@ void ha_partition::get_auto_increment(ulonglong offset, ulonglong increment,
based replication. Because the statement-based binary log contains
only the first generated value used by the statement, and slaves assumes
all other generated values used by this statement were consecutive to
this first one, we must exclusively lock the generator until the statement
is done.
this first one, we must exclusively lock the generator until the
statement is done.
*/
if (!auto_increment_safe_stmt_log_lock &&
thd->lex->sql_command != SQLCOM_INSERT &&
Expand Down
16 changes: 10 additions & 6 deletions sql/ha_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -1137,23 +1137,26 @@ class ha_partition :public handler
auto_increment_column_changed
-------------------------------------------------------------------------
*/
virtual bool need_info_for_auto_inc();
virtual bool can_use_for_auto_inc_init();
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
ulonglong *first_value,
ulonglong *nb_reserved_values);
virtual void release_auto_increment();
private:
virtual int reset_auto_increment(ulonglong value);
void update_next_auto_inc_val();
virtual void lock_auto_increment()
{
/* lock already taken */
if (auto_increment_safe_stmt_log_lock)
return;
DBUG_ASSERT(!auto_increment_lock);
if(table_share->tmp_table == NO_TMP_TABLE)
if (table_share->tmp_table == NO_TMP_TABLE)
{
auto_increment_lock= TRUE;
part_share->lock_auto_inc();
DBUG_ASSERT(!auto_increment_lock);
auto_increment_lock= TRUE;
}
}
virtual void unlock_auto_increment()
Expand All @@ -1163,18 +1166,19 @@ class ha_partition :public handler
It will be set to false and thus unlocked at the end of the statement by
ha_partition::release_auto_increment.
*/
if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
if (auto_increment_lock && !auto_increment_safe_stmt_log_lock)
{
part_share->unlock_auto_inc();
auto_increment_lock= FALSE;
part_share->unlock_auto_inc();
}
}
virtual void set_auto_increment_if_higher(Field *field)
{
ulonglong nr= (((Field_num*) field)->unsigned_flag ||
field->val_int() > 0) ? field->val_int() : 0;
lock_auto_increment();
DBUG_ASSERT(part_share->auto_inc_initialized);
DBUG_ASSERT(part_share->auto_inc_initialized ||
!can_use_for_auto_inc_init());
/* must check when the mutex is taken */
if (nr >= part_share->next_auto_inc_val)
part_share->next_auto_inc_val= nr + 1;
Expand Down
2 changes: 2 additions & 0 deletions sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -3395,6 +3395,8 @@ class handler :public Sql_alloc
virtual void try_semi_consistent_read(bool) {}
virtual void unlock_row() {}
virtual int start_stmt(THD *thd, thr_lock_type lock_type) {return 0;}
virtual bool need_info_for_auto_inc() { return 0; }
virtual bool can_use_for_auto_inc_init() { return 1; }
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
ulonglong nb_desired_values,
ulonglong *first_value,
Expand Down
186 changes: 186 additions & 0 deletions storage/spider/mysql-test/spider/r/auto_increment.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
for master_1
for child2
child2_1
child2_2
child2_3
for child3
child3_1
child3_2
child3_3

drop and create databases
connection master_1;
DROP DATABASE IF EXISTS auto_test_local;
CREATE DATABASE auto_test_local;
USE auto_test_local;
connection child2_1;
SET @old_log_output = @@global.log_output;
SET GLOBAL log_output = 'TABLE,FILE';
DROP DATABASE IF EXISTS auto_test_remote;
CREATE DATABASE auto_test_remote;
USE auto_test_remote;

test select 1
connection master_1;
SELECT 1;
1
1
connection child2_1;
SELECT 1;
1
1

create table select test
connection child2_1;
CHILD2_1_DROP_TABLES
CHILD2_1_CREATE_TABLES
TRUNCATE TABLE mysql.general_log;
connection master_1;
DROP TABLE IF EXISTS tbl_a;
CREATE TABLE tbl_a (
col_a INT NOT NULL AUTO_INCREMENT,
col_b VARCHAR(20) DEFAULT 'defg',
col_c INT NOT NULL DEFAULT 100,
PRIMARY KEY(col_a)
) MASTER_1_ENGINE MASTER_1_AUTO_INCREMENT_2_1 MASTER_1_COMMENT_2_1
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` int(11) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
INSERT INTO tbl_a () VALUES ();
INSERT INTO tbl_a () VALUES ();
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` int(11) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
ALTER TABLE tbl_a MODIFY col_c MEDIUMINT NOT NULL DEFAULT 100;
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
RENAME TABLE tbl_a TO tbl_x;
SHOW CREATE TABLE tbl_x;
Table Create Table
tbl_x CREATE TABLE `tbl_x` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
RENAME TABLE tbl_x TO tbl_a;
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
INSERT INTO tbl_a () VALUES ();
INSERT INTO tbl_a () VALUES ();
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
MASTER_1_AUTO_INCREMENT1
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=30 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
INSERT INTO tbl_a () VALUES ();
INSERT INTO tbl_a () VALUES ();
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=5 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
MASTER_1_AUTO_INCREMENT2
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=20 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'
INSERT INTO tbl_a () VALUES ();
INSERT INTO tbl_a () VALUES ();
SHOW CREATE TABLE tbl_a;
Table Create Table
tbl_a CREATE TABLE `tbl_a` (
`col_a` int(11) NOT NULL AUTO_INCREMENT,
`col_b` varchar(20) DEFAULT 'defg',
`col_c` mediumint(9) NOT NULL DEFAULT 100,
PRIMARY KEY (`col_a`)
) ENGINE=SPIDER AUTO_INCREMENT=7 DEFAULT CHARSET=latin1 COMMENT='database "auto_test_remote", table "tbl_a", srv "s_2_1", aim "0"'

select test
connection child2_1;
TRUNCATE TABLE mysql.general_log;
connection master_1;
SELECT * FROM tbl_a;
col_a col_b col_c
1 def 10
2 def 10
3 def 10
4 def 10
5 def 10
6 def 10
7 def 10
8 def 10
connection child2_1;
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %';
argument
select `col_a`,`col_b`,`col_c` from `auto_test_remote`.`tbl_a`
SELECT argument FROM mysql.general_log WHERE argument LIKE '%select %'
SELECT col_a, col_b, col_c FROM tbl_a ORDER BY col_a;
col_a col_b col_c
1 def 10
2 def 10
3 def 10
4 def 10
5 def 10
6 def 10
7 def 10
8 def 10

deinit
connection master_1;
DROP DATABASE IF EXISTS auto_test_local;
connection child2_1;
DROP DATABASE IF EXISTS auto_test_remote;
SET GLOBAL log_output = @old_log_output;
for master_1
for child2
child2_1
child2_2
child2_3
for child3
child3_1
child3_2
child3_3

end of test
Loading

0 comments on commit dc17ac1

Please sign in to comment.