Commit 1118e979 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-29672 Add MTR tests covering key and key segment flags and types

parent e3fdabd5
This source diff could not be displayed because it is too large. You can view the blob instead.
--source include/have_debug.inc
--echo #
--echo # MDEV-29672 Add MTR tests covering key and key segment flags and types
--echo #
SET debug_dbug='+d,key';
CREATE TABLE types (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
type TEXT NOT NULL,
prefix_length INT NOT NULL
);
INSERT INTO types (type, prefix_length) VALUES
('INT', 0),
('BIGINT', 0),
('DOUBLE', 0),
('DECIMAL(20,10)', 0),
('CHAR(4)', 0),
('CHAR(10)', 0),
('VARCHAR(4)', 0),
('VARCHAR(6)', 0),
('VARCHAR(8)', 0),
('VARCHAR(12)', 0),
('VARCHAR(16)', 0),
('VARCHAR(100)', 0),
('TEXT', 4),
('TEXT', 6),
('TEXT', 8),
('TEXT', 12),
('TEXT', 16),
('TEXT', 100);
DELIMITER $$;
BEGIN NOT ATOMIC
DECLARE create2_template TEXT
DEFAULT 'CREATE TABLE t1 (a TYPE1 NOT NULL, b TYPE2 NOT NULL, KEY(SEG1,SEG2))';
DECLARE cur2 CURSOR FOR
SELECT t1.type AS type1,
t2.type AS type2,
t1.prefix_length AS prefix_length1,
t2.prefix_length AS prefix_length2
FROM types AS t1, types AS t2
ORDER BY t1.id, t2.id;
FOR rec IN cur2 DO
BEGIN
DECLARE tabledef TEXT DEFAULT REPLACE(create2_template,'TYPE1', rec.type1);
SET tabledef=REPLACE(tabledef, 'TYPE2', rec.type2);
SET tabledef=REPLACE(tabledef, 'SEG1',
IF(rec.prefix_length1,
CONCAT('a(',rec.prefix_length1,')'), 'a'));
SET tabledef=REPLACE(tabledef, 'SEG2',
IF(rec.prefix_length2,
CONCAT('b(',rec.prefix_length2,')'), 'b'));
SELECT tabledef AS ``;
EXECUTE IMMEDIATE tabledef;
SHOW WARNINGS;
SHOW CREATE TABLE t1;
DROP TABLE t1;
END;
END FOR;
END;
$$
DELIMITER ;$$
DROP TABLE types;
SET debug_dbug='';
#ifndef SQL_DEBUG_INCLUDED
#define SQL_DEBUG_INCLUDED
/*
Copyright (c) 2022, 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 the Free Software Foundation; version 2 of
the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
*/
class Debug_key: public String
{
public:
Debug_key() { };
void print(THD *thd) const
{
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "DBUG: %.*s", length(), ptr());
}
bool append_key_type(ha_base_keytype type)
{
static const char *names[20]=
{
"END",
"TEXT",
"BINARY",
"SHORT_INT",
"LONG_INT",
"FLOAT",
"DOUBLE",
"NUM",
"USHORT_INT",
"ULONG_INT",
"LONGLONG",
"ULONGLONG",
"INT24",
"UINT24",
"INT8",
"VARTEXT1",
"VARBINARY1",
"VARTEXT2",
"VARBINARY2",
"BIT"
};
if ((uint) type >= array_elements(names))
return append("???");
return append(names[(uint) type]);
}
bool append_KEY_flag_names(ulong flags)
{
static const char *names[17]=
{
"HA_NOSAME",
"HA_PACK_KEY",
"HA_SPACE_PACK_USED",
"HA_VAR_LENGTH_KEY",
"HA_AUTO_KEY",
"HA_BINARY_PACK_KEY",
"HA_NULL_PART_KEY",
"HA_FULLTEXT",
"HA_UNIQUE_CHECK",
"HA_SORT_ALLOWS_SAME",
"HA_SPATIAL",
"HA_NULL_ARE_EQUAL",
"HA_GENERATED_KEY",
"HA_USES_COMMENT",
"HA_USES_PARSER",
"HA_USES_BLOCK_SIZE",
"HA_KEY_HAS_PART_KEY_SEG"
};
return append_flag32_names((uint) flags, names, array_elements(names));
}
bool append_HA_KEYSEG_flag_names(uint32 flags)
{
static const char *names[]=
{
"HA_SPACE_PACK", // 1
"??? 2 ???", // 2
"HA_PART_KEY_SEG", // 4
"HA_VAR_LENGTH_PART", // 8
"HA_NULL_PART", // 16
"HA_BLOB_PART", // 32
"HA_SWAP_KEY", // 64
"HA_REVERSE_SORT", // 128
"HA_NO_SORT", // 256
"??? 512 ???", // 512
"HA_BIT_PART", // 1024
"HA_CAN_MEMCMP" // 2048
};
return append_flag32_names(flags, names, array_elements(names));
}
bool append_HA_KEYSEG_type(ha_base_keytype type)
{
return append_ulonglong(type) ||
append(' ') ||
append_key_type(type);
}
bool append_HA_KEYSEG_flags(uint32 flags)
{
return append_hex_uint32(flags) ||
append(' ') ||
append_HA_KEYSEG_flag_names(flags);
}
bool append_key(const LEX_CSTRING &name, uint32 flags)
{
return
append_name_value(Lex_cstring(STRING_WITH_LEN("name")), name, '`') ||
append(Lex_cstring(STRING_WITH_LEN(" flags="))) ||
append_hex_uint32(flags) ||
append(' ') ||
append_KEY_flag_names(flags);
}
bool append_KEY(const KEY &key)
{
return append_key(key.name, key.flags);
}
static void print_keysegs(THD *thd, const HA_KEYSEG *seg, uint count)
{
for (uint i= 0; i < count; i++)
{
Debug_key tmp;
if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) &&
!tmp.append_ulonglong(i) &&
!tmp.append(Lex_cstring(STRING_WITH_LEN("].type="))) &&
!tmp.append_HA_KEYSEG_type((ha_base_keytype) seg[i].type))
tmp.print(thd);
tmp.length(0);
if (!tmp.append(Lex_cstring(STRING_WITH_LEN(" seg["))) &&
!tmp.append_ulonglong(i) &&
!tmp.append(Lex_cstring(STRING_WITH_LEN("].flag="))) &&
!tmp.append_HA_KEYSEG_flags(seg[i].flag))
tmp.print(thd);
}
}
static void print_keys(THD *thd, const char *where,
const KEY *keys, uint key_count)
{
for (uint i= 0; i < key_count; i++)
{
Debug_key tmp;
if (!tmp.append(where) && !tmp.append_KEY(keys[i]))
tmp.print(thd);
}
}
};
#endif // SQL_DEBUG_INCLUDED
......@@ -164,6 +164,17 @@ void Static_binary_string::qs_append_hex(const char *str, uint32 len)
}
void Static_binary_string::qs_append_hex_uint32(uint32 num)
{
char *to= Ptr + str_length;
APPEND_HEX(to, (uchar) (num >> 24));
APPEND_HEX(to, (uchar) (num >> 16));
APPEND_HEX(to, (uchar) (num >> 8));
APPEND_HEX(to, (uchar) num);
str_length+= 8;
}
// Convert a string to its HEX representation
bool Binary_string::set_hex(const char *str, uint32 len)
{
......
......@@ -348,6 +348,7 @@ class Static_binary_string : public Sql_alloc
}
void qs_append(const char *str, size_t len);
void qs_append_hex(const char *str, uint32 len);
void qs_append_hex_uint32(uint32 num);
void qs_append(double d);
void qs_append(double *d);
inline void qs_append(const char c)
......@@ -571,7 +572,13 @@ class Binary_string: public Static_binary_string
}
return false;
}
bool append_hex_uint32(uint32 num)
{
if (reserve(8))
return true;
qs_append_hex_uint32(num);
return false;
}
bool append_with_step(const char *s, uint32 arg_length, uint32 step_alloc)
{
uint32 new_length= arg_length + str_length;
......@@ -916,6 +923,17 @@ class String: public Charset, public Binary_string
{
return append(&ls);
}
bool append_name_value(const LEX_CSTRING &name,
const LEX_CSTRING &value,
uchar quot= '\0')
{
return
append(name) ||
append('=') ||
(quot && append(quot)) ||
append(value) ||
(quot && append(quot));
}
bool append(const char *s, size_t size);
bool append_with_prefill(const char *s, uint32 arg_length,
uint32 full_length, char fill_char);
......@@ -928,6 +946,37 @@ class String: public Charset, public Binary_string
return append(s.str, s.length, cs);
}
/*
Append a bitmask in an uint32 with a translation into a
C-style human readable representation, e.g.:
0x05 -> "(flag04|flag01)"
@param flags - the flags to translate
@param names - an array of flag names
@param count - the number of available elements in "names"
*/
bool append_flag32_names(uint32 flags, const char *names[], size_t count)
{
bool added= false;
if (flags && append('('))
return true;
for (ulong i= 0; i <= 31; i++)
{
ulong bit= 31 - i;
if (flags & (1 << bit))
{
if (added && append('|'))
return true;
if (append(bit < count ? names[bit] : "?"))
return true;
added= true;
}
}
if (flags && append(')'))
return true;
return false;
}
void strip_sp();
friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
friend int stringcmp(const String *a,const String *b);
......
......@@ -58,6 +58,7 @@
#ifdef WITH_WSREP
#include "wsrep_mysqld.h"
#endif
#include "sql_debug.h"
#ifdef __WIN__
#include <io.h>
......@@ -4458,6 +4459,13 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
thd->mem_root))
DBUG_RETURN(TRUE);
#ifndef DBUG_OFF
DBUG_EXECUTE_IF("key",
Debug_key::print_keys(thd, "prep_create_table: ",
*key_info_buffer, *key_count);
);
#endif
DBUG_RETURN(FALSE);
}
......
......@@ -33,6 +33,7 @@
#include "sql_table.h" // tablename_to_filename
#include "sql_class.h" // THD
#include "debug_sync.h"
#include "sql_debug.h"
ulonglong myisam_recover_options;
static ulong opt_myisam_block_size;
......@@ -121,6 +122,28 @@ static void debug_wait_for_kill(const char *info)
thd_proc_info(thd, prev_info);
DBUG_VOID_RETURN;
}
class Debug_key_myisam: public Debug_key
{
public:
Debug_key_myisam() { }
static void print_keys_myisam(THD *thd, const char *where,
const TABLE *table,
const MI_KEYDEF *keydef, uint count)
{
for (uint i= 0; i < count; i++)
{
Debug_key_myisam tmp;
if (!tmp.append(where) &&
!tmp.append_key(table->s->key_info[i].name, keydef[i].flag))
tmp.print(thd);
print_keysegs(thd, keydef[i].seg, keydef[i].keysegs);
}
}
};
#endif
/*****************************************************************************
......@@ -2232,6 +2255,15 @@ int ha_myisam::create(const char *name, TABLE *table_arg,
if ((error= table2myisam(table_arg, &keydef, &recinfo, &record_count)))
DBUG_RETURN(error); /* purecov: inspected */
#ifndef DBUG_OFF
DBUG_EXECUTE_IF("key",
Debug_key_myisam::print_keys_myisam(table_arg->in_use,
"ha_myisam::create: ",
table_arg, keydef, share->keys);
);
#endif
bzero((char*) &create_info, sizeof(create_info));
create_info.max_rows= share->max_rows;
create_info.reloc_rows= share->min_rows;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment