Fixed lp:879939 "assertion in ha_maria::enable_indexes with derived_with_keys=on"
Honor unique/not unique when creating keys for internal tempory tables. Added new variables to be used to limit how keys are created for internal temporary tables. include/maria.h: Added maria_max_key_length() and maria_max_key_segments() include/myisam.h: Added myisam_max_key_length() and myisam_max_key_segments() mysql-test/r/mysql.result: Drop all used tables mysql-test/r/subselect4.result: Added test case for lp:879939 mysql-test/t/mysql.test: Drop all used tables mysql-test/t/subselect4.test: Added test case for lp:879939 sql/mysql_priv.h: Added internal_tmp_table_max_key_length and internal_tmp_table_max_key_segments to be used to limit how keys for derived tables are created. sql/mysqld.cc: Added internal_tmp_table_max_key_length and internal_tmp_table_max_key_segments to be used to limit how keys for derived tables are created. sql/share/errmsg.txt: Added new error message for internal errors sql/sql_select.cc: Give error if we try to create a wrong key (this error should never happen) Honor unique/not unique when creating keys for internal tempory tables. storage/maria/ha_maria.cc: Added change_table_ptr() to ensure that external_ref points always to the correct table. (Not having this caused an assert in the included test) storage/maria/ha_maria.h: Added change_table_ptr() to ensure that external_ref points always to the correct table. storage/maria/ma_check.c: Fixed bug in Duplicate key error printing (now row position is printed correctly) storage/maria/ma_create.c: maria_max_key_length() -> _ma_max_key_length() storage/maria/ma_info.c: Added extern function maria_max_key_length() to calculate the max key length based on current block size. storage/maria/ma_open.c: maria_max_key_length() -> _ma_max_key_length() storage/maria/maria_def.h: maria_max_key_length() -> _ma_max_key_length() storage/myisam/ha_myisam.cc: Added change_table_ptr() to ensure that external_ref points always to the correct table. (Not having this caused an assert in the included test) storage/myisam/ha_myisam.h: Added change_table_ptr() to ensure that external_ref points always to the correct table.
This commit is contained in:
parent
16942bc5ca
commit
fa36a7426b
@ -466,6 +466,8 @@ void maria_change_pagecache(PAGECACHE *old_key_cache,
|
||||
int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves);
|
||||
void maria_versioning(MARIA_HA *info, my_bool versioning);
|
||||
void maria_ignore_trids(MARIA_HA *info);
|
||||
uint maria_max_key_length(void);
|
||||
#define maria_max_key_segments() HA_MAX_KEY_SEG
|
||||
|
||||
/* fulltext functions */
|
||||
FT_INFO *maria_ft_init_search(uint,void *, uint, uchar *, size_t,
|
||||
|
@ -298,6 +298,8 @@ extern ulong _mi_calc_blob_length(uint length , const uchar *pos);
|
||||
extern uint mi_get_pointer_length(ulonglong file_length, uint def);
|
||||
extern int mi_make_backup_of_index(struct st_myisam_info *info,
|
||||
time_t backup_time, myf flags);
|
||||
#define myisam_max_key_length() HA_MAX_KEY_LENGTH
|
||||
#define myisam_max_key_segments() HA_MAX_KEY_SEG
|
||||
|
||||
#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for mmap file */
|
||||
/* this is used to pass to mysql_myisamchk_table */
|
||||
|
@ -1,4 +1,4 @@
|
||||
drop table if exists t1;
|
||||
drop table if exists t1,t2,t3;
|
||||
create table t1(a int);
|
||||
insert into t1 values(1);
|
||||
ERROR at line 9: DELIMITER must be followed by a 'delimiter' character or string
|
||||
|
@ -2104,3 +2104,38 @@ NULL
|
||||
deallocate prepare st1;
|
||||
drop table t1, t2, t3;
|
||||
set optimizer_switch=@subselect4_tmp;
|
||||
#
|
||||
# LP bug #879939: assertion in ha_maria::enable_indexes with derived_with_keys=on
|
||||
#
|
||||
CREATE TABLE t2 ( a varchar(3)) ;
|
||||
INSERT INTO t2 VALUES ('USA'),('USA'),('USA'),('USA'),('USA');
|
||||
CREATE TABLE t1 ( a varchar(3), b varchar(35)) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES ('USA','Lansing'),('USA','Laredo'),('USA','Las Vegas'),('USA','Lexington-Fayett'),('USA','Lincoln'),('USA','Little Rock'),('USA','Livonia'),('USA','Long Beach'),('USA','Los Angeles'),('USA','Louisville'),('USA','Lowell'),('USA','Lubbock'),('USA','Macon'),('USA','Madison'),('USA','Manchester'),('USA','McAllen'),('USA','Memphis'),('USA','Mesa'),('USA','Mesquite'),('USA','Metairie'),('USA','Miami');
|
||||
CREATE TABLE t3 ( a varchar(35)) ENGINE=MyISAM;
|
||||
INSERT INTO t3 VALUES ('Miami');
|
||||
SET optimizer_switch = 'derived_with_keys=on';
|
||||
SET @@tmp_table_size=1024*4;
|
||||
explain SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY t3 system NULL NULL NULL NULL 1
|
||||
1 PRIMARY <derived2> ref key0 key0 39 const 10
|
||||
2 DERIVED t2 ALL NULL NULL NULL NULL 5
|
||||
2 DERIVED t1 ALL NULL NULL NULL NULL 21 Using join buffer (flat, BNL join)
|
||||
SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
a b a
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
SET @@tmp_table_size=1024*1024*16;
|
||||
SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
a b a
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
USA Miami Miami
|
||||
drop table t1,t2,t3;
|
||||
SET optimizer_switch= @@global.optimizer_switch;
|
||||
set @@tmp_table_size= @@global.tmp_table_size;
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
drop table if exists t1,t2,t3;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
|
@ -1735,3 +1735,27 @@ deallocate prepare st1;
|
||||
drop table t1, t2, t3;
|
||||
|
||||
set optimizer_switch=@subselect4_tmp;
|
||||
|
||||
--echo #
|
||||
--echo # LP bug #879939: assertion in ha_maria::enable_indexes with derived_with_keys=on
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t2 ( a varchar(3)) ;
|
||||
INSERT INTO t2 VALUES ('USA'),('USA'),('USA'),('USA'),('USA');
|
||||
CREATE TABLE t1 ( a varchar(3), b varchar(35)) ENGINE=MyISAM;
|
||||
INSERT INTO t1 VALUES ('USA','Lansing'),('USA','Laredo'),('USA','Las Vegas'),('USA','Lexington-Fayett'),('USA','Lincoln'),('USA','Little Rock'),('USA','Livonia'),('USA','Long Beach'),('USA','Los Angeles'),('USA','Louisville'),('USA','Lowell'),('USA','Lubbock'),('USA','Macon'),('USA','Madison'),('USA','Manchester'),('USA','McAllen'),('USA','Memphis'),('USA','Mesa'),('USA','Mesquite'),('USA','Metairie'),('USA','Miami');
|
||||
|
||||
CREATE TABLE t3 ( a varchar(35)) ENGINE=MyISAM;
|
||||
INSERT INTO t3 VALUES ('Miami');
|
||||
|
||||
SET optimizer_switch = 'derived_with_keys=on';
|
||||
SET @@tmp_table_size=1024*4;
|
||||
|
||||
explain SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
SET @@tmp_table_size=1024*1024*16;
|
||||
SELECT * FROM (SELECT t1.* FROM t1, t2 ) AS alias1 JOIN t3 ON ( t3.a = alias1.b );
|
||||
|
||||
drop table t1,t2,t3;
|
||||
SET optimizer_switch= @@global.optimizer_switch;
|
||||
set @@tmp_table_size= @@global.tmp_table_size;
|
||||
|
@ -2181,6 +2181,9 @@ extern uint test_flags,select_errors,ha_open_options;
|
||||
extern uint protocol_version, mysqld_port, mysqld_extra_port, dropping_tables;
|
||||
extern uint delay_key_write_options;
|
||||
extern ulong max_long_data_size;
|
||||
extern uint internal_tmp_table_max_key_length;
|
||||
extern uint internal_tmp_table_max_key_segments;
|
||||
|
||||
#endif /* MYSQL_SERVER */
|
||||
#if defined MYSQL_SERVER || defined INNODB_COMPATIBILITY_HOOKS
|
||||
extern MYSQL_PLUGIN_IMPORT uint lower_case_table_names;
|
||||
|
@ -669,6 +669,10 @@ ulong extra_max_connections;
|
||||
*/
|
||||
ulong max_long_data_size;
|
||||
|
||||
/* Limits for internal temporary tables (MyISAM or Aria) */
|
||||
uint internal_tmp_table_max_key_length;
|
||||
uint internal_tmp_table_max_key_segments;
|
||||
|
||||
int max_user_connections= 0;
|
||||
bool max_user_connections_checking=0;
|
||||
ulonglong denied_connections;
|
||||
@ -4464,6 +4468,11 @@ a file name for --log-bin-index option", opt_binlog_index_name);
|
||||
sql_print_error("Aria engine is not enabled or did not start. The Aria engine must be enabled to continue as mysqld was configured with --with-aria-tmp-tables");
|
||||
unireg_abort(1);
|
||||
}
|
||||
internal_tmp_table_max_key_length= maria_max_key_length();
|
||||
internal_tmp_table_max_key_segments= maria_max_key_segments();
|
||||
#else
|
||||
internal_tmp_table_max_key_length= myisam_max_key_length();
|
||||
internal_tmp_table_max_key_segments= myisam_max_key_segments();
|
||||
#endif
|
||||
|
||||
tc_log= (total_ha_2pc > 1 ? (opt_bin_log ?
|
||||
|
@ -6292,3 +6292,7 @@ ER_VIEW_ORDERBY_IGNORED
|
||||
eng "View '%-.192s'.'%-.192s' ORDER BY clause ignored because there is other ORDER BY clause already."
|
||||
ER_CONNECTION_KILLED 70100
|
||||
eng "Connection was killed"
|
||||
ER_INTERNAL_ERROR
|
||||
eng "Internal error: '%-.192s'"
|
||||
|
||||
|
||||
|
@ -14172,6 +14172,13 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
|
||||
keyinfo->key_parts > table->file->max_key_parts() ||
|
||||
share->uniques)
|
||||
{
|
||||
if (!share->uniques && !(keyinfo->flags & HA_NOSAME))
|
||||
{
|
||||
my_error(ER_INTERNAL_ERROR, MYF(0),
|
||||
"Using too big key for internal temp tables");
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* Can't create a key; Make a unique constraint instead of a key */
|
||||
share->keys= 0;
|
||||
share->uniques= 1;
|
||||
@ -14190,9 +14197,9 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Create an unique key */
|
||||
/* Create a key */
|
||||
bzero((char*) &keydef,sizeof(keydef));
|
||||
keydef.flag=HA_NOSAME;
|
||||
keydef.flag= keyinfo->flags & HA_NOSAME;
|
||||
keydef.keysegs= keyinfo->key_parts;
|
||||
keydef.seg= seg;
|
||||
}
|
||||
@ -14368,7 +14375,8 @@ bool create_internal_tmp_table(TABLE *table, KEY *keyinfo,
|
||||
{
|
||||
/* Create an unique key */
|
||||
bzero((char*) &keydef,sizeof(keydef));
|
||||
keydef.flag=HA_NOSAME | HA_BINARY_PACK_KEY | HA_PACK_KEY;
|
||||
keydef.flag= ((keyinfo->flags & HA_NOSAME) | HA_BINARY_PACK_KEY |
|
||||
HA_PACK_KEY);
|
||||
keydef.keysegs= keyinfo->key_parts;
|
||||
keydef.seg= seg;
|
||||
}
|
||||
|
@ -935,8 +935,7 @@ double ha_maria::scan_time()
|
||||
|
||||
uint ha_maria::max_supported_key_length() const
|
||||
{
|
||||
uint tmp= (maria_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
|
||||
return min(HA_MAX_KEY_BUFF, tmp);
|
||||
return maria_max_key_length();
|
||||
}
|
||||
|
||||
|
||||
@ -2601,6 +2600,14 @@ void ha_maria::drop_table(const char *name)
|
||||
}
|
||||
|
||||
|
||||
void ha_maria::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
|
||||
{
|
||||
handler::change_table_ptr(table_arg, share);
|
||||
if (file)
|
||||
file->external_ref= table_arg;
|
||||
}
|
||||
|
||||
|
||||
int ha_maria::external_lock(THD *thd, int lock_type)
|
||||
{
|
||||
DBUG_ENTER("ha_maria::external_lock");
|
||||
|
@ -77,6 +77,7 @@ public:
|
||||
{ return max_supported_key_length(); }
|
||||
enum row_type get_row_type() const;
|
||||
uint checksum() const;
|
||||
void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
|
||||
virtual double scan_time();
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
|
@ -5671,7 +5671,8 @@ static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo,
|
||||
MARIA_KEY key;
|
||||
key.keyinfo= keyinfo;
|
||||
key.data= (uchar*) key_data;
|
||||
key.data_length= _ma_keylength(keyinfo, key_data);
|
||||
key.data_length= (_ma_keylength(keyinfo, key_data) -
|
||||
keyinfo->share->rec_reflength);
|
||||
return _ma_row_pos_from_key(&key);
|
||||
} /* get_record_for_key */
|
||||
|
||||
|
@ -623,7 +623,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
|
||||
to be able to put at least 2 keys on an index block for the key
|
||||
algorithms to work).
|
||||
*/
|
||||
if (length > maria_max_key_length())
|
||||
if (length > _ma_max_key_length())
|
||||
{
|
||||
my_errno=HA_WRONG_CREATE_OPTION;
|
||||
goto err_no_lock;
|
||||
|
@ -28,6 +28,12 @@ MARIA_RECORD_POS maria_position(MARIA_HA *info)
|
||||
}
|
||||
|
||||
|
||||
uint maria_max_key_length()
|
||||
{
|
||||
uint tmp= (_ma_max_key_length() - 8 - HA_MAX_KEY_SEG*3);
|
||||
return min(HA_MAX_KEY_BUFF, tmp);
|
||||
}
|
||||
|
||||
/* Get information about the table */
|
||||
/* if flag == 2 one get current info (no sync from database */
|
||||
|
||||
|
@ -468,7 +468,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
||||
}
|
||||
|
||||
key_parts+=fulltext_keys*FT_SEGS;
|
||||
if (share->base.max_key_length > maria_max_key_length() ||
|
||||
if (share->base.max_key_length > _ma_max_key_length() ||
|
||||
keys > MARIA_MAX_KEY || key_parts > MARIA_MAX_KEY * HA_MAX_KEY_SEG)
|
||||
{
|
||||
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
|
||||
|
@ -747,7 +747,7 @@ struct st_maria_handler
|
||||
{ length=mi_uint2korr((key)+1)+3; } \
|
||||
}
|
||||
|
||||
#define maria_max_key_length() ((maria_block_size - MAX_KEYPAGE_HEADER_SIZE)/3 - MARIA_INDEX_OVERHEAD_SIZE)
|
||||
#define _ma_max_key_length() ((maria_block_size - MAX_KEYPAGE_HEADER_SIZE)/3 - MARIA_INDEX_OVERHEAD_SIZE)
|
||||
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
|
||||
#define _ma_have_versioning(info) ((info)->row_flag & ROW_FLAG_TRANSID)
|
||||
|
||||
|
@ -551,7 +551,6 @@ my_bool mi_killed_in_mariadb(MI_INFO *info)
|
||||
|
||||
}
|
||||
|
||||
|
||||
ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg)
|
||||
:handler(hton, table_arg), file(0),
|
||||
int_table_flags(HA_NULL_IN_KEY | HA_CAN_FULLTEXT | HA_CAN_SQL_HANDLER |
|
||||
@ -2005,6 +2004,13 @@ int ha_myisam::delete_table(const char *name)
|
||||
return mi_delete_table(name);
|
||||
}
|
||||
|
||||
void ha_myisam::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share)
|
||||
{
|
||||
handler::change_table_ptr(table_arg, share);
|
||||
if (file)
|
||||
file->external_ref= table_arg;
|
||||
}
|
||||
|
||||
|
||||
int ha_myisam::external_lock(THD *thd, int lock_type)
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ class ha_myisam: public handler
|
||||
uint max_supported_key_length() const { return HA_MAX_KEY_LENGTH; }
|
||||
uint max_supported_key_part_length() const { return HA_MAX_KEY_LENGTH; }
|
||||
uint checksum() const;
|
||||
|
||||
void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
int close(void);
|
||||
int write_row(uchar * buf);
|
||||
|
Loading…
x
Reference in New Issue
Block a user