Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
b1538f4d
Commit
b1538f4d
authored
Jul 21, 2020
by
Marko Mäkelä
Browse files
Options
Browse Files
Download
Plain Diff
Merge 10.3 into 10.4
parents
fc48c8ff
b75563cd
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
295 additions
and
93 deletions
+295
-93
mysql-test/suite/sql_sequence/kill.result
mysql-test/suite/sql_sequence/kill.result
+12
-0
mysql-test/suite/sql_sequence/kill.test
mysql-test/suite/sql_sequence/kill.test
+20
-0
mysql-test/suite/versioning/r/update.result
mysql-test/suite/versioning/r/update.result
+31
-0
mysql-test/suite/versioning/t/update.test
mysql-test/suite/versioning/t/update.test
+41
-0
sql/sql_insert.cc
sql/sql_insert.cc
+4
-0
sql/sql_sequence.cc
sql/sql_sequence.cc
+4
-0
sql/table.cc
sql/table.cc
+10
-15
storage/innobase/handler/ha_innodb.cc
storage/innobase/handler/ha_innodb.cc
+67
-0
storage/innobase/include/row0ins.h
storage/innobase/include/row0ins.h
+3
-0
storage/innobase/include/row0upd.h
storage/innobase/include/row0upd.h
+35
-10
storage/innobase/row/row0mysql.cc
storage/innobase/row/row0mysql.cc
+10
-48
storage/innobase/row/row0upd.cc
storage/innobase/row/row0upd.cc
+51
-18
storage/innobase/trx/trx0trx.cc
storage/innobase/trx/trx0trx.cc
+7
-2
No files found.
mysql-test/suite/sql_sequence/kill.result
0 → 100644
View file @
b1538f4d
#
# MDEV-16929 Assertion ... in close_thread_tables upon killing connection
# running SHOW on sequence
#
CREATE SEQUENCE s ENGINE=InnoDB;
RENAME TABLE s TO s1;
connect con1,localhost,root,,test;
SHOW CREATE SEQUENCE s1;
connection default;
KILL thread_id;
connection default;
drop sequence s1;
mysql-test/suite/sql_sequence/kill.test
0 → 100644
View file @
b1538f4d
--
source
include
/
have_innodb
.
inc
--
echo
#
--
echo
# MDEV-16929 Assertion ... in close_thread_tables upon killing connection
--
echo
# running SHOW on sequence
--
echo
#
CREATE
SEQUENCE
s
ENGINE
=
InnoDB
;
RENAME
TABLE
s
TO
s1
;
--
connect
(
con1
,
localhost
,
root
,,
test
)
--
let
$conid
=
`SELECT CONNECTION_ID()`
--
send
SHOW
CREATE
SEQUENCE
s1
;
--
connection
default
--
replace_result
$conid
thread_id
--
eval
KILL
$conid
# Cleanup
--
connection
default
drop
sequence
s1
;
mysql-test/suite/versioning/r/update.result
View file @
b1538f4d
...
...
@@ -319,3 +319,34 @@ create or replace table t1 (f point, key(f)) with system versioning engine=myisa
update t1 set f = null where f = 'foo';
ERROR 22003: Cannot get geometry object from data you send to the GEOMETRY field
drop table t1;
#
# MDEV-22061 InnoDB: Assertion of missing row in sec index row_start upon REPLACE on a system-versioned table
#
create or replace table t1 (
a int,
b int,
row_start bigint(20) unsigned generated always as row start,
row_end bigint(20) unsigned generated always as row end,
unique key (b,row_end),
key (row_start),
period for system_time (row_start,row_end)
) engine=innodb with system versioning;
insert into t1 (a, b) values (1, 2);
replace into t1 (a, b) values (3, 2);
replace into t1 (a, b) values (4, 2);
drop table t1;
#
# MDEV-20661 Virtual fields are not recalculated on system fields value assignment
#
create table t1 (
a int,
row_start SYS_DATATYPE as row start invisible,
row_end SYS_DATATYPE as row end invisible,
period for system_time (row_start, row_end),
v1 bigint unsigned as (a ^ row_start) unique,
v2 bigint unsigned as (a ^ row_end) unique
) engine=innodb with system versioning;
insert into t1 (a) values (1), (2);
update ignore t1 set a= 3;
delete history from t1;
drop table t1;
mysql-test/suite/versioning/t/update.test
View file @
b1538f4d
...
...
@@ -245,4 +245,45 @@ update t1 set f = null where f = 'foo';
# cleanup
drop
table
t1
;
--
echo
#
--
echo
# MDEV-22061 InnoDB: Assertion of missing row in sec index row_start upon REPLACE on a system-versioned table
--
echo
#
create
or
replace
table
t1
(
a
int
,
b
int
,
row_start
bigint
(
20
)
unsigned
generated
always
as
row
start
,
row_end
bigint
(
20
)
unsigned
generated
always
as
row
end
,
unique
key
(
b
,
row_end
),
key
(
row_start
),
period
for
system_time
(
row_start
,
row_end
)
)
engine
=
innodb
with
system
versioning
;
insert
into
t1
(
a
,
b
)
values
(
1
,
2
);
replace
into
t1
(
a
,
b
)
values
(
3
,
2
);
replace
into
t1
(
a
,
b
)
values
(
4
,
2
);
# cleanup
drop
table
t1
;
--
echo
#
--
echo
# MDEV-20661 Virtual fields are not recalculated on system fields value assignment
--
echo
#
replace_result
$sys_datatype_expl
SYS_DATATYPE
;
eval
create
table
t1
(
a
int
,
row_start
$sys_datatype_expl
as
row
start
invisible
,
row_end
$sys_datatype_expl
as
row
end
invisible
,
period
for
system_time
(
row_start
,
row_end
),
v1
bigint
unsigned
as
(
a
^
row_start
)
unique
,
v2
bigint
unsigned
as
(
a
^
row_end
)
unique
)
engine
=
innodb
with
system
versioning
;
insert
into
t1
(
a
)
values
(
1
),
(
2
);
update
ignore
t1
set
a
=
3
;
delete
history
from
t1
;
# cleanup
drop
table
t1
;
source
suite
/
versioning
/
common_finish
.
inc
;
sql/sql_insert.cc
View file @
b1538f4d
...
...
@@ -1682,6 +1682,10 @@ int vers_insert_history_row(TABLE *table)
if
(
row_start
->
cmp
(
row_start
->
ptr
,
row_end
->
ptr
)
>=
0
)
return
0
;
if
(
table
->
vfield
&&
table
->
update_virtual_fields
(
table
->
file
,
VCOL_UPDATE_FOR_READ
))
return
HA_ERR_GENERIC
;
return
table
->
file
->
ha_write_row
(
table
->
record
[
0
]);
}
...
...
sql/sql_sequence.cc
View file @
b1538f4d
...
...
@@ -485,6 +485,10 @@ int SEQUENCE::read_initial_values(TABLE *table)
if
(
mdl_lock_used
)
thd
->
mdl_context
.
release_lock
(
mdl_request
.
ticket
);
write_unlock
(
table
);
if
(
!
has_active_transaction
&&
!
thd
->
transaction
.
stmt
.
is_empty
()
&&
!
thd
->
in_sub_stmt
)
trans_commit_stmt
(
thd
);
DBUG_RETURN
(
HA_ERR_LOCK_WAIT_TIMEOUT
);
}
DBUG_ASSERT
(
table
->
reginfo
.
lock_type
==
TL_READ
);
...
...
sql/table.cc
View file @
b1538f4d
...
...
@@ -8546,29 +8546,24 @@ void TABLE::vers_update_fields()
bitmap_set_bit
(
write_set
,
vers_start_field
()
->
field_index
);
bitmap_set_bit
(
write_set
,
vers_end_field
()
->
field_index
);
if
(
versioned
(
VERS_TIMESTAMP
))
{
if
(
!
vers_write
)
{
file
->
column_bitmaps_signal
();
return
;
}
if
(
vers_start_field
()
->
store_timestamp
(
in_use
->
query_start
(),
if
(
versioned
(
VERS_TIMESTAMP
)
&&
vers_start_field
()
->
store_timestamp
(
in_use
->
query_start
(),
in_use
->
query_start_sec_part
()))
DBUG_ASSERT
(
0
);
}
else
{
if
(
!
vers_write
)
{
file
->
column_bitmaps_signal
();
return
;
}
DBUG_ASSERT
(
0
);
}
vers_end_field
()
->
set_max
();
bitmap_set_bit
(
read_set
,
vers_end_field
()
->
field_index
);
file
->
column_bitmaps_signal
();
if
(
vfield
)
update_virtual_fields
(
file
,
VCOL_UPDATE_FOR_READ
);
}
...
...
storage/innobase/handler/ha_innodb.cc
View file @
b1538f4d
...
...
@@ -21707,3 +21707,70 @@ ib_push_frm_error(
break
;
}
}
/** Writes 8 bytes to nth tuple field
@param[in] tuple where to write
@param[in] nth index in tuple
@param[in] data what to write
@param[in] buf field data buffer */
static
void
set_tuple_col_8
(
dtuple_t
*
tuple
,
int
col
,
uint64_t
data
,
byte
*
buf
)
{
dfield_t
*
dfield
=
dtuple_get_nth_field
(
tuple
,
col
);
ut_ad
(
dfield
->
type
.
len
==
8
);
if
(
dfield
->
len
==
UNIV_SQL_NULL
)
{
dfield_set_data
(
dfield
,
buf
,
8
);
}
ut_ad
(
dfield
->
len
==
dfield
->
type
.
len
&&
dfield
->
data
);
mach_write_to_8
(
dfield
->
data
,
data
);
}
void
ins_node_t
::
vers_update_end
(
row_prebuilt_t
*
prebuilt
,
bool
history_row
)
{
ut_ad
(
prebuilt
->
ins_node
==
this
);
trx_t
*
trx
=
prebuilt
->
trx
;
#ifndef DBUG_OFF
ut_ad
(
table
->
vers_start
!=
table
->
vers_end
);
const
mysql_row_templ_t
*
t
=
prebuilt
->
get_template_by_col
(
table
->
vers_end
);
ut_ad
(
t
);
ut_ad
(
t
->
mysql_col_len
==
8
);
#endif
if
(
history_row
)
{
set_tuple_col_8
(
row
,
table
->
vers_end
,
trx
->
id
,
vers_end_buf
);
}
else
/* ROW_INS_VERSIONED */
{
set_tuple_col_8
(
row
,
table
->
vers_end
,
TRX_ID_MAX
,
vers_end_buf
);
#ifndef DBUG_OFF
t
=
prebuilt
->
get_template_by_col
(
table
->
vers_start
);
ut_ad
(
t
);
ut_ad
(
t
->
mysql_col_len
==
8
);
#endif
set_tuple_col_8
(
row
,
table
->
vers_start
,
trx
->
id
,
vers_start_buf
);
}
dict_index_t
*
clust_index
=
dict_table_get_first_index
(
table
);
THD
*
thd
=
trx
->
mysql_thd
;
TABLE
*
mysql_table
=
prebuilt
->
m_mysql_table
;
mem_heap_t
*
local_heap
=
NULL
;
for
(
ulint
col_no
=
0
;
col_no
<
dict_table_get_n_v_cols
(
table
);
col_no
++
)
{
const
dict_v_col_t
*
v_col
=
dict_table_get_nth_v_col
(
table
,
col_no
);
for
(
ulint
i
=
0
;
i
<
unsigned
(
v_col
->
num_base
);
i
++
)
{
dict_col_t
*
base_col
=
v_col
->
base_col
[
i
];
if
(
base_col
->
ind
==
table
->
vers_end
)
{
innobase_get_computed_value
(
row
,
v_col
,
clust_index
,
&
local_heap
,
table
->
heap
,
NULL
,
thd
,
mysql_table
,
mysql_table
->
record
[
0
],
NULL
,
NULL
,
NULL
);
}
}
}
if
(
local_heap
)
{
mem_heap_free
(
local_heap
);
}
}
storage/innobase/include/row0ins.h
View file @
b1538f4d
...
...
@@ -163,6 +163,8 @@ row_ins_step(
#define INS_NODE_INSERT_ENTRIES 3
/* index entries should be built and
inserted */
struct
row_prebuilt_t
;
/** Insert node structure */
struct
ins_node_t
{
...
...
@@ -203,6 +205,7 @@ struct ins_node_t
entry_list and sys fields are stored here;
if this is NULL, entry list should be created
and buffers for sys fields in row allocated */
void
vers_update_end
(
row_prebuilt_t
*
prebuilt
,
bool
history_row
);
};
/** Create an insert object.
...
...
storage/innobase/include/row0upd.h
View file @
b1538f4d
...
...
@@ -429,6 +429,31 @@ struct upd_t{
fields
[
n_fields
++
]
=
field
;
}
void
remove_element
(
ulint
i
)
{
ut_ad
(
n_fields
>
0
);
ut_ad
(
i
<
n_fields
);
while
(
i
<
n_fields
-
1
)
{
fields
[
i
]
=
fields
[
i
+
1
];
i
++
;
}
n_fields
--
;
}
bool
remove
(
const
ulint
field_no
)
{
for
(
ulint
i
=
0
;
i
<
n_fields
;
++
i
)
{
if
(
field_no
==
fields
[
i
].
field_no
)
{
remove_element
(
i
);
return
true
;
}
}
return
false
;
}
/** Determine if the given field_no is modified.
@return true if modified, false otherwise. */
bool
is_modified
(
const
ulint
field_no
)
const
...
...
@@ -569,24 +594,24 @@ struct upd_node_t{
make_versioned_delete().
@param[in] trx transaction
@param[in] vers_sys_idx table->row_start or table->row_end */
void
make_versioned_helper
(
const
trx_t
*
trx
,
ulint
idx
);
void
vers_update_fields
(
const
trx_t
*
trx
,
ulint
idx
);
public:
/** Also set row_start = CURRENT_TIMESTAMP/trx->id
@param[in] trx transaction */
void
make_versioned_update
(
const
trx_t
*
trx
)
void
vers_make_update
(
const
trx_t
*
trx
)
{
make_versioned_helper
(
trx
,
table
->
vers_start
);
vers_update_fields
(
trx
,
table
->
vers_start
);
}
/** Only set row_end = CURRENT_TIMESTAMP/trx->id.
Do not touch other fields at all.
@param[in] trx transaction */
void
make_versioned_delete
(
const
trx_t
*
trx
)
void
vers_make_delete
(
const
trx_t
*
trx
)
{
update
->
n_fields
=
0
;
is_delete
=
VERSIONED_DELETE
;
make_versioned_helper
(
trx
,
table
->
vers_end
);
vers_update_fields
(
trx
,
table
->
vers_end
);
}
};
...
...
storage/innobase/row/row0mysql.cc
View file @
b1538f4d
...
...
@@ -1332,23 +1332,6 @@ row_mysql_get_table_status(
return
(
err
);
}
/** Writes 8 bytes to nth tuple field
@param[in] tuple where to write
@param[in] nth index in tuple
@param[in] data what to write
@param[in] buf field data buffer */
static
void
set_tuple_col_8
(
dtuple_t
*
tuple
,
int
col
,
uint64_t
data
,
byte
*
buf
)
{
dfield_t
*
dfield
=
dtuple_get_nth_field
(
tuple
,
col
);
ut_ad
(
dfield
->
type
.
len
==
8
);
if
(
dfield
->
len
==
UNIV_SQL_NULL
)
{
dfield_set_data
(
dfield
,
buf
,
8
);
}
ut_ad
(
dfield
->
len
==
dfield
->
type
.
len
&&
dfield
->
data
);
mach_write_to_8
(
dfield
->
data
,
data
);
}
/** Does an insert for MySQL.
@param[in] mysql_rec row in the MySQL format
@param[in,out] prebuilt prebuilt struct in MySQL handle
...
...
@@ -1416,28 +1399,7 @@ row_insert_for_mysql(
&
blob_heap
);
if
(
ins_mode
!=
ROW_INS_NORMAL
)
{
#ifndef DBUG_OFF
ut_ad
(
table
->
vers_start
!=
table
->
vers_end
);
const
mysql_row_templ_t
*
t
=
prebuilt
->
get_template_by_col
(
table
->
vers_end
);
ut_ad
(
t
);
ut_ad
(
t
->
mysql_col_len
==
8
);
#endif
if
(
ins_mode
==
ROW_INS_HISTORICAL
)
{
set_tuple_col_8
(
node
->
row
,
table
->
vers_end
,
trx
->
id
,
node
->
vers_end_buf
);
}
else
/* ROW_INS_VERSIONED */
{
set_tuple_col_8
(
node
->
row
,
table
->
vers_end
,
TRX_ID_MAX
,
node
->
vers_end_buf
);
#ifndef DBUG_OFF
t
=
prebuilt
->
get_template_by_col
(
table
->
vers_start
);
ut_ad
(
t
);
ut_ad
(
t
->
mysql_col_len
==
8
);
#endif
set_tuple_col_8
(
node
->
row
,
table
->
vers_start
,
trx
->
id
,
node
->
vers_start_buf
);
}
node
->
vers_update_end
(
prebuilt
,
ins_mode
==
ROW_INS_HISTORICAL
);
}
savept
=
trx_savept_take
(
trx
);
...
...
@@ -1872,9 +1834,9 @@ row_update_for_mysql(row_prebuilt_t* prebuilt)
if
(
prebuilt
->
versioned_write
)
{
if
(
node
->
is_delete
==
VERSIONED_DELETE
)
{
node
->
make_versioned
_delete
(
trx
);
node
->
vers_make
_delete
(
trx
);
}
else
if
(
node
->
update
->
affects_versioned
())
{
node
->
make_versioned
_update
(
trx
);
node
->
vers_make
_update
(
trx
);
}
}
...
...
@@ -2240,13 +2202,13 @@ row_update_cascade_for_mysql(
if
(
table
->
versioned
())
{
if
(
node
->
is_delete
==
PLAIN_DELETE
)
{
node
->
make_versioned
_delete
(
trx
);
node
->
vers_make
_delete
(
trx
);
}
else
if
(
node
->
update
->
affects_versioned
())
{
dberr_t
err
=
row_update_vers_insert
(
thr
,
node
);
if
(
err
!=
DB_SUCCESS
)
{
return
err
;
}
node
->
make_versioned
_update
(
trx
);
node
->
vers_make
_update
(
trx
);
}
}
...
...
storage/innobase/row/row0upd.cc
View file @
b1538f4d
...
...
@@ -3477,32 +3477,65 @@ Supposed to be called only by make_versioned_update() and
make_versioned_delete().
@param[in] trx transaction
@param[in] vers_sys_idx table->row_start or table->row_end */
void
upd_node_t
::
make_versioned_helper
(
const
trx_t
*
trx
,
ulint
idx
)
void
upd_node_t
::
vers_update_fields
(
const
trx_t
*
trx
,
ulint
idx
)
{
ut_ad
(
in_mysql_interface
);
// otherwise needs to recalculate
// node->cmpl_info
ut_ad
(
idx
==
table
->
vers_start
||
idx
==
table
->
vers_end
);
dict_index_t
*
clust_index
=
dict_table_get_first_index
(
table
);
const
dict_col_t
*
col
=
dict_table_get_nth_col
(
table
,
idx
);
ulint
field_no
=
dict_col_get_clust_pos
(
col
,
clust_index
);
upd_field_t
*
ufield
;
for
(
ulint
i
=
0
;
i
<
update
->
n_fields
;
++
i
)
{
if
(
update
->
fields
[
i
].
field_no
==
field_no
)
{
ufield
=
&
update
->
fields
[
i
];
goto
skip_append
;
}
}
/* row_create_update_node_for_mysql() pre-allocated this much.
At least one PK column always remains unchanged. */
ut_ad
(
update
->
n_fields
<
ulint
(
table
->
n_cols
+
table
->
n_v_cols
));
update
->
n_fields
++
;
upd_field_t
*
ufield
=
upd_get_nth_field
(
update
,
update
->
n_fields
-
1
);
const
dict_col_t
*
col
=
dict_table_get_nth_col
(
table
,
idx
);
upd_field_set_field_no
(
ufield
,
dict_col_get_clust_pos
(
col
,
clust_index
),
clust_index
);
ufield
=
upd_get_nth_field
(
update
,
update
->
n_fields
-
1
);
upd_field_set_field_no
(
ufield
,
field_no
,
clust_index
);
char
*
where
=
reinterpret_cast
<
char
*>
(
update
->
vers_sys_value
);
if
(
col
->
vers_native
())
{
skip_append:
char
*
where
=
reinterpret_cast
<
char
*>
(
update
->
vers_sys_value
);
if
(
col
->
vers_native
())
{
mach_write_to_8
(
where
,
trx
->
id
);
}
else
{
}
else
{
thd_get_query_start_data
(
trx
->
mysql_thd
,
where
);
}
dfield_set_data
(
&
ufield
->
new_val
,
update
->
vers_sys_value
,
col
->
len
);
}
for
(
ulint
col_no
=
0
;
col_no
<
dict_table_get_n_v_cols
(
table
);
col_no
++
)
{
const
dict_v_col_t
*
v_col
=
dict_table_get_nth_v_col
(
table
,
col_no
);
if
(
!
v_col
->
m_col
.
ord_part
)
continue
;
for
(
ulint
i
=
0
;
i
<
unsigned
(
v_col
->
num_base
);
i
++
)
{
dict_col_t
*
base_col
=
v_col
->
base_col
[
i
];
if
(
base_col
->
ind
==
col
->
ind
)
{
/* Virtual column depends on system field value
which we updated above. Remove it from update
vector, so it is recalculated in
row_upd_store_v_row() (see !update branch). */
update
->
remove
(
v_col
->
v_pos
);
break
;
}
}
}
}
storage/innobase/trx/trx0trx.cc
View file @
b1538f4d
...
...
@@ -1288,7 +1288,8 @@ trx_update_mod_tables_timestamp(
dict_table_t
*
table
=
it
->
first
;
table
->
update_time
=
now
;
#ifdef UNIV_DEBUG
if
(
preserve_tables
||
table
->
get_ref_count
())
{
if
(
preserve_tables
||
table
->
get_ref_count
()
||
UT_LIST_GET_LEN
(
table
->
locks
))
{
/* do not evict when committing DDL operations
or if some other transaction is holding the
table handle */
...
...
@@ -1297,7 +1298,11 @@ trx_update_mod_tables_timestamp(
/* recheck while holding the mutex that blocks
table->acquire() */
mutex_enter
(
&
dict_sys
.
mutex
);
if
(
!
table
->
get_ref_count
())
{
mutex_enter
(
&
lock_sys
.
mutex
);
const
bool
do_evict
=
!
table
->
get_ref_count
()
&&
!
UT_LIST_GET_LEN
(
table
->
locks
);
mutex_exit
(
&
lock_sys
.
mutex
);
if
(
do_evict
)
{
dict_sys
.
remove
(
table
,
true
);
}
mutex_exit
(
&
dict_sys
.
mutex
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment