diff options
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | EXCEPTIONS-CLIENT | 136 | ||||
-rw-r--r-- | mysql-test/main/multi_update.result | 53 | ||||
-rw-r--r-- | mysql-test/main/multi_update.test | 53 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/foreign_key.result | 11 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/mvcc_secondary.result | 24 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/foreign_key.test | 39 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/mvcc_secondary.test | 26 | ||||
-rw-r--r-- | mysql-test/suite/vcol/r/vcol_syntax.result | 38 | ||||
-rw-r--r-- | mysql-test/suite/vcol/t/vcol_syntax.test | 44 | ||||
-rw-r--r-- | sql/gen_win_tzname_data.ps1 | 1 | ||||
-rw-r--r-- | sql/item.h | 36 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.h | 4 | ||||
-rw-r--r-- | sql/sql_delete.cc | 19 | ||||
-rw-r--r-- | sql/sql_derived.cc | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 21 | ||||
-rw-r--r-- | sql/sql_lex.h | 30 | ||||
-rw-r--r-- | sql/sql_table.cc | 55 | ||||
-rw-r--r-- | sql/sql_update.cc | 38 | ||||
-rw-r--r-- | sql/win_tzname_data.h | 1 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 32 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 3 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 94 |
24 files changed, 542 insertions, 227 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b8d000947f..f3d4ae49744 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -505,8 +505,7 @@ ADD_CUSTOM_TARGET(INFO_BIN ALL WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) -INSTALL_DOCUMENTATION(README.md CREDITS COPYING THIRDPARTY - EXCEPTIONS-CLIENT COMPONENT Readme) +INSTALL_DOCUMENTATION(README.md CREDITS COPYING THIRDPARTY COMPONENT Readme) # MDEV-6526 these files are not installed anymore #INSTALL_DOCUMENTATION(${CMAKE_BINARY_DIR}/Docs/INFO_SRC diff --git a/EXCEPTIONS-CLIENT b/EXCEPTIONS-CLIENT deleted file mode 100644 index 11ba42c422f..00000000000 --- a/EXCEPTIONS-CLIENT +++ /dev/null @@ -1,136 +0,0 @@ - FOSS License Exception - - http://www.mysql.com/about/legal/licensing/foss-exception/ - Updated February 23, 2012 - -What is the FOSS License Exception? - - Oracle's Free and Open Source Software ("FOSS") License Exception - (formerly known as the FLOSS License Exception) allows developers of FOSS - applications to include Oracle's MySQL Client Libraries (also referred to - as "MySQL Drivers" or "MySQL Connectors") with their FOSS applications. - MySQL Client Libraries are typically licensed pursuant to version 2 of the - General Public License ("GPL"), but this exception permits distribution of - certain MySQL Client Libraries with a developer's FOSS applications - licensed under the terms of another FOSS license listed below, even though - such other FOSS license may be incompatible with the GPL. - - The following terms and conditions describe the circumstances under which - Oracle's FOSS License Exception applies. - -Oracle's FOSS License Exception Terms and Conditions - - 1. Definitions. "Derivative Work" means a derivative work, as defined - under applicable copyright law, formed entirely from the Program and - one or more FOSS Applications. - - "FOSS Application" means a free and open source software application - distributed subject to a license listed in the section below titled - "FOSS License List." - - "FOSS Notice" means a notice placed by Oracle or MySQL in a copy of - the MySQL Client Libraries stating that such copy of the MySQL Client - Libraries may be distributed under Oracle's or MySQL's FOSS (or FLOSS) - License Exception. - - "Independent Work" means portions of the Derivative Work that are not - derived from the Program and can reasonably be considered independent - and separate works. - - "Program" means a copy of Oracle's MySQL Client Libraries that - contains a FOSS Notice. - - 2. A FOSS application developer ("you" or "your") may distribute a - Derivative Work provided that you and the Derivative Work meet all of - the following conditions: - - a. You obey the GPL in all respects for the Program and all portions - (including modifications) of the Program included in the - Derivative Work (provided that this condition does not apply to - Independent Works); - b. The Derivative Work does not include any work licensed under the - GPL other than the Program; - c. You distribute Independent Works subject to a license listed in - the section below titled "FOSS License List"; - d. You distribute Independent Works in object code or executable - form with the complete corresponding machine-readable source code - on the same medium and under the same FOSS license applying to - the object code or executable forms; - e. All works that are aggregated with the Program or the Derivative - Work on a medium or volume of storage are not derivative works of - the Program, Derivative Work or FOSS Application, and must - reasonably be considered independent and separate works. - - 3. Oracle reserves all rights not expressly granted in these terms and - conditions. If all of the above conditions are not met, then this FOSS - License Exception does not apply to you or your Derivative Work. - -FOSS License List - -+------------------------------------------------------------------------+ -|License Name |Version(s)/Copyright Date| -|----------------------------------------------+-------------------------| -|Academic Free License |2.0 | -|----------------------------------------------+-------------------------| -|Apache Software License |1.0/1.1/2.0 | -|----------------------------------------------+-------------------------| -|Apple Public Source License |2.0 | -|----------------------------------------------+-------------------------| -|Artistic license |From Perl 5.8.0 | -|----------------------------------------------+-------------------------| -|BSD license |"July 22 1999" | -|----------------------------------------------+-------------------------| -|Common Development and Distribution License |1.0 | -|(CDDL) | | -|----------------------------------------------+-------------------------| -|Common Public License |1.0 | -|----------------------------------------------+-------------------------| -|Eclipse Public License |1.0 | -|----------------------------------------------+-------------------------| -|European Union Public License (EUPL)¹ |1.1 | -|----------------------------------------------+-------------------------| -|GNU Affero General Public License (AGPL) |3.0 | -|----------------------------------------------+-------------------------| -|GNU Library or "Lesser" General Public License|2.0/2.1/3.0 | -|(LGPL) | | -|----------------------------------------------+-------------------------| -|GNU General Public License (GPL) |3.0 | -|----------------------------------------------+-------------------------| -|IBM Public License |1.0 | -|----------------------------------------------+-------------------------| -|Jabber Open Source License |1.0 | -|----------------------------------------------+-------------------------| -|MIT License (As listed in file |- | -|MIT-License.txt) | | -|----------------------------------------------+-------------------------| -|Mozilla Public License (MPL) |1.0/1.1 | -|----------------------------------------------+-------------------------| -|Open Software License |2.0 | -|----------------------------------------------+-------------------------| -|OpenSSL license (with original SSLeay license)|"2003" ("1998") | -|----------------------------------------------+-------------------------| -|PHP License |3.0/3.01 | -|----------------------------------------------+-------------------------| -|Python license (CNRI Python License) |- | -|----------------------------------------------+-------------------------| -|Python Software Foundation License |2.1.1 | -|----------------------------------------------+-------------------------| -|Sleepycat License |"1999" | -|----------------------------------------------+-------------------------| -|University of Illinois/NCSA Open Source |- | -|License | | -|----------------------------------------------+-------------------------| -|W3C License |"2001" | -|----------------------------------------------+-------------------------| -|X11 License |"2001" | -|----------------------------------------------+-------------------------| -|Zlib/libpng License |- | -|----------------------------------------------+-------------------------| -|Zope Public License |2.0 | -+------------------------------------------------------------------------+ - -¹) When an Independent Work is licensed under a "Compatible License" -pursuant to the EUPL, the Compatible License rather than the EUPL is the -applicable license for purposes of these FOSS License Exception Terms and -Conditions. - diff --git a/mysql-test/main/multi_update.result b/mysql-test/main/multi_update.result index d792b2828b8..4001a47ecd4 100644 --- a/mysql-test/main/multi_update.result +++ b/mysql-test/main/multi_update.result @@ -982,6 +982,59 @@ drop function f1; # # end of 5.5 tests # +# +# MDEV-24823: Invalid multi-table update of view within SP +# +create table t1 (id int) engine=myisam; +insert into t1 values (1),(2),(1); +create table t2 (pk int, c0 int) engine=myisam; +insert into t2 values (1,1), (2,3); +create view v2 as select * from t2; +create view v3 as select * from t2 where c0 < 3; +create procedure sp0() update t1, v2 set v2.pk = 1 where v2.c0 = t1.c1; +call sp0(); +ERROR 42S22: Unknown column 't1.c1' in 'where clause' +call sp0(); +ERROR 42S22: Unknown column 't1.c1' in 'where clause' +create procedure sp1() update (t1 join v2 on v2.c0 = t1.c1) set v2.pk = 1; +call sp1(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +call sp1(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +create procedure sp2() update (t1 join v3 on v3.c0 = t1.c1) set v3.pk = 1; +call sp2(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +call sp2(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +create procedure sp3() +update (t1 join v2 on v2.c0 = t1.id) set v2.c0 = v2.c0+1; +select * from t2; +pk c0 +1 1 +2 3 +call sp3(); +select * from t2; +pk c0 +1 2 +2 3 +call sp3(); +select * from t2; +pk c0 +1 3 +2 3 +create procedure sp4() delete t1 from t1 join v2 on v2.c0 = t1.c1; +call sp4(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +call sp4(); +ERROR 42S22: Unknown column 't1.c1' in 'on clause' +drop procedure sp0; +drop procedure sp1; +drop procedure sp2; +drop procedure sp3; +drop procedure sp4; +drop view v2,v3; +drop table t1,t2; +# End of 10.2 tests create table t1 (c1 int, c3 int); insert t1(c3) values (1), (2), (3), (4), (5), (6), (7), (8); create table t2 select * from t1; diff --git a/mysql-test/main/multi_update.test b/mysql-test/main/multi_update.test index 8a32f626818..84f06a7c165 100644 --- a/mysql-test/main/multi_update.test +++ b/mysql-test/main/multi_update.test @@ -958,6 +958,59 @@ drop function f1; --echo # end of 5.5 tests --echo # +--echo # +--echo # MDEV-24823: Invalid multi-table update of view within SP +--echo # + +create table t1 (id int) engine=myisam; +insert into t1 values (1),(2),(1); +create table t2 (pk int, c0 int) engine=myisam; +insert into t2 values (1,1), (2,3); +create view v2 as select * from t2; +create view v3 as select * from t2 where c0 < 3; + +create procedure sp0() update t1, v2 set v2.pk = 1 where v2.c0 = t1.c1; +--error ER_BAD_FIELD_ERROR +call sp0(); +--error ER_BAD_FIELD_ERROR +call sp0(); + +create procedure sp1() update (t1 join v2 on v2.c0 = t1.c1) set v2.pk = 1; +--error ER_BAD_FIELD_ERROR +call sp1(); +--error ER_BAD_FIELD_ERROR +call sp1(); + +create procedure sp2() update (t1 join v3 on v3.c0 = t1.c1) set v3.pk = 1; +--error ER_BAD_FIELD_ERROR +call sp2(); +--error ER_BAD_FIELD_ERROR +call sp2(); + +create procedure sp3() +update (t1 join v2 on v2.c0 = t1.id) set v2.c0 = v2.c0+1; +select * from t2; +call sp3(); +select * from t2; +call sp3(); +select * from t2; + +create procedure sp4() delete t1 from t1 join v2 on v2.c0 = t1.c1; +--error ER_BAD_FIELD_ERROR +call sp4(); +--error ER_BAD_FIELD_ERROR +call sp4(); + +drop procedure sp0; +drop procedure sp1; +drop procedure sp2; +drop procedure sp3; +drop procedure sp4; +drop view v2,v3; +drop table t1,t2; + +--echo # End of 10.2 tests + # # MDEV-13911 Support ORDER BY and LIMIT in multi-table update # diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index 34d0c3dad64..c7332f3dfc6 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -801,6 +801,17 @@ ERROR 23000: Duplicate entry '10' for key 'ind9' SET FOREIGN_KEY_CHECKS= 0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk); DROP TABLE t1; +SET FOREIGN_KEY_CHECKS= 1; +# +# MDEV-23455 Hangs + Sig11 in unknown location(s) due to single complex FK query +# +Parsing foreign keys 1... +ERROR HY000: Can't create table `test`.`t0` (errno: 150 "Foreign key constraint is incorrectly formed") +Parsing foreign keys 2... +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +Parsing foreign keys 3... +ERROR HY000: Can't create table `test`.`t1` (errno: 150 "Foreign key constraint is incorrectly formed") +Parsing foreign keys 4... # End of 10.2 tests CREATE TABLE t1 (a GEOMETRY, INDEX(a(8)), FOREIGN KEY (a) REFERENCES x (xx)) ENGINE=InnoDB; diff --git a/mysql-test/suite/innodb/r/mvcc_secondary.result b/mysql-test/suite/innodb/r/mvcc_secondary.result new file mode 100644 index 00000000000..2289742e830 --- /dev/null +++ b/mysql-test/suite/innodb/r/mvcc_secondary.result @@ -0,0 +1,24 @@ +# +# MDEV-25459 MVCC read from index on CHAR or VARCHAR wrongly omits rows +# +CREATE TABLE t1 ( +pk int PRIMARY KEY, c varchar(255) UNIQUE, +d char(255), e varchar(255), f char(255), g char(255) +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARACTER SET ucs2; +INSERT INTO t1 VALUES +(1,REPEAT('c',248),REPEAT('a',106),REPEAT('b',220),REPEAT('x',14),''); +BEGIN; +UPDATE t1 SET c=REPEAT('d',170); +connect con1,localhost,root,,; +SELECT pk FROM t1 FORCE INDEX (c); +pk +1 +connection default; +COMMIT; +connection con1; +SELECT pk FROM t1 FORCE INDEX (c); +pk +1 +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 41299e4bc35..a413ea43646 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -782,6 +782,45 @@ ALTER TABLE t1 ADD UNIQUE INDEX ind9 (b), LOCK=SHARED; SET FOREIGN_KEY_CHECKS= 0; ALTER TABLE t1 ADD FOREIGN KEY (a) REFERENCES t1 (pk); DROP TABLE t1; +SET FOREIGN_KEY_CHECKS= 1; + +--echo # +--echo # MDEV-23455 Hangs + Sig11 in unknown location(s) due to single complex FK query +--echo # +let $constr_prefix= aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa; +let $fk_ref= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx; +let $fk_field= yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy; +let $constr_count= 200; # each 100 constrs is 1 sec of test execution +let $i= 0; + +while ($i < $constr_count) +{ + let $p= $constr_prefix$i; + let $constr= CONSTRAINT $p FOREIGN KEY ($fk_field) REFERENCES t1($fk_ref) ON UPDATE SET NULL; + if ($i) + { + let $constrs= $constrs, $constr; + } + if (!$i) + { + let $constrs= $constr; + } + inc $i; +} +--disable_query_log +--echo Parsing foreign keys 1... +--error ER_CANT_CREATE_TABLE +eval create table t0($fk_field int, $constrs) engine innodb; +--echo Parsing foreign keys 2... +--error ER_CANT_CREATE_TABLE +eval create table t1($fk_field int, $constrs) engine innodb; +--echo Parsing foreign keys 3... +--error ER_CANT_CREATE_TABLE +eval create table t1($fk_ref int, $fk_field int, $constrs) engine innodb; +--echo Parsing foreign keys 4... +eval create table t1($fk_ref int primary key, $fk_field int, $constrs) engine innodb; +drop table t1; +--enable_query_log --echo # End of 10.2 tests diff --git a/mysql-test/suite/innodb/t/mvcc_secondary.test b/mysql-test/suite/innodb/t/mvcc_secondary.test new file mode 100644 index 00000000000..93c91c40076 --- /dev/null +++ b/mysql-test/suite/innodb/t/mvcc_secondary.test @@ -0,0 +1,26 @@ +--source include/innodb_page_size_small.inc + +--echo # +--echo # MDEV-25459 MVCC read from index on CHAR or VARCHAR wrongly omits rows +--echo # + +CREATE TABLE t1 ( + pk int PRIMARY KEY, c varchar(255) UNIQUE, + d char(255), e varchar(255), f char(255), g char(255) +) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARACTER SET ucs2; + +INSERT INTO t1 VALUES +(1,REPEAT('c',248),REPEAT('a',106),REPEAT('b',220),REPEAT('x',14),''); + +BEGIN; +UPDATE t1 SET c=REPEAT('d',170); + +connect (con1,localhost,root,,); +SELECT pk FROM t1 FORCE INDEX (c); +connection default; +COMMIT; +connection con1; +SELECT pk FROM t1 FORCE INDEX (c); +disconnect con1; +connection default; +DROP TABLE t1; diff --git a/mysql-test/suite/vcol/r/vcol_syntax.result b/mysql-test/suite/vcol/r/vcol_syntax.result index 16e30e57230..c8983f34c93 100644 --- a/mysql-test/suite/vcol/r/vcol_syntax.result +++ b/mysql-test/suite/vcol/r/vcol_syntax.result @@ -50,3 +50,41 @@ t1 CREATE TABLE "t1" ( ) drop table t1; set session sql_mode=@OLD_SQL_MODE; +# +# MDEV-25091 CREATE TABLE: field references qualified by a wrong table name succeed +# +create table t2 (x int); +create table t1 (x int, y int generated always as (t2.x)); +ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS' +create table t1 (x int, y int check (y > t2.x)); +ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +create table t1 (x int, y int default t2.x); +ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT' +create table t1 (x int, check (t2.x > 0)); +ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +create table t1 (x int); +alter table t1 add column y int generated always as (t2.x); +ERROR 42S22: Unknown column '`t2`.`x`' in 'GENERATED ALWAYS' +alter table t1 add column y int check (z > t2.x); +ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +alter table t1 add column y int default t2.x; +ERROR 42S22: Unknown column '`t2`.`x`' in 'DEFAULT' +alter table t1 add constraint check (t2.x > 0); +ERROR 42S22: Unknown column '`t2`.`x`' in 'CHECK' +create or replace table t1 (x int, y int generated always as (t1.x)); +create or replace table t1 (x int, y int check (y > t1.x)); +create or replace table t1 (x int, y int default t1.x); +create or replace table t1 (x int, check (t1.x > 0)); +create or replace table t1 (x int, y int generated always as (test.t1.x)); +create or replace table t1 (x int, y int check (y > test.t1.x)); +create or replace table t1 (x int, y int default test.t1.x); +create or replace table t1 (x int, check (test.t1.x > 0)); +drop tables t1, t2; +create table t1 (x int, y int generated always as (test2.t1.x)); +ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'GENERATED ALWAYS' +create table t1 (x int, y int check (y > test2.t1.x)); +ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK' +create table t1 (x int, y int default test2.t1.x); +ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'DEFAULT' +create table t1 (x int, check (test2.t1.x > 0)); +ERROR 42S22: Unknown column '`test2`.`t1`.`x`' in 'CHECK' diff --git a/mysql-test/suite/vcol/t/vcol_syntax.test b/mysql-test/suite/vcol/t/vcol_syntax.test index 6dc3cf43317..f425b52ab79 100644 --- a/mysql-test/suite/vcol/t/vcol_syntax.test +++ b/mysql-test/suite/vcol/t/vcol_syntax.test @@ -28,3 +28,47 @@ show create table t1; drop table t1; set session sql_mode=@OLD_SQL_MODE; +--echo # +--echo # MDEV-25091 CREATE TABLE: field references qualified by a wrong table name succeed +--echo # +create table t2 (x int); + +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int generated always as (t2.x)); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int check (y > t2.x)); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int default t2.x); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, check (t2.x > 0)); + +create table t1 (x int); +--error ER_BAD_FIELD_ERROR +alter table t1 add column y int generated always as (t2.x); +--error ER_BAD_FIELD_ERROR +alter table t1 add column y int check (z > t2.x); +--error ER_BAD_FIELD_ERROR +alter table t1 add column y int default t2.x; +--error ER_BAD_FIELD_ERROR +alter table t1 add constraint check (t2.x > 0); + +create or replace table t1 (x int, y int generated always as (t1.x)); +create or replace table t1 (x int, y int check (y > t1.x)); +create or replace table t1 (x int, y int default t1.x); +create or replace table t1 (x int, check (t1.x > 0)); + +create or replace table t1 (x int, y int generated always as (test.t1.x)); +create or replace table t1 (x int, y int check (y > test.t1.x)); +create or replace table t1 (x int, y int default test.t1.x); +create or replace table t1 (x int, check (test.t1.x > 0)); + +drop tables t1, t2; + +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int generated always as (test2.t1.x)); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int check (y > test2.t1.x)); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, y int default test2.t1.x); +--error ER_BAD_FIELD_ERROR +create table t1 (x int, check (test2.t1.x > 0)); diff --git a/sql/gen_win_tzname_data.ps1 b/sql/gen_win_tzname_data.ps1 index c0a37d21895..474ab889d25 100644 --- a/sql/gen_win_tzname_data.ps1 +++ b/sql/gen_win_tzname_data.ps1 @@ -4,6 +4,7 @@ write-output "/* This file was generated using gen_win_tzname_data.ps1 */" $xdoc = new-object System.Xml.XmlDocument +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 $xdoc.load("https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml") $nodes = $xdoc.SelectNodes("//mapZone[@territory='001']") # use default territory (001) foreach ($node in $nodes) { diff --git a/sql/item.h b/sql/item.h index 717e49e5b33..dbd2cb0b1df 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1938,6 +1938,15 @@ public: return 0; } + /** + Check db/table_name if they defined in item and match arg values + + @param arg Pointer to Check_table_name_prm structure + + @retval true Match failed + @retval false Match succeeded + */ + virtual bool check_table_name_processor(void *arg) { return false; } /* TRUE if the expression depends only on the table indicated by tab_map or can be converted to such an exression using equalities. @@ -2096,6 +2105,15 @@ public: bool collect; }; + struct Check_table_name_prm + { + LEX_CSTRING db; + LEX_CSTRING table_name; + String field; + Check_table_name_prm(LEX_CSTRING _db, LEX_CSTRING _table_name) : + db(_db), table_name(_table_name) {} + }; + /* For SP local variable returns pointer to Item representing its current value and pointer to current Item otherwise. @@ -3500,6 +3518,24 @@ public: } return 0; } + bool check_table_name_processor(void *arg) + { + Check_table_name_prm &p= *(Check_table_name_prm *) arg; + if (p.table_name.length && table_name) + { + DBUG_ASSERT(p.db.length); + if ((db_name && + my_strcasecmp(table_alias_charset, p.db.str, db_name)) || + my_strcasecmp(table_alias_charset, p.table_name.str, table_name)) + { + print(&p.field, (enum_query_type) (QT_ITEM_ORIGINAL_FUNC_NULLIF | + QT_NO_DATA_EXPANSION | + QT_TO_SYSTEM_CHARSET)); + return true; + } + } + return false; + } void cleanup(); Item_equal *get_item_equal() { return item_equal; } void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index a1be9e76fc8..cc6ecda9327 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7952,7 +7952,8 @@ bool setup_tables(THD *thd, Name_resolution_context *context, if (table_list->jtbm_subselect) { Item *item= table_list->jtbm_subselect->optimizer; - if (table_list->jtbm_subselect->optimizer->fix_fields(thd, &item)) + if (!table_list->jtbm_subselect->optimizer->fixed && + table_list->jtbm_subselect->optimizer->fix_fields(thd, &item)) { my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES)); /* psergey-todo: WHY ER_TOO_MANY_TABLES ???*/ DBUG_RETURN(1); diff --git a/sql/sql_class.h b/sql/sql_class.h index 6701c366f0a..d33cd1b35a4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -6267,7 +6267,8 @@ public: class multi_update :public select_result_interceptor { TABLE_LIST *all_tables; /* query/update command tables */ - List<TABLE_LIST> *leaves; /* list of leves of join table tree */ + List<TABLE_LIST> *leaves; /* list of leaves of join table tree */ + List<TABLE_LIST> updated_leaves; /* list of of updated leaves */ TABLE_LIST *update_tables; TABLE **tmp_tables, *main_table, *table_to_update; TMP_TABLE_PARAM *tmp_table_param; @@ -6305,6 +6306,7 @@ public: List<Item> *fields, List<Item> *values, enum_duplicates handle_duplicates, bool ignore); ~multi_update(); + bool init(THD *thd); int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int send_data(List<Item> &items); bool initialize_tables (JOIN *join); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index be8767af111..9fa1e015274 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB + Copyright (c) 2010, 2021, MariaDB 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 @@ -1128,14 +1128,11 @@ int mysql_multi_delete_prepare(THD *thd) FALSE, DELETE_ACL, SELECT_ACL, FALSE)) DBUG_RETURN(TRUE); - if (lex->first_select_lex()->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(TRUE); - /* Multi-delete can't be constructed over-union => we always have single SELECT on top and have to check underlying SELECTs of it */ - lex->first_select_lex()->exclude_from_table_unique_test= TRUE; + lex->first_select_lex()->set_unique_exclude(); /* Fix tables-to-be-deleted-from list to point at opened tables */ for (target_tbl= (TABLE_LIST*) aux_tables; target_tbl; @@ -1158,6 +1155,12 @@ int mysql_multi_delete_prepare(THD *thd) target_tbl->table_name.str, "DELETE"); DBUG_RETURN(TRUE); } + } + + for (target_tbl= (TABLE_LIST*) aux_tables; + target_tbl; + target_tbl= target_tbl->next_local) + { /* Check that table from which we delete is not used somewhere inside subqueries/view. @@ -1202,12 +1205,6 @@ multi_delete::prepare(List<Item> &values, SELECT_LEX_UNIT *u) unit= u; do_delete= 1; THD_STAGE_INFO(thd, stage_deleting_from_main_table); - SELECT_LEX *select_lex= u->first_select(); - if (select_lex->first_cond_optimization) - { - if (select_lex->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(TRUE); - } DBUG_RETURN(0); } diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index c5874046224..132872c4a9e 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -382,10 +382,6 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_RETURN(FALSE); } - if (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || - thd->lex->sql_command == SQLCOM_DELETE_MULTI) - thd->save_prep_leaf_list= TRUE; - arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test if (!derived->merged_for_insert || @@ -459,6 +455,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->on_expr= expr; derived->prep_on_expr= expr->copy_andor_structure(thd); } + thd->where= "on clause"; if (derived->on_expr && derived->on_expr->fix_fields_if_needed_for_bool(thd, &derived->on_expr)) { diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index c840ae6990c..5937c43c95d 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5047,6 +5047,27 @@ bool st_select_lex::save_prep_leaf_tables(THD *thd) } +/** + Set exclude_from_table_unique_test for selects of this select and all selects + belonging to the underlying units of derived tables or views +*/ + +void st_select_lex::set_unique_exclude() +{ + exclude_from_table_unique_test= TRUE; + for (SELECT_LEX_UNIT *unit= first_inner_unit(); + unit; + unit= unit->next_unit()) + { + if (unit->derived && unit->derived->is_view_or_derived()) + { + for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select()) + sl->set_unique_exclude(); + } + } +} + + /* Return true if this select_lex has been converted into a semi-join nest within 'ancestor'. diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 960e36f63b4..466b23b3f94 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2019, Oracle and/or its affiliates. - Copyright (c) 2010, 2019, MariaDB Corporation. + Copyright (c) 2010, 2021, MariaDB Corporation 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 @@ -938,6 +938,10 @@ public: void init_query(); st_select_lex* outer_select(); + const st_select_lex* first_select() const + { + return reinterpret_cast<const st_select_lex*>(slave); + } st_select_lex* first_select() { return reinterpret_cast<st_select_lex*>(slave); @@ -1473,6 +1477,8 @@ public: bool save_leaf_tables(THD *thd); bool save_prep_leaf_tables(THD *thd); + void set_unique_exclude(); + bool is_merged_child_of(st_select_lex *ancestor); /* @@ -3081,7 +3087,8 @@ public: struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ - inline SELECT_LEX *first_select_lex() {return unit.first_select();} + SELECT_LEX *first_select_lex() { return unit.first_select(); } + const SELECT_LEX *first_select_lex() const { return unit.first_select(); } private: SELECT_LEX builtin_select; @@ -4345,6 +4352,25 @@ public: return false; } + bool create_like() const + { + DBUG_ASSERT(!create_info.like() || + !first_select_lex()->item_list.elements); + return create_info.like(); + } + + bool create_select() const + { + DBUG_ASSERT(!create_info.like() || + !first_select_lex()->item_list.elements); + return first_select_lex()->item_list.elements; + } + + bool create_simple() const + { + return !create_like() && !create_select(); + } + SELECT_LEX *exclude_last_select(); SELECT_LEX *exclude_not_first_select(SELECT_LEX *exclude); void check_automatic_up(enum sub_select_type type); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f66963d7b4f..0249ae68cc3 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -74,7 +74,9 @@ static int copy_data_between_tables(THD *, TABLE *,TABLE *, Alter_info::enum_enable_or_disable, Alter_table_ctx *); static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *, - uint *, handler *, KEY **, uint *, int); + uint *, handler *, KEY **, uint *, int, + const LEX_CSTRING db, + const LEX_CSTRING table_name); static uint blob_length_by_type(enum_field_types type); static bool fix_constraints_names(THD *, List<Virtual_column_info> *, const HA_CREATE_INFO *); @@ -1824,7 +1826,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info, &lpt->db_options, lpt->table->file, &lpt->key_info_buffer, &lpt->key_count, - C_ALTER_TABLE)) + C_ALTER_TABLE, lpt->db, lpt->table_name)) { DBUG_RETURN(TRUE); } @@ -3392,7 +3394,8 @@ static int mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Alter_info *alter_info, uint *db_options, handler *file, KEY **key_info_buffer, - uint *key_count, int create_table_mode) + uint *key_count, int create_table_mode, + const LEX_CSTRING db, const LEX_CSTRING table_name) { const char *key_name; Create_field *sql_field,*dup_field; @@ -3407,6 +3410,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, uint total_uneven_bit_length= 0; int select_field_count= C_CREATE_SELECT(create_table_mode); bool tmp_table= create_table_mode == C_ALTER_TABLE; + const bool create_simple= thd->lex->create_simple(); bool is_hash_field_needed= false; const Column_derived_attributes dattr(create_info->default_table_charset); const Column_bulk_alter_attributes @@ -4256,6 +4260,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, create_info->null_bits= null_fields; /* Check fields. */ + Item::Check_table_name_prm walk_prm(db, table_name); it.rewind(); while ((sql_field=it++)) { @@ -4310,6 +4315,37 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, sql_field->field_name.str); DBUG_RETURN(TRUE); } + + if (create_simple) + { + /* + NOTE: we cannot do this in check_vcol_func_processor() as there is already + no table name qualifier in expression. + */ + if (sql_field->vcol_info && sql_field->vcol_info->expr && + sql_field->vcol_info->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "GENERATED ALWAYS"); + DBUG_RETURN(TRUE); + } + + if (sql_field->default_value && + sql_field->default_value->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "DEFAULT"); + DBUG_RETURN(TRUE); + } + + if (sql_field->check_constraint && + sql_field->check_constraint->expr->walk(&Item::check_table_name_processor, + false, (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); + DBUG_RETURN(TRUE); + } + } } /* Check table level constraints */ @@ -4319,6 +4355,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, Virtual_column_info *check; while ((check= c_it++)) { + if (create_simple && check->expr->walk(&Item::check_table_name_processor, false, + (void *) &walk_prm)) + { + my_error(ER_BAD_FIELD_ERROR, MYF(0), walk_prm.field.c_ptr(), "CHECK"); + DBUG_RETURN(TRUE); + } if (!check->name.length || check->automatic_name) continue; @@ -4844,7 +4886,8 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db, } if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, - file, key_info, key_count, create_table_mode)) + file, key_info, key_count, + create_table_mode, db, table_name)) goto err; create_info->table_options=db_options; @@ -7320,13 +7363,15 @@ bool mysql_compare_tables(TABLE *table, Alter_info tmp_alter_info(*alter_info, thd->mem_root); uint db_options= 0; /* not used */ KEY *key_info_buffer= NULL; + LEX_CSTRING db= { table->s->db.str, table->s->db.length }; + LEX_CSTRING table_name= { table->s->db.str, table->s->table_name.length }; /* Create the prepared information. */ int create_table_mode= table->s->tmp_table == NO_TMP_TABLE ? C_ORDINARY_CREATE : C_ALTER_TABLE; if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info, &db_options, table->file, &key_info_buffer, - &key_count, create_table_mode)) + &key_count, create_table_mode, db, table_name)) DBUG_RETURN(1); /* Some very basic checks. */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 19a9a15921b..41ea52ef3c3 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1710,15 +1710,8 @@ bool Multiupdate_prelocking_strategy::handle_end(THD *thd) call in setup_tables()). */ - if (setup_tables_and_check_access(thd, &select_lex->context, - &select_lex->top_join_list, table_list, select_lex->leaf_tables, - FALSE, UPDATE_ACL, SELECT_ACL, FALSE)) - DBUG_RETURN(1); - - if (select_lex->handle_derived(thd->lex, DT_MERGE)) - DBUG_RETURN(1); - - if (thd->lex->save_prep_leaf_tables()) + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, FALSE, TRUE)) DBUG_RETURN(1); List<Item> *fields= &lex->first_select_lex()->item_list; @@ -1944,9 +1937,16 @@ bool mysql_multi_update(THD *thd, TABLE_LIST *table_list, List<Item> *fields, DBUG_RETURN(TRUE); } + if ((*result)->init(thd)) + DBUG_RETURN(1); + thd->abort_on_warning= !ignore && thd->is_strict_mode(); List<Item> total_list; + if (setup_tables(thd, &select_lex->context, &select_lex->top_join_list, + table_list, select_lex->leaf_tables, FALSE, FALSE)) + DBUG_RETURN(1); + if (select_lex->vers_setup_conds(thd, table_list)) DBUG_RETURN(1); @@ -1988,6 +1988,24 @@ multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list, } +bool multi_update::init(THD *thd) +{ + table_map tables_to_update= get_table_map(fields); + List_iterator_fast<TABLE_LIST> li(*leaves); + TABLE_LIST *tbl; + while ((tbl =li++)) + { + if (tbl->is_jtbm()) + continue; + if (!(tbl->table->map & tables_to_update)) + continue; + if (updated_leaves.push_back(tbl, thd->mem_root)) + return true; + } + return false; +} + + /* Connect fields with tables and create list of tables that are updated */ @@ -2004,7 +2022,7 @@ int multi_update::prepare(List<Item> ¬_used_values, List_iterator_fast<Item> value_it(*values); uint i, max_fields; uint leaf_table_count= 0; - List_iterator<TABLE_LIST> ti(*leaves); + List_iterator<TABLE_LIST> ti(updated_leaves); DBUG_ENTER("multi_update::prepare"); if (prepared) diff --git a/sql/win_tzname_data.h b/sql/win_tzname_data.h index 03197227f8e..792cdbc7a13 100644 --- a/sql/win_tzname_data.h +++ b/sql/win_tzname_data.h @@ -12,6 +12,7 @@ {L"US Mountain Standard Time","America/Phoenix"}, {L"Mountain Standard Time (Mexico)","America/Chihuahua"}, {L"Mountain Standard Time","America/Denver"}, +{L"Yukon Standard Time","America/Whitehorse"}, {L"Central America Standard Time","America/Guatemala"}, {L"Central Standard Time","America/Chicago"}, {L"Easter Island Standard Time","Pacific/Easter"}, diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 71dc310501d..68b7a018821 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -6195,16 +6195,6 @@ ha_innobase::open(const char* name, int, uint) innobase_copy_frm_flags_from_table_share(ib_table, table->s); - const bool bk_thread = THDVAR(thd, background_thread); - /* No point to init any statistics if tablespace is still encrypted - or if table is being opened by background thread */ - if (bk_thread) { - } else if (ib_table->is_readable()) { - dict_stats_init(ib_table); - } else { - ib_table->stat_initialized = 1; - } - MONITOR_INC(MONITOR_TABLE_OPEN); if ((ib_table->flags2 & DICT_TF2_DISCARDED)) { @@ -6400,7 +6390,7 @@ ha_innobase::open(const char* name, int, uint) ut_ad(!m_prebuilt->table || table->versioned() == m_prebuilt->table->versioned()); - if (!bk_thread) { + if (!THDVAR(thd, background_thread)) { info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST | HA_STATUS_OPEN); } @@ -14251,6 +14241,10 @@ ha_innobase::info_low( ib_table = m_prebuilt->table; DBUG_ASSERT(ib_table->get_ref_count() > 0); + if (!ib_table->is_readable()) { + ib_table->stat_initialized = true; + } + if (flag & HA_STATUS_TIME) { if (is_analyze || innobase_stats_on_metadata) { @@ -14303,6 +14297,8 @@ ha_innobase::info_low( DBUG_EXECUTE_IF("dict_sys_mutex_avoid", goto func_exit;); + dict_stats_init(ib_table); + if (flag & HA_STATUS_VARIABLE) { ulint stat_clustered_index_size; @@ -21747,11 +21743,12 @@ ib_push_warning( va_start(args, format); buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME)); - vsprintf(buf,format, args); - - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - uint(convert_error_code_to_mysql(error, 0, thd)), buf); + buf[MAX_BUF_SIZE - 1] = 0; + vsnprintf(buf, MAX_BUF_SIZE - 1, format, args); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + uint(convert_error_code_to_mysql(error, 0, + thd)), + buf); my_free(buf); va_end(args); } @@ -21779,7 +21776,8 @@ ib_push_warning( if (thd) { va_start(args, format); buf = (char *)my_malloc(MAX_BUF_SIZE, MYF(MY_WME)); - vsprintf(buf,format, args); + buf[MAX_BUF_SIZE - 1] = 0; + vsnprintf(buf, MAX_BUF_SIZE - 1, format, args); push_warning_printf( thd, Sql_condition::WARN_LEVEL_WARN, diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index e9d9c349241..4359fb6b308 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -972,7 +972,8 @@ fail: DBUG_EXECUTE_IF("log_checksum_mismatch", { cksum = crc + 1; }); if (crc != cksum) { - ib::error() << "Invalid log block checksum." + ib::error_or_warn(srv_operation != SRV_OPERATION_BACKUP) + << "Invalid log block checksum." << " block: " << block_number << " checkpoint no: " << log_block_get_checkpoint_no(buf) diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index f3445a340d6..74947b78774 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -81,9 +81,9 @@ is alphabetically the same as the corresponding BLOB column in the clustered index record. NOTE: the comparison is NOT done as a binary comparison, but character fields are compared with collation! -@return TRUE if the columns are equal */ +@return whether the columns are equal */ static -ibool +bool row_sel_sec_rec_is_for_blob( /*========================*/ ulint mtype, /*!< in: main type */ @@ -102,19 +102,18 @@ row_sel_sec_rec_is_for_blob( const byte* sec_field, /*!< in: column in secondary index */ ulint sec_len, /*!< in: length of sec_field */ ulint prefix_len, /*!< in: index column prefix length - in bytes */ + in bytes, or 0 for full column */ dict_table_t* table) /*!< in: table */ { ulint len; - byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN]; + byte buf[REC_VERSION_56_MAX_INDEX_COL_LEN + 1]; /* This function should never be invoked on tables in ROW_FORMAT=REDUNDANT or ROW_FORMAT=COMPACT, because they should always contain enough prefix in the clustered index record. */ ut_ad(dict_table_has_atomic_blobs(table)); ut_a(clust_len >= BTR_EXTERN_FIELD_REF_SIZE); - ut_ad(prefix_len >= sec_len); - ut_ad(prefix_len > 0); + ut_ad(!prefix_len || prefix_len >= sec_len); ut_a(prefix_len <= sizeof buf); if (!memcmp(clust_field + clust_len - BTR_EXTERN_FIELD_REF_SIZE, @@ -123,11 +122,12 @@ row_sel_sec_rec_is_for_blob( This record should only be seen by recv_recovery_rollback_active() or any TRX_ISO_READ_UNCOMMITTED transactions. */ - return(FALSE); + return false; } len = btr_copy_externally_stored_field_prefix( - buf, prefix_len, table->space->zip_size(), + buf, prefix_len ? prefix_len : sizeof buf, + table->space->zip_size(), clust_field, clust_len); if (len == 0) { @@ -136,11 +136,18 @@ row_sel_sec_rec_is_for_blob( referring to this clustered index record, because btr_free_externally_stored_field() is called after all secondary index entries of the row have been purged. */ - return(FALSE); + return false; } - len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, - prefix_len, len, (const char*) buf); + if (prefix_len) { + len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, + prefix_len, len, + reinterpret_cast<const char*> + (buf)); + } else if (len >= sizeof buf) { + ut_ad("too long column" == 0); + return false; + } return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); } @@ -217,12 +224,13 @@ row_sel_sec_rec_is_for_clust_rec( ulint clust_pos = 0; ulint clust_len = 0; ulint len; - bool is_virtual; ifield = dict_index_get_nth_field(sec_index, i); col = dict_field_get_col(ifield); - is_virtual = col->is_virtual(); + sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len); + + const bool is_virtual = col->is_virtual(); /* For virtual column, its value will need to be reconstructed from base column in cluster index */ @@ -254,43 +262,55 @@ row_sel_sec_rec_is_for_clust_rec( innobase_report_computed_value_failed(row); return DB_COMPUTE_VALUE_FAILED; } - clust_len = vfield->len; + len = clust_len = vfield->len; clust_field = static_cast<byte*>(vfield->data); } else { clust_pos = dict_col_get_clust_pos(col, clust_index); + clust_field = rec_get_nth_cfield( clust_rec, clust_index, clust_offs, clust_pos, &clust_len); - } - - sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len); - - len = clust_len; - - if (ifield->prefix_len > 0 && len != UNIV_SQL_NULL - && sec_len != UNIV_SQL_NULL && !is_virtual) { + if (clust_len == UNIV_SQL_NULL) { + if (sec_len == UNIV_SQL_NULL) { + continue; + } + return DB_SUCCESS; + } + if (sec_len == UNIV_SQL_NULL) { + return DB_SUCCESS; + } + len = clust_len; if (rec_offs_nth_extern(clust_offs, clust_pos)) { len -= BTR_EXTERN_FIELD_REF_SIZE; } - len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminlen, col->mbmaxlen, - ifield->prefix_len, len, (char*) clust_field); - - if (rec_offs_nth_extern(clust_offs, clust_pos) - && len < sec_len) { - if (!row_sel_sec_rec_is_for_blob( - col->mtype, col->prtype, - col->mbminlen, col->mbmaxlen, - clust_field, clust_len, - sec_field, sec_len, - ifield->prefix_len, - clust_index->table)) { - return DB_SUCCESS; + if (ulint prefix_len = ifield->prefix_len) { + len = dtype_get_at_most_n_mbchars( + col->prtype, col->mbminlen, + col->mbmaxlen, prefix_len, len, + reinterpret_cast<const char*>( + clust_field)); + if (len < sec_len) { + goto check_for_blob; } + } else { +check_for_blob: + if (rec_offs_nth_extern(clust_offs, + clust_pos)) { + if (!row_sel_sec_rec_is_for_blob( + col->mtype, col->prtype, + col->mbminlen, + col->mbmaxlen, + clust_field, clust_len, + sec_field, sec_len, + prefix_len, + clust_index->table)) { + return DB_SUCCESS; + } - continue; + continue; + } } } |