mirror of
https://github.com/MariaDB/server.git
synced 2025-07-18 23:03:28 +03:00
Merge 10.3 into 10.4
This commit is contained in:
@ -687,7 +687,23 @@ DROP TABLE t1,t2;
|
|||||||
# End of 10.0 tests
|
# End of 10.0 tests
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# Start of 10.4 tests
|
# MDEV-17551
|
||||||
|
# Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
|
||||||
|
# pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
|
||||||
|
# thread)' failed in _ma_state_info_write or ER_CRASHED_ON_USAGE
|
||||||
|
# upon SELECT with UNION
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (b BLOB, vb BLOB AS (b) VIRTUAL);
|
||||||
|
INSERT INTO t1 (b) VALUES ('foobar');
|
||||||
|
SELECT 'foo' AS f1, CONVERT( 'bar' USING latin1 ) AS f2 FROM t1
|
||||||
|
UNION
|
||||||
|
SELECT b AS f1, CONVERT( vb USING latin1 ) AS f2 FROM t1;
|
||||||
|
f1 f2
|
||||||
|
foo bar
|
||||||
|
foobar foobar
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
|
# End of 10.3 tests
|
||||||
#
|
#
|
||||||
SET sql_mode='';
|
SET sql_mode='';
|
||||||
CREATE TABLE t1 (c VARCHAR(1) DEFAULT 'foo');
|
CREATE TABLE t1 (c VARCHAR(1) DEFAULT 'foo');
|
||||||
|
@ -329,9 +329,23 @@ DROP TABLE t1,t2;
|
|||||||
--echo # End of 10.0 tests
|
--echo # End of 10.0 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-17551
|
||||||
|
--echo # Assertion `(&(&share->intern_lock)->m_mutex)->count > 0 &&
|
||||||
|
--echo # pthread_equal(pthread_self(), (&(&share->intern_lock)->m_mutex)->
|
||||||
|
--echo # thread)' failed in _ma_state_info_write or ER_CRASHED_ON_USAGE
|
||||||
|
--echo # upon SELECT with UNION
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
CREATE TABLE t1 (b BLOB, vb BLOB AS (b) VIRTUAL);
|
||||||
|
INSERT INTO t1 (b) VALUES ('foobar');
|
||||||
|
SELECT 'foo' AS f1, CONVERT( 'bar' USING latin1 ) AS f2 FROM t1
|
||||||
|
UNION
|
||||||
|
SELECT b AS f1, CONVERT( vb USING latin1 ) AS f2 FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # Start of 10.4 tests
|
--echo # End of 10.3 tests
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
SET sql_mode='';
|
SET sql_mode='';
|
||||||
|
@ -110,7 +110,7 @@ SET debug_sync='alter_table_intermediate_table_created SIGNAL ready WAIT_FOR go'
|
|||||||
ALTER TABLE t1 ADD FOREIGN KEY(pk) REFERENCES t2(pk) ON UPDATE CASCADE;
|
ALTER TABLE t1 ADD FOREIGN KEY(pk) REFERENCES t2(pk) ON UPDATE CASCADE;
|
||||||
connect con1, localhost, root;
|
connect con1, localhost, root;
|
||||||
SET debug_sync='now WAIT_FOR ready';
|
SET debug_sync='now WAIT_FOR ready';
|
||||||
SET lock_wait_timeout=1;
|
SET lock_wait_timeout=0;
|
||||||
UPDATE t2 SET pk=10 WHERE pk=1;
|
UPDATE t2 SET pk=10 WHERE pk=1;
|
||||||
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
PREPARE stmt FROM 'UPDATE t2 SET pk=10 WHERE pk=1';
|
PREPARE stmt FROM 'UPDATE t2 SET pk=10 WHERE pk=1';
|
||||||
|
@ -264,6 +264,33 @@ a b c d
|
|||||||
2 3 4 1
|
2 3 4 1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
#
|
||||||
|
# MDEV-19916 Corruption after instant ADD/DROP and shrinking the tree
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
SET @old_limit = @@innodb_limit_optimistic_insert_debug;
|
||||||
|
SET GLOBAL innodb_limit_optimistic_insert_debug = 2;
|
||||||
|
INSERT INTO t1 VALUES (1),(5),(4),(3),(2);
|
||||||
|
SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit;
|
||||||
|
ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT;
|
||||||
|
SET @old_defragment = @@innodb_defragment;
|
||||||
|
SET GLOBAL innodb_defragment = 1;
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 optimize status OK
|
||||||
|
SET GLOBAL innodb_defragment = @old_defragment;
|
||||||
|
ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
SELECT * FROM t1;
|
||||||
|
a b vb
|
||||||
|
1 NULL NULL
|
||||||
|
2 NULL NULL
|
||||||
|
3 NULL NULL
|
||||||
|
4 NULL NULL
|
||||||
|
5 NULL NULL
|
||||||
|
DROP TABLE t1;
|
||||||
|
#
|
||||||
# MDEV-17899 Assertion failures on rollback of instant ADD/DROP
|
# MDEV-17899 Assertion failures on rollback of instant ADD/DROP
|
||||||
# MDEV-18098 Crash after rollback of instant DROP COLUMN
|
# MDEV-18098 Crash after rollback of instant DROP COLUMN
|
||||||
#
|
#
|
||||||
@ -299,5 +326,5 @@ SELECT variable_value-@old_instant instants
|
|||||||
FROM information_schema.global_status
|
FROM information_schema.global_status
|
||||||
WHERE variable_name = 'innodb_instant_alter_column';
|
WHERE variable_name = 'innodb_instant_alter_column';
|
||||||
instants
|
instants
|
||||||
21
|
22
|
||||||
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
|
SET GLOBAL innodb_purge_rseg_truncate_frequency = @save_frequency;
|
||||||
|
@ -140,7 +140,7 @@ send ALTER TABLE t1 ADD FOREIGN KEY(pk) REFERENCES t2(pk) ON UPDATE CASCADE;
|
|||||||
|
|
||||||
connect con1, localhost, root;
|
connect con1, localhost, root;
|
||||||
SET debug_sync='now WAIT_FOR ready';
|
SET debug_sync='now WAIT_FOR ready';
|
||||||
SET lock_wait_timeout=1; # change to 0 in 10.3
|
SET lock_wait_timeout=0;
|
||||||
--error ER_LOCK_WAIT_TIMEOUT
|
--error ER_LOCK_WAIT_TIMEOUT
|
||||||
UPDATE t2 SET pk=10 WHERE pk=1;
|
UPDATE t2 SET pk=10 WHERE pk=1;
|
||||||
PREPARE stmt FROM 'UPDATE t2 SET pk=10 WHERE pk=1';
|
PREPARE stmt FROM 'UPDATE t2 SET pk=10 WHERE pk=1';
|
||||||
|
@ -300,6 +300,31 @@ SET DEBUG_SYNC = RESET;
|
|||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # MDEV-19916 Corruption after instant ADD/DROP and shrinking the tree
|
||||||
|
--echo #
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
|
||||||
|
# Create an index tree with 2 levels of node pointer pages.
|
||||||
|
|
||||||
|
SET @old_limit = @@innodb_limit_optimistic_insert_debug;
|
||||||
|
SET GLOBAL innodb_limit_optimistic_insert_debug = 2;
|
||||||
|
INSERT INTO t1 VALUES (1),(5),(4),(3),(2);
|
||||||
|
SET GLOBAL innodb_limit_optimistic_insert_debug = @old_limit;
|
||||||
|
|
||||||
|
ALTER TABLE t1 ADD COLUMN b INT, ALGORITHM=INSTANT;
|
||||||
|
|
||||||
|
SET @old_defragment = @@innodb_defragment;
|
||||||
|
SET GLOBAL innodb_defragment = 1;
|
||||||
|
OPTIMIZE TABLE t1;
|
||||||
|
SET GLOBAL innodb_defragment = @old_defragment;
|
||||||
|
|
||||||
|
# Exploit MDEV-17468 to force the table definition to be reloaded
|
||||||
|
ALTER TABLE t1 ADD vb INT AS (b) VIRTUAL;
|
||||||
|
CHECK TABLE t1;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo #
|
||||||
--echo # MDEV-17899 Assertion failures on rollback of instant ADD/DROP
|
--echo # MDEV-17899 Assertion failures on rollback of instant ADD/DROP
|
||||||
--echo # MDEV-18098 Crash after rollback of instant DROP COLUMN
|
--echo # MDEV-18098 Crash after rollback of instant DROP COLUMN
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
CREATE TABLE t1 (c VARBINARY(65534));
|
CREATE TABLE t1 (c VARBINARY(65534));
|
||||||
CREATE TABLE t1 (c VARBINARY(65535));
|
CREATE TABLE t1 (c VARBINARY(65535));
|
||||||
Like VARCHAR(65536), they will be converted to BLOB automatically
|
Like VARCHAR(65536), they will be converted to BLOB automatically
|
||||||
in non-sctict mode.
|
in non-strict mode.
|
||||||
*/
|
*/
|
||||||
#define MAX_FIELD_VARCHARLENGTH (65535-2-1)
|
#define MAX_FIELD_VARCHARLENGTH (65535-2-1)
|
||||||
#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */
|
#define MAX_FIELD_BLOBLENGTH UINT_MAX32 /* cf field_blob::get_length() */
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2015 MariaDB Foundation.
|
Copyright (c) 2015,2019 MariaDB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -1173,6 +1173,8 @@ Type_handler::string_type_handler(uint max_octet_length)
|
|||||||
return &type_handler_long_blob;
|
return &type_handler_long_blob;
|
||||||
else if (max_octet_length >= 65536)
|
else if (max_octet_length >= 65536)
|
||||||
return &type_handler_medium_blob;
|
return &type_handler_medium_blob;
|
||||||
|
else if (max_octet_length >= MAX_FIELD_VARCHARLENGTH)
|
||||||
|
return &type_handler_blob;
|
||||||
return &type_handler_varchar;
|
return &type_handler_varchar;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2256,6 +2258,7 @@ Field *Type_handler_varchar::make_conversion_table_field(TABLE *table,
|
|||||||
const Field *target)
|
const Field *target)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(HA_VARCHAR_PACKLENGTH(metadata) <= MAX_FIELD_VARCHARLENGTH);
|
||||||
return new(table->in_use->mem_root)
|
return new(table->in_use->mem_root)
|
||||||
Field_varstring(NULL, metadata, HA_VARCHAR_PACKLENGTH(metadata),
|
Field_varstring(NULL, metadata, HA_VARCHAR_PACKLENGTH(metadata),
|
||||||
(uchar *) "", 1, Field::NONE, &empty_clex_str,
|
(uchar *) "", 1, Field::NONE, &empty_clex_str,
|
||||||
@ -3326,6 +3329,8 @@ Field *Type_handler_varchar::make_table_field(const LEX_CSTRING *name,
|
|||||||
TABLE *table) const
|
TABLE *table) const
|
||||||
|
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(HA_VARCHAR_PACKLENGTH(attr.max_length) <=
|
||||||
|
MAX_FIELD_VARCHARLENGTH);
|
||||||
return new (table->in_use->mem_root)
|
return new (table->in_use->mem_root)
|
||||||
Field_varstring(addr.ptr(), attr.max_length,
|
Field_varstring(addr.ptr(), attr.max_length,
|
||||||
HA_VARCHAR_PACKLENGTH(attr.max_length),
|
HA_VARCHAR_PACKLENGTH(attr.max_length),
|
||||||
|
@ -3494,7 +3494,8 @@ btr_lift_page_up(
|
|||||||
/* btr_page_empty() is supposed to zero-initialize the field. */
|
/* btr_page_empty() is supposed to zero-initialize the field. */
|
||||||
ut_ad(!page_get_instant(father_block->frame));
|
ut_ad(!page_get_instant(father_block->frame));
|
||||||
|
|
||||||
if (page_level == 0 && index->is_instant()) {
|
if (index->is_instant()
|
||||||
|
&& father_block->page.id.page_no() == root_page_no) {
|
||||||
ut_ad(!father_page_zip);
|
ut_ad(!father_page_zip);
|
||||||
btr_set_instant(father_block, *index, mtr);
|
btr_set_instant(father_block, *index, mtr);
|
||||||
}
|
}
|
||||||
|
@ -2366,18 +2366,11 @@ page_validate(
|
|||||||
the page record type definition */
|
the page record type definition */
|
||||||
{
|
{
|
||||||
const page_dir_slot_t* slot;
|
const page_dir_slot_t* slot;
|
||||||
mem_heap_t* heap;
|
|
||||||
byte* buf;
|
|
||||||
ulint count;
|
|
||||||
ulint own_count;
|
|
||||||
ulint rec_own_count;
|
|
||||||
ulint slot_no;
|
|
||||||
ulint data_size;
|
|
||||||
const rec_t* rec;
|
const rec_t* rec;
|
||||||
const rec_t* old_rec = NULL;
|
const rec_t* old_rec = NULL;
|
||||||
ulint offs;
|
ulint offs;
|
||||||
ulint n_slots;
|
ulint n_slots;
|
||||||
ibool ret = FALSE;
|
ibool ret = TRUE;
|
||||||
ulint i;
|
ulint i;
|
||||||
ulint* offsets = NULL;
|
ulint* offsets = NULL;
|
||||||
ulint* old_offsets = NULL;
|
ulint* old_offsets = NULL;
|
||||||
@ -2391,7 +2384,13 @@ page_validate(
|
|||||||
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
|
if (UNIV_UNLIKELY((ibool) !!page_is_comp(page)
|
||||||
!= dict_table_is_comp(index->table))) {
|
!= dict_table_is_comp(index->table))) {
|
||||||
ib::error() << "'compact format' flag mismatch";
|
ib::error() << "'compact format' flag mismatch";
|
||||||
goto func_exit2;
|
func_exit2:
|
||||||
|
ib::error() << "Apparent corruption in space "
|
||||||
|
<< page_get_space_id(page) << " page "
|
||||||
|
<< page_get_page_no(page)
|
||||||
|
<< " of index " << index->name
|
||||||
|
<< " of table " << index->table->name;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (page_is_comp(page)) {
|
if (page_is_comp(page)) {
|
||||||
if (UNIV_UNLIKELY(!page_simple_validate_new(page))) {
|
if (UNIV_UNLIKELY(!page_simple_validate_new(page))) {
|
||||||
@ -2416,19 +2415,12 @@ page_validate(
|
|||||||
if (max_trx_id == 0 || max_trx_id > sys_max_trx_id) {
|
if (max_trx_id == 0 || max_trx_id > sys_max_trx_id) {
|
||||||
ib::error() << "PAGE_MAX_TRX_ID out of bounds: "
|
ib::error() << "PAGE_MAX_TRX_ID out of bounds: "
|
||||||
<< max_trx_id << ", " << sys_max_trx_id;
|
<< max_trx_id << ", " << sys_max_trx_id;
|
||||||
goto func_exit2;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ut_ad(srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN);
|
ut_ad(srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
heap = mem_heap_create(srv_page_size + 200);
|
|
||||||
|
|
||||||
/* The following buffer is used to check that the
|
|
||||||
records in the page record heap do not overlap */
|
|
||||||
|
|
||||||
buf = static_cast<byte*>(mem_heap_zalloc(heap, srv_page_size));
|
|
||||||
|
|
||||||
/* Check first that the record heap and the directory do not
|
/* Check first that the record heap and the directory do not
|
||||||
overlap. */
|
overlap. */
|
||||||
|
|
||||||
@ -2437,20 +2429,45 @@ page_validate(
|
|||||||
if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP)
|
if (UNIV_UNLIKELY(!(page_header_get_ptr(page, PAGE_HEAP_TOP)
|
||||||
<= page_dir_get_nth_slot(page, n_slots - 1)))) {
|
<= page_dir_get_nth_slot(page, n_slots - 1)))) {
|
||||||
|
|
||||||
ib::warn() << "Record heap and dir overlap on space "
|
ib::warn() << "Record heap and directory overlap";
|
||||||
<< page_get_space_id(page) << " page "
|
goto func_exit2;
|
||||||
<< page_get_page_no(page) << " index " << index->name
|
|
||||||
<< ", " << page_header_get_ptr(page, PAGE_HEAP_TOP)
|
|
||||||
<< ", " << page_dir_get_nth_slot(page, n_slots - 1);
|
|
||||||
|
|
||||||
goto func_exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (uint16_t type = fil_page_get_type(page)) {
|
||||||
|
case FIL_PAGE_RTREE:
|
||||||
|
if (!index->is_spatial()) {
|
||||||
|
wrong_page_type:
|
||||||
|
ib::warn() << "Wrong page type " << type;
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FIL_PAGE_TYPE_INSTANT:
|
||||||
|
if (index->is_instant()
|
||||||
|
&& page_get_page_no(page) == index->page) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto wrong_page_type;
|
||||||
|
case FIL_PAGE_INDEX:
|
||||||
|
if (index->is_spatial()) {
|
||||||
|
goto wrong_page_type;
|
||||||
|
}
|
||||||
|
if (index->is_instant()
|
||||||
|
&& page_get_page_no(page) == index->page) {
|
||||||
|
goto wrong_page_type;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto wrong_page_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The following buffer is used to check that the
|
||||||
|
records in the page record heap do not overlap */
|
||||||
|
mem_heap_t* heap = mem_heap_create(srv_page_size + 200);;
|
||||||
|
byte* buf = static_cast<byte*>(mem_heap_zalloc(heap, srv_page_size));
|
||||||
|
|
||||||
/* Validate the record list in a loop checking also that
|
/* Validate the record list in a loop checking also that
|
||||||
it is consistent with the directory. */
|
it is consistent with the directory. */
|
||||||
count = 0;
|
ulint count = 0, data_size = 0, own_count = 1, slot_no = 0;
|
||||||
data_size = 0;
|
|
||||||
own_count = 1;
|
|
||||||
slot_no = 0;
|
slot_no = 0;
|
||||||
slot = page_dir_get_nth_slot(page, slot_no);
|
slot = page_dir_get_nth_slot(page, slot_no);
|
||||||
|
|
||||||
@ -2465,11 +2482,13 @@ page_validate(
|
|||||||
&& UNIV_UNLIKELY(rec_get_node_ptr_flag(rec)
|
&& UNIV_UNLIKELY(rec_get_node_ptr_flag(rec)
|
||||||
== page_is_leaf(page))) {
|
== page_is_leaf(page))) {
|
||||||
ib::error() << "'node_ptr' flag mismatch";
|
ib::error() << "'node_ptr' flag mismatch";
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
|
goto next_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) {
|
if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) {
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
|
goto next_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the records are in the ascending order */
|
/* Check that the records are in the ascending order */
|
||||||
@ -2481,16 +2500,10 @@ page_validate(
|
|||||||
|
|
||||||
/* For spatial index, on nonleaf leavel, we
|
/* For spatial index, on nonleaf leavel, we
|
||||||
allow recs to be equal. */
|
allow recs to be equal. */
|
||||||
bool rtr_equal_nodeptrs =
|
if (ret <= 0 && !(ret == 0 && index->is_spatial()
|
||||||
(ret == 0 && dict_index_is_spatial(index)
|
&& !page_is_leaf(page))) {
|
||||||
&& !page_is_leaf(page));
|
|
||||||
|
|
||||||
if (ret <= 0 && !rtr_equal_nodeptrs) {
|
ib::error() << "Records in wrong order";
|
||||||
|
|
||||||
ib::error() << "Records in wrong order on"
|
|
||||||
" space " << page_get_space_id(page)
|
|
||||||
<< " page " << page_get_page_no(page)
|
|
||||||
<< " index " << index->name;
|
|
||||||
|
|
||||||
fputs("\nInnoDB: previous record ", stderr);
|
fputs("\nInnoDB: previous record ", stderr);
|
||||||
/* For spatial index, print the mbr info.*/
|
/* For spatial index, print the mbr info.*/
|
||||||
@ -2511,7 +2524,7 @@ page_validate(
|
|||||||
putc('\n', stderr);
|
putc('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2531,41 +2544,41 @@ page_validate(
|
|||||||
offs = page_offset(rec_get_start(rec, offsets));
|
offs = page_offset(rec_get_start(rec, offsets));
|
||||||
i = rec_offs_size(offsets);
|
i = rec_offs_size(offsets);
|
||||||
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
||||||
ib::error() << "Record offset out of bounds";
|
ib::error() << "Record offset out of bounds: "
|
||||||
goto func_exit;
|
<< offs << '+' << i;
|
||||||
|
ret = FALSE;
|
||||||
|
goto next_rec;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i--) {
|
while (i--) {
|
||||||
if (UNIV_UNLIKELY(buf[offs + i])) {
|
if (UNIV_UNLIKELY(buf[offs + i])) {
|
||||||
/* No other record may overlap this */
|
ib::error() << "Record overlaps another: "
|
||||||
ib::error() << "Record overlaps another";
|
<< offs << '+' << i;
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[offs + i] = 1;
|
buf[offs + i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_is_comp(page)) {
|
if (ulint rec_own_count = page_is_comp(page)
|
||||||
rec_own_count = rec_get_n_owned_new(rec);
|
? rec_get_n_owned_new(rec)
|
||||||
} else {
|
: rec_get_n_owned_old(rec)) {
|
||||||
rec_own_count = rec_get_n_owned_old(rec);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(rec_own_count != 0)) {
|
|
||||||
/* This is a record pointed to by a dir slot */
|
/* This is a record pointed to by a dir slot */
|
||||||
if (UNIV_UNLIKELY(rec_own_count != own_count)) {
|
if (UNIV_UNLIKELY(rec_own_count != own_count)) {
|
||||||
ib::error() << "Wrong owned count "
|
ib::error() << "Wrong owned count at " << offs
|
||||||
<< rec_own_count << ", " << own_count;
|
<< ": " << rec_own_count
|
||||||
goto func_exit;
|
<< ", " << own_count;
|
||||||
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_dir_slot_get_rec(slot) != rec) {
|
if (page_dir_slot_get_rec(slot) != rec) {
|
||||||
ib::error() << "Dir slot does not"
|
ib::error() << "Dir slot does not"
|
||||||
" point to right rec";
|
" point to right rec at " << offs;
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
page_dir_slot_check(slot);
|
if (ret) {
|
||||||
|
page_dir_slot_check(slot);
|
||||||
|
}
|
||||||
|
|
||||||
own_count = 0;
|
own_count = 0;
|
||||||
if (!page_rec_is_supremum(rec)) {
|
if (!page_rec_is_supremum(rec)) {
|
||||||
@ -2574,6 +2587,7 @@ page_validate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
next_rec:
|
||||||
if (page_rec_is_supremum(rec)) {
|
if (page_rec_is_supremum(rec)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2598,14 +2612,14 @@ page_validate(
|
|||||||
}
|
}
|
||||||
} else if (UNIV_UNLIKELY(rec_get_n_owned_old(rec) == 0)) {
|
} else if (UNIV_UNLIKELY(rec_get_n_owned_old(rec) == 0)) {
|
||||||
n_owned_zero:
|
n_owned_zero:
|
||||||
ib::error() << "n owned is zero";
|
ib::error() << "n owned is zero at " << offs;
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(slot_no != n_slots - 1)) {
|
if (UNIV_UNLIKELY(slot_no != n_slots - 1)) {
|
||||||
ib::error() << "n slots wrong " << slot_no << " "
|
ib::error() << "n slots wrong " << slot_no << " "
|
||||||
<< (n_slots - 1);
|
<< (n_slots - 1);
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(ulint(page_header_get_field(page, PAGE_N_RECS))
|
if (UNIV_UNLIKELY(ulint(page_header_get_field(page, PAGE_N_RECS))
|
||||||
@ -2614,65 +2628,57 @@ n_owned_zero:
|
|||||||
ib::error() << "n recs wrong "
|
ib::error() << "n recs wrong "
|
||||||
<< page_header_get_field(page, PAGE_N_RECS)
|
<< page_header_get_field(page, PAGE_N_RECS)
|
||||||
+ PAGE_HEAP_NO_USER_LOW << " " << (count + 1);
|
+ PAGE_HEAP_NO_USER_LOW << " " << (count + 1);
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(data_size != page_get_data_size(page))) {
|
if (UNIV_UNLIKELY(data_size != page_get_data_size(page))) {
|
||||||
ib::error() << "Summed data size " << data_size
|
ib::error() << "Summed data size " << data_size
|
||||||
<< ", returned by func " << page_get_data_size(page);
|
<< ", returned by func " << page_get_data_size(page);
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check then the free list */
|
/* Check then the free list */
|
||||||
rec = page_header_get_ptr(page, PAGE_FREE);
|
for (rec = page_header_get_ptr(page, PAGE_FREE);
|
||||||
|
rec;
|
||||||
while (rec != NULL) {
|
rec = page_rec_get_next_const(rec)) {
|
||||||
offsets = rec_get_offsets(rec, index, offsets,
|
offsets = rec_get_offsets(rec, index, offsets,
|
||||||
page_is_leaf(page),
|
page_is_leaf(page),
|
||||||
ULINT_UNDEFINED, &heap);
|
ULINT_UNDEFINED, &heap);
|
||||||
if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) {
|
if (UNIV_UNLIKELY(!page_rec_validate(rec, offsets))) {
|
||||||
|
ret = FALSE;
|
||||||
goto func_exit;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
offs = page_offset(rec_get_start(rec, offsets));
|
offs = page_offset(rec_get_start(rec, offsets));
|
||||||
i = rec_offs_size(offsets);
|
i = rec_offs_size(offsets);
|
||||||
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
if (UNIV_UNLIKELY(offs + i >= srv_page_size)) {
|
||||||
ib::error() << "Record offset out of bounds";
|
ib::error() << "Free record offset out of bounds: "
|
||||||
goto func_exit;
|
<< offs << '+' << i;
|
||||||
|
ret = FALSE;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(buf[offs + i])) {
|
if (UNIV_UNLIKELY(buf[offs + i])) {
|
||||||
ib::error() << "Record overlaps another"
|
ib::error() << "Free record overlaps another: "
|
||||||
" in free list";
|
<< offs << '+' << i;
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[offs + i] = 1;
|
buf[offs + i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rec = page_rec_get_next_const(rec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
|
if (UNIV_UNLIKELY(page_dir_get_n_heap(page) != count + 1)) {
|
||||||
ib::error() << "N heap is wrong "
|
ib::error() << "N heap is wrong "
|
||||||
<< page_dir_get_n_heap(page) << " " << count + 1;
|
<< page_dir_get_n_heap(page) << " " << count + 1;
|
||||||
goto func_exit;
|
ret = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
|
||||||
|
|
||||||
func_exit:
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
if (UNIV_UNLIKELY(ret == FALSE)) {
|
if (UNIV_UNLIKELY(!ret)) {
|
||||||
func_exit2:
|
goto func_exit2;
|
||||||
ib::error() << "Apparent corruption in space "
|
|
||||||
<< page_get_space_id(page) << " page "
|
|
||||||
<< page_get_page_no(page) << " index " << index->name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return(ret);
|
return(ret);
|
||||||
|
@ -5432,7 +5432,12 @@ int _ma_sort_write_record(MARIA_SORT_PARAM *sort_param)
|
|||||||
info->cur_row.checksum= (*share->calc_check_checksum)(info,
|
info->cur_row.checksum= (*share->calc_check_checksum)(info,
|
||||||
sort_param->
|
sort_param->
|
||||||
record);
|
record);
|
||||||
reclength= _ma_rec_pack(info,from,sort_param->record);
|
if (!(reclength= _ma_rec_pack(info,from,sort_param->record)))
|
||||||
|
{
|
||||||
|
_ma_check_print_error(param,"Got error %d when packing record",
|
||||||
|
my_errno);
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
flag=0;
|
flag=0;
|
||||||
|
|
||||||
do
|
do
|
||||||
|
@ -114,8 +114,10 @@ int maria_close(register MARIA_HA *info)
|
|||||||
share->deleting ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))
|
share->deleting ? FLUSH_IGNORE_CHANGED : FLUSH_RELEASE))
|
||||||
error= my_errno;
|
error= my_errno;
|
||||||
unmap_file(info);
|
unmap_file(info);
|
||||||
if (((share->changed && share->base.born_transactional) ||
|
if (!internal_table &&
|
||||||
maria_is_crashed(info) || (share->temporary && !share->deleting)))
|
(((share->changed && share->base.born_transactional) ||
|
||||||
|
maria_is_crashed(info) ||
|
||||||
|
(share->temporary && !share->deleting))))
|
||||||
{
|
{
|
||||||
if (save_global_changed)
|
if (save_global_changed)
|
||||||
{
|
{
|
||||||
|
@ -224,6 +224,8 @@ my_bool _ma_write_dynamic_record(MARIA_HA *info, const uchar *record)
|
|||||||
{
|
{
|
||||||
ulong reclength= _ma_rec_pack(info,info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
ulong reclength= _ma_rec_pack(info,info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
||||||
record);
|
record);
|
||||||
|
if (!reclength)
|
||||||
|
return 1;
|
||||||
return (write_dynamic_record(info,info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
return (write_dynamic_record(info,info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
||||||
reclength));
|
reclength));
|
||||||
}
|
}
|
||||||
@ -234,6 +236,8 @@ my_bool _ma_update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS pos,
|
|||||||
{
|
{
|
||||||
uint length= _ma_rec_pack(info, info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
uint length= _ma_rec_pack(info, info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
||||||
record);
|
record);
|
||||||
|
if (!length)
|
||||||
|
return 1;
|
||||||
return (update_dynamic_record(info, pos,
|
return (update_dynamic_record(info, pos,
|
||||||
info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
info->rec_buff + MARIA_REC_BUFF_OFFSET,
|
||||||
length));
|
length));
|
||||||
@ -258,12 +262,19 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const uchar *record)
|
|||||||
reclength2= _ma_rec_pack(info,
|
reclength2= _ma_rec_pack(info,
|
||||||
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
||||||
record);
|
record);
|
||||||
|
if (!reclength2)
|
||||||
|
{
|
||||||
|
error= 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_PRINT("info",("reclength: %lu reclength2: %lu",
|
DBUG_PRINT("info",("reclength: %lu reclength2: %lu",
|
||||||
reclength, reclength2));
|
reclength, reclength2));
|
||||||
DBUG_ASSERT(reclength2 <= reclength);
|
DBUG_ASSERT(reclength2 <= reclength);
|
||||||
error= write_dynamic_record(info,
|
error= write_dynamic_record(info,
|
||||||
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
||||||
reclength2);
|
reclength2);
|
||||||
|
err:
|
||||||
my_safe_afree(rec_buff, reclength);
|
my_safe_afree(rec_buff, reclength);
|
||||||
return(error != 0);
|
return(error != 0);
|
||||||
}
|
}
|
||||||
@ -293,12 +304,19 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos,
|
|||||||
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
|
my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
|
||||||
return(1);
|
return(1);
|
||||||
}
|
}
|
||||||
reclength2= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
reclength2= _ma_rec_pack(info, rec_buff+
|
||||||
record);
|
ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
||||||
|
record);
|
||||||
|
if (!reclength2)
|
||||||
|
{
|
||||||
|
error= 1;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
DBUG_ASSERT(reclength2 <= reclength);
|
DBUG_ASSERT(reclength2 <= reclength);
|
||||||
error=update_dynamic_record(info,pos,
|
error=update_dynamic_record(info,pos,
|
||||||
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
|
||||||
reclength2);
|
reclength2);
|
||||||
|
err:
|
||||||
my_safe_afree(rec_buff, reclength);
|
my_safe_afree(rec_buff, reclength);
|
||||||
return(error != 0);
|
return(error != 0);
|
||||||
}
|
}
|
||||||
@ -938,7 +956,12 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pack a record. Return new reclength */
|
/**
|
||||||
|
Pack a record.
|
||||||
|
|
||||||
|
@return new reclength
|
||||||
|
@return 0 in case of wrong data in record
|
||||||
|
*/
|
||||||
|
|
||||||
uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
|
uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
|
||||||
register const uchar *from)
|
register const uchar *from)
|
||||||
@ -1042,6 +1065,11 @@ uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
|
|||||||
tmp_length= uint2korr(from);
|
tmp_length= uint2korr(from);
|
||||||
store_key_length_inc(to,tmp_length);
|
store_key_length_inc(to,tmp_length);
|
||||||
}
|
}
|
||||||
|
if (tmp_length > column->length)
|
||||||
|
{
|
||||||
|
my_errno= HA_ERR_WRONG_IN_RECORD;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
memcpy(to, from+pack_length,tmp_length);
|
memcpy(to, from+pack_length,tmp_length);
|
||||||
to+= tmp_length;
|
to+= tmp_length;
|
||||||
continue;
|
continue;
|
||||||
@ -1613,7 +1641,9 @@ my_bool _ma_cmp_dynamic_record(register MARIA_HA *info,
|
|||||||
if (!(buffer=(uchar*) my_safe_alloca(buffer_length)))
|
if (!(buffer=(uchar*) my_safe_alloca(buffer_length)))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
reclength= _ma_rec_pack(info,buffer,record);
|
if (!(reclength= _ma_rec_pack(info,buffer,record)))
|
||||||
|
goto err;
|
||||||
|
|
||||||
record= buffer;
|
record= buffer;
|
||||||
|
|
||||||
filepos= info->cur_row.lastpos;
|
filepos= info->cur_row.lastpos;
|
||||||
|
Reference in New Issue
Block a user