MDEV-33658 1/2 Refactoring: extract Key length initialization
mysql_prepare_create_table: Extract a Key initialization part that relates to length calculation and long unique index designation. append_system_key_parts call also moves there. Move this initialization before the duplicate elimination. Extract WITHOUT OVERPLAPS check into a separate function. It had to be moved earlier in the code to preserve the order of the error checks, as in the tests.
This commit is contained in:
parent
e33064e0fc
commit
ecaedbe299
@ -38,7 +38,7 @@ CREATE TABLE t_stmt (a VARCHAR(100)) ENGINE = EXAMPLE;
|
|||||||
ALTER TABLE t_stmt ADD COLUMN b INT;
|
ALTER TABLE t_stmt ADD COLUMN b INT;
|
||||||
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||||
CREATE INDEX i ON t_stmt(a);
|
CREATE INDEX i ON t_stmt(a);
|
||||||
ERROR 42000: Too many key parts specified; max 0 parts allowed
|
ERROR 42000: Specified key was too long; max key length is 0 bytes
|
||||||
CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt;
|
CREATE TABLE t_stmt_new ENGINE = EXAMPLE SELECT * FROM t_stmt;
|
||||||
ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging
|
ERROR HY000: Cannot execute statement: impossible to write to binary log since BINLOG_FORMAT = ROW and at least one table uses a storage engine limited to statement-based logging
|
||||||
DROP TABLE t_stmt;
|
DROP TABLE t_stmt;
|
||||||
|
@ -75,7 +75,7 @@ ALTER TABLE t_stmt ADD COLUMN b INT;
|
|||||||
|
|
||||||
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
CREATE TRIGGER trig_stmt BEFORE INSERT ON t_stmt FOR EACH ROW INSERT INTO t_stmt VALUES (1);
|
||||||
|
|
||||||
--error ER_TOO_MANY_KEY_PARTS
|
--error ER_TOO_LONG_KEY
|
||||||
CREATE INDEX i ON t_stmt(a);
|
CREATE INDEX i ON t_stmt(a);
|
||||||
|
|
||||||
--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
|
--error ER_BINLOG_ROW_MODE_AND_STMT_ENGINE
|
||||||
|
@ -659,6 +659,8 @@ NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 15000
|
|||||||
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 16000
|
NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL 16000
|
||||||
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx1 (col_1);
|
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx1 (col_1);
|
||||||
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx6 (col_1(255));
|
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx6 (col_1(255));
|
||||||
|
Warnings:
|
||||||
|
Note 1831 Duplicate index `idx6`. This is deprecated and will be disallowed in a future release
|
||||||
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx10 (col_10(255));
|
ALTER TABLE testdb_wl5522.t1 ADD INDEX idx10 (col_10(255));
|
||||||
SELECT
|
SELECT
|
||||||
col_1 = REPEAT("col1_00001",10),
|
col_1 = REPEAT("col1_00001",10),
|
||||||
|
@ -1075,6 +1075,8 @@ col1 POINT,
|
|||||||
col2 POINT
|
col2 POINT
|
||||||
);
|
);
|
||||||
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
||||||
|
ERROR 42000: Key column 'col1' doesn't exist in table
|
||||||
|
CREATE SPATIAL INDEX idx0 ON t2 (col0, col2);
|
||||||
ERROR HY000: Incorrect arguments to SPATIAL INDEX
|
ERROR HY000: Incorrect arguments to SPATIAL INDEX
|
||||||
CREATE TABLE t4 (
|
CREATE TABLE t4 (
|
||||||
col0 INTEGER NOT NULL,
|
col0 INTEGER NOT NULL,
|
||||||
|
@ -1562,7 +1562,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p);
|
|||||||
ERROR HY000: Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
ERROR HY000: Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||||
show warnings;
|
show warnings;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns.
|
||||||
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||||
Warning 1215 Cannot add foreign key constraint for `child`
|
Warning 1215 Cannot add foreign key constraint for `child`
|
||||||
ALTER TABLE parent DROP INDEX idx1;
|
ALTER TABLE parent DROP INDEX idx1;
|
||||||
@ -1570,7 +1570,7 @@ ALTER TABLE child ADD FOREIGN KEY(p) REFERENCES parent(p);
|
|||||||
Got one of the listed errors
|
Got one of the listed errors
|
||||||
show warnings;
|
show warnings;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.
|
Warning 150 Alter table `test`.`child` with foreign key (p) constraint failed. There is only prefix index in the referenced table where the referenced columns appear as the first columns.
|
||||||
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
Error 1005 Can't create table `test`.`child` (errno: 150 "Foreign key constraint is incorrectly formed")
|
||||||
Warning 1215 Cannot add foreign key constraint for `child`
|
Warning 1215 Cannot add foreign key constraint for `child`
|
||||||
ALTER TABLE child DROP INDEX idx2;
|
ALTER TABLE child DROP INDEX idx2;
|
||||||
|
@ -839,8 +839,10 @@ CREATE TABLE t3 (
|
|||||||
);
|
);
|
||||||
|
|
||||||
# --error ER_TOO_MANY_KEY_PARTS
|
# --error ER_TOO_MANY_KEY_PARTS
|
||||||
--error ER_WRONG_ARGUMENTS
|
--error ER_KEY_COLUMN_DOES_NOT_EXITS
|
||||||
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
CREATE SPATIAL INDEX idx0 ON t2 (col1, col2);
|
||||||
|
--error ER_WRONG_ARGUMENTS
|
||||||
|
CREATE SPATIAL INDEX idx0 ON t2 (col0, col2);
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE t4 (
|
CREATE TABLE t4 (
|
||||||
|
@ -171,9 +171,11 @@ Note 1071 Specified key was too long; max key length is 1536 bytes
|
|||||||
create index idx3 on worklog5743_8(a2(3072));
|
create index idx3 on worklog5743_8(a2(3072));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1071 Specified key was too long; max key length is 1536 bytes
|
Note 1071 Specified key was too long; max key length is 1536 bytes
|
||||||
|
Note 1831 Duplicate index `idx3`. This is deprecated and will be disallowed in a future release
|
||||||
show warnings;
|
show warnings;
|
||||||
Level Code Message
|
Level Code Message
|
||||||
Note 1071 Specified key was too long; max key length is 1536 bytes
|
Note 1071 Specified key was too long; max key length is 1536 bytes
|
||||||
|
Note 1831 Duplicate index `idx3`. This is deprecated and will be disallowed in a future release
|
||||||
create index idx4 on worklog5743_8(a1, a2(1533));
|
create index idx4 on worklog5743_8(a1, a2(1533));
|
||||||
ERROR 42000: Specified key was too long; max key length is 1536 bytes
|
ERROR 42000: Specified key was too long; max key length is 1536 bytes
|
||||||
show warnings;
|
show warnings;
|
||||||
@ -355,6 +357,7 @@ Note 1071 Specified key was too long; max key length is 1536 bytes
|
|||||||
create index idx2 on worklog5743(a(3072));
|
create index idx2 on worklog5743(a(3072));
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1071 Specified key was too long; max key length is 1536 bytes
|
Note 1071 Specified key was too long; max key length is 1536 bytes
|
||||||
|
Note 1831 Duplicate index `idx2`. This is deprecated and will be disallowed in a future release
|
||||||
SET sql_mode= default;
|
SET sql_mode= default;
|
||||||
show create table worklog5743;
|
show create table worklog5743;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
|
@ -176,7 +176,8 @@ Key::Key(const Key &rhs, MEM_ROOT *mem_root)
|
|||||||
name(rhs.name),
|
name(rhs.name),
|
||||||
option_list(rhs.option_list),
|
option_list(rhs.option_list),
|
||||||
generated(rhs.generated), invisible(false),
|
generated(rhs.generated), invisible(false),
|
||||||
without_overlaps(rhs.without_overlaps), old(rhs.old), period(rhs.period)
|
without_overlaps(rhs.without_overlaps), old(rhs.old), length(rhs.length),
|
||||||
|
period(rhs.period)
|
||||||
{
|
{
|
||||||
list_copy_and_replace_each_value(columns, mem_root);
|
list_copy_and_replace_each_value(columns, mem_root);
|
||||||
}
|
}
|
||||||
|
@ -424,6 +424,7 @@ public:
|
|||||||
bool invisible;
|
bool invisible;
|
||||||
bool without_overlaps;
|
bool without_overlaps;
|
||||||
bool old;
|
bool old;
|
||||||
|
uint length;
|
||||||
Lex_ident period;
|
Lex_ident period;
|
||||||
|
|
||||||
Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
|
Key(enum Keytype type_par, const LEX_CSTRING *name_arg,
|
||||||
@ -431,7 +432,7 @@ public:
|
|||||||
:DDL_options(ddl_options),
|
:DDL_options(ddl_options),
|
||||||
type(type_par), key_create_info(default_key_create_info),
|
type(type_par), key_create_info(default_key_create_info),
|
||||||
name(*name_arg), option_list(NULL), generated(generated_arg),
|
name(*name_arg), option_list(NULL), generated(generated_arg),
|
||||||
invisible(false), without_overlaps(false), old(false)
|
invisible(false), without_overlaps(false), old(false), length(0)
|
||||||
{
|
{
|
||||||
key_create_info.algorithm= algorithm_arg;
|
key_create_info.algorithm= algorithm_arg;
|
||||||
}
|
}
|
||||||
@ -442,7 +443,7 @@ public:
|
|||||||
:DDL_options(ddl_options),
|
:DDL_options(ddl_options),
|
||||||
type(type_par), key_create_info(*key_info_arg), columns(*cols),
|
type(type_par), key_create_info(*key_info_arg), columns(*cols),
|
||||||
name(*name_arg), option_list(create_opt), generated(generated_arg),
|
name(*name_arg), option_list(create_opt), generated(generated_arg),
|
||||||
invisible(false), without_overlaps(false), old(false)
|
invisible(false), without_overlaps(false), old(false), length(0)
|
||||||
{}
|
{}
|
||||||
Key(const Key &rhs, MEM_ROOT *mem_root);
|
Key(const Key &rhs, MEM_ROOT *mem_root);
|
||||||
virtual ~Key() = default;
|
virtual ~Key() = default;
|
||||||
|
586
sql/sql_table.cc
586
sql/sql_table.cc
@ -3558,6 +3558,303 @@ key_add_part_check_null(const handler *file, KEY *key_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
my_bool key_check_without_overlaps(THD *thd, HA_CREATE_INFO *create_info,
|
||||||
|
Alter_info *alter_info,
|
||||||
|
Key &key)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("key_check_without_overlaps");
|
||||||
|
if (!key.without_overlaps)
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
// append_system_key_parts is already called, so we should check all the
|
||||||
|
// columns except the last two.
|
||||||
|
const auto &period_start= create_info->period_info.period.start;
|
||||||
|
const auto &period_end= create_info->period_info.period.end;
|
||||||
|
List_iterator<Key_part_spec> part_it_forwarded(key.columns);
|
||||||
|
List_iterator<Key_part_spec> part_it(key.columns);
|
||||||
|
part_it_forwarded++;
|
||||||
|
part_it_forwarded++;
|
||||||
|
while (part_it_forwarded++)
|
||||||
|
{
|
||||||
|
Key_part_spec *key_part= part_it++;
|
||||||
|
|
||||||
|
if (period_start.streq(key_part->field_name)
|
||||||
|
|| period_end.streq(key_part->field_name))
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_CONTAINS_PERIOD_FIELDS, MYF(0), key.name.str,
|
||||||
|
key_part->field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.key_create_info.algorithm == HA_KEY_ALG_HASH ||
|
||||||
|
key.key_create_info.algorithm == HA_KEY_ALG_LONG_HASH)
|
||||||
|
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key.name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
for (Key &key2: alter_info->key_list)
|
||||||
|
{
|
||||||
|
if (key2.type != Key::FOREIGN_KEY)
|
||||||
|
continue;
|
||||||
|
DBUG_ASSERT(&key != &key2);
|
||||||
|
const Foreign_key &fk= (Foreign_key&)key2;
|
||||||
|
if (fk.update_opt != FK_OPTION_CASCADE)
|
||||||
|
continue;
|
||||||
|
for (Key_part_spec& kp: key.columns)
|
||||||
|
{
|
||||||
|
for (Key_part_spec& kp2: fk.columns)
|
||||||
|
{
|
||||||
|
if (kp.field_name.streq(kp2.field_name))
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key.name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
create_info->period_info.unique_keys++;
|
||||||
|
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
my_bool init_key_part_spec(THD *thd, Alter_info *alter_info,
|
||||||
|
const handler *file,
|
||||||
|
const Key &key, Key_part_spec &kp,
|
||||||
|
uint max_key_length, uint max_key_part_length,
|
||||||
|
bool *is_hash_field_needed)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("init_key_part_spec");
|
||||||
|
|
||||||
|
const Lex_ident &field_name= kp.field_name;
|
||||||
|
Create_field *column= NULL;
|
||||||
|
|
||||||
|
for (Create_field &c: alter_info->create_list)
|
||||||
|
if (c.field_name.streq(field_name))
|
||||||
|
column= &c;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Either field is not present or field visibility is > INVISIBLE_USER
|
||||||
|
*/
|
||||||
|
if (!column || (column->invisible > INVISIBLE_USER && !kp.generated))
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DBUG_EVALUATE_IF("test_invisible_index", 0, 1)
|
||||||
|
&& column->invisible > INVISIBLE_USER
|
||||||
|
&& !(column->flags & VERS_SYSTEM_FIELD) && !key.invisible)
|
||||||
|
{
|
||||||
|
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type_handler *type_handler= column->type_handler();
|
||||||
|
switch(key.type)
|
||||||
|
{
|
||||||
|
case Key::FULLTEXT:
|
||||||
|
if (type_handler->Key_part_spec_init_ft(&kp, *column))
|
||||||
|
{
|
||||||
|
my_error(ER_BAD_FT_COLUMN, MYF(0), field_name.str);
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key::SPATIAL:
|
||||||
|
if (type_handler->Key_part_spec_init_spatial(&kp, *column))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key::PRIMARY:
|
||||||
|
if (column->vcol_info)
|
||||||
|
{
|
||||||
|
my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (type_handler->Key_part_spec_init_primary(&kp, *column, file))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key::MULTIPLE:
|
||||||
|
if (type_handler->Key_part_spec_init_multiple(&kp, *column, file))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key::FOREIGN_KEY:
|
||||||
|
if (type_handler->Key_part_spec_init_foreign(&kp, *column, file))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Key::UNIQUE:
|
||||||
|
if (type_handler->Key_part_spec_init_unique(&kp, *column, file,
|
||||||
|
is_hash_field_needed))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint key_part_length= type_handler->calc_key_length(*column);
|
||||||
|
|
||||||
|
if (kp.length)
|
||||||
|
{
|
||||||
|
if (f_is_blob(column->pack_flag))
|
||||||
|
{
|
||||||
|
key_part_length= MY_MIN(kp.length,
|
||||||
|
blob_length_by_type(column->real_field_type())
|
||||||
|
* column->charset->mbmaxlen);
|
||||||
|
if (key_part_length > max_key_length ||
|
||||||
|
key_part_length > max_key_part_length)
|
||||||
|
{
|
||||||
|
if (key.type == Key::MULTIPLE)
|
||||||
|
{
|
||||||
|
key_part_length= MY_MIN(max_key_length, max_key_part_length);
|
||||||
|
/* not a critical problem */
|
||||||
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||||
|
ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY),
|
||||||
|
key_part_length);
|
||||||
|
/* Align key length to multibyte char boundary */
|
||||||
|
key_part_length-= key_part_length % column->charset->mbmaxlen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Catch invalid use of partial keys
|
||||||
|
else if (!f_is_geom(column->pack_flag) &&
|
||||||
|
// is the key partial?
|
||||||
|
kp.length != key_part_length &&
|
||||||
|
// is prefix length bigger than field length?
|
||||||
|
(kp.length > key_part_length ||
|
||||||
|
// can the field have a partial key?
|
||||||
|
!type_handler->type_can_have_key_part() ||
|
||||||
|
// a packed field can't be used in a partial key
|
||||||
|
f_is_packed(column->pack_flag) ||
|
||||||
|
// does the storage engine allow prefixed search?
|
||||||
|
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
|
||||||
|
// and is this a 'unique' key?
|
||||||
|
(key.type == Key::PRIMARY || key.type == Key::UNIQUE))))
|
||||||
|
{
|
||||||
|
my_message(ER_WRONG_SUB_KEY, ER_THD(thd, ER_WRONG_SUB_KEY), MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
|
||||||
|
key_part_length= kp.length;
|
||||||
|
}
|
||||||
|
else if (key_part_length == 0 && (column->flags & NOT_NULL_FLAG) &&
|
||||||
|
!*is_hash_field_needed)
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(), field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (key_part_length > max_key_part_length && key.type != Key::FULLTEXT)
|
||||||
|
{
|
||||||
|
if (key.type == Key::MULTIPLE)
|
||||||
|
{
|
||||||
|
key_part_length= max_key_part_length;
|
||||||
|
/* not a critical problem */
|
||||||
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
||||||
|
ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY),
|
||||||
|
key_part_length);
|
||||||
|
/* Align key length to multibyte char boundary */
|
||||||
|
key_part_length-= key_part_length % column->charset->mbmaxlen;
|
||||||
|
}
|
||||||
|
else if (key.type != Key::UNIQUE)
|
||||||
|
{
|
||||||
|
key_part_length= MY_MIN(max_key_length, max_key_part_length);
|
||||||
|
my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key.type == Key::UNIQUE && key_part_length > MY_MIN(max_key_length,
|
||||||
|
max_key_part_length))
|
||||||
|
*is_hash_field_needed= true;
|
||||||
|
|
||||||
|
/* We can not store key_part_length more than 2^16 - 1 in frm. */
|
||||||
|
if (*is_hash_field_needed && kp.length > UINT_MAX16)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_KEYPART, MYF(0), UINT_MAX16);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
kp.length= key_part_length;
|
||||||
|
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Initialize the key length and algorithm (if long hash).
|
||||||
|
|
||||||
|
This function does:
|
||||||
|
1. Append system key parts (versioning, periods)
|
||||||
|
2. Call Type_handler key_part initialization function.
|
||||||
|
3. Determine the length of each key_part.
|
||||||
|
4. Calculate the total Key length.
|
||||||
|
5. Determine if the key is long unique based on its length
|
||||||
|
smd result from type handler. It'll be saved in
|
||||||
|
key_create_info.algorithm as HA_KEY_ALG_LONG_HASH.
|
||||||
|
|
||||||
|
@return FALSE OK
|
||||||
|
@return TRUE error
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
my_bool init_key_info(THD *thd, Alter_info *alter_info,
|
||||||
|
HA_CREATE_INFO *create_info,
|
||||||
|
const handler *file)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("init_key_info");
|
||||||
|
uint max_key_length= file->max_key_length();
|
||||||
|
uint max_key_part_length= file->max_key_part_length();
|
||||||
|
|
||||||
|
for (Key &key: alter_info->key_list)
|
||||||
|
{
|
||||||
|
if (key.type == Key::FOREIGN_KEY)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int parts_added= append_system_key_parts(thd, create_info, &key);
|
||||||
|
if (parts_added < 0)
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
|
bool is_hash_field_needed= false;
|
||||||
|
for (Key_part_spec &kp: key.columns)
|
||||||
|
{
|
||||||
|
if (init_key_part_spec(thd, alter_info, file, key, kp,
|
||||||
|
max_key_length, max_key_part_length,
|
||||||
|
&is_hash_field_needed))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
|
key.length+= kp.length;
|
||||||
|
if (key.length > max_key_length && key.type == Key::UNIQUE)
|
||||||
|
is_hash_field_needed= true; // for case "a BLOB UNIQUE"
|
||||||
|
|
||||||
|
if (key.length > max_key_length && key.type != Key::FULLTEXT &&
|
||||||
|
!is_hash_field_needed)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
KEY_CREATE_INFO *key_cinfo= &key.key_create_info;
|
||||||
|
|
||||||
|
if (is_hash_field_needed)
|
||||||
|
{
|
||||||
|
if (key_cinfo->algorithm == HA_KEY_ALG_UNDEF)
|
||||||
|
key_cinfo->algorithm= HA_KEY_ALG_LONG_HASH;
|
||||||
|
|
||||||
|
if (key_cinfo->algorithm != HA_KEY_ALG_HASH &&
|
||||||
|
key_cinfo->algorithm != HA_KEY_ALG_LONG_HASH)
|
||||||
|
{
|
||||||
|
my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Preparation for table creation
|
Preparation for table creation
|
||||||
|
|
||||||
@ -3592,7 +3889,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
{
|
{
|
||||||
const char *key_name;
|
const char *key_name;
|
||||||
Create_field *sql_field,*dup_field;
|
Create_field *sql_field,*dup_field;
|
||||||
uint field,null_fields,max_key_length;
|
uint field,null_fields;
|
||||||
ulong record_offset= 0;
|
ulong record_offset= 0;
|
||||||
KEY_PART_INFO *key_part_info;
|
KEY_PART_INFO *key_part_info;
|
||||||
int field_no,dup_no;
|
int field_no,dup_no;
|
||||||
@ -3603,7 +3900,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
int select_field_count= C_CREATE_SELECT(create_table_mode);
|
int select_field_count= C_CREATE_SELECT(create_table_mode);
|
||||||
bool tmp_table= create_table_mode == C_ALTER_TABLE;
|
bool tmp_table= create_table_mode == C_ALTER_TABLE;
|
||||||
const bool create_simple= thd->lex->create_simple();
|
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_derived_attributes dattr(create_info->default_table_charset);
|
||||||
const Column_bulk_alter_attributes
|
const Column_bulk_alter_attributes
|
||||||
battr(create_info->alter_table_convert_to_charset);
|
battr(create_info->alter_table_convert_to_charset);
|
||||||
@ -3639,7 +3935,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
create_info->versioned());
|
create_info->versioned());
|
||||||
null_fields= 0;
|
null_fields= 0;
|
||||||
create_info->varchar= 0;
|
create_info->varchar= 0;
|
||||||
max_key_length= file->max_key_length();
|
|
||||||
|
|
||||||
/* Handle creation of sequences */
|
/* Handle creation of sequences */
|
||||||
if (create_info->sequence)
|
if (create_info->sequence)
|
||||||
@ -3838,6 +4133,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
/* special marker for keys to be ignored */
|
/* special marker for keys to be ignored */
|
||||||
static char ignore_key[1];
|
static char ignore_key[1];
|
||||||
|
|
||||||
|
if (init_key_info(thd, alter_info, create_info, file))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* Calculate number of key segements */
|
/* Calculate number of key segements */
|
||||||
*key_count= 0;
|
*key_count= 0;
|
||||||
|
|
||||||
@ -3967,10 +4265,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
key_info->name.length= strlen(key_name);
|
key_info->name.length= strlen(key_name);
|
||||||
key->name= key_info->name;
|
key->name= key_info->name;
|
||||||
|
|
||||||
int parts_added= append_system_key_parts(thd, create_info, key);
|
|
||||||
if (parts_added < 0)
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
key_parts += parts_added;
|
|
||||||
key_info++;
|
key_info++;
|
||||||
}
|
}
|
||||||
tmp=file->max_keys();
|
tmp=file->max_keys();
|
||||||
@ -3989,11 +4283,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
key_number=0;
|
key_number=0;
|
||||||
for (; (key=key_iterator++) ; key_number++)
|
for (; (key=key_iterator++) ; key_number++)
|
||||||
{
|
{
|
||||||
uint key_length=0;
|
|
||||||
Create_field *auto_increment_key= 0;
|
Create_field *auto_increment_key= 0;
|
||||||
Key_part_spec *column;
|
Key_part_spec *column;
|
||||||
|
|
||||||
is_hash_field_needed= false;
|
bool is_hash_field_needed= key->key_create_info.algorithm
|
||||||
|
== HA_KEY_ALG_LONG_HASH;
|
||||||
if (key->name.str == ignore_key)
|
if (key->name.str == ignore_key)
|
||||||
{
|
{
|
||||||
/* ignore redundant keys */
|
/* ignore redundant keys */
|
||||||
@ -4004,6 +4298,9 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key_check_without_overlaps(thd, create_info, alter_info, *key))
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
switch (key->type) {
|
switch (key->type) {
|
||||||
case Key::MULTIPLE:
|
case Key::MULTIPLE:
|
||||||
key_info->flags= 0;
|
key_info->flags= 0;
|
||||||
@ -4034,10 +4331,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
if (key->generated)
|
if (key->generated)
|
||||||
key_info->flags|= HA_GENERATED_KEY;
|
key_info->flags|= HA_GENERATED_KEY;
|
||||||
|
|
||||||
|
key_info->key_length= key->length;
|
||||||
key_info->user_defined_key_parts=(uint8) key->columns.elements;
|
key_info->user_defined_key_parts=(uint8) key->columns.elements;
|
||||||
key_info->key_part=key_part_info;
|
key_info->key_part=key_part_info;
|
||||||
key_info->usable_key_parts= key_number;
|
key_info->usable_key_parts= key_number;
|
||||||
key_info->algorithm= key->key_create_info.algorithm;
|
key_info->algorithm= key->key_create_info.algorithm;
|
||||||
|
key_info->without_overlaps= key->without_overlaps;
|
||||||
key_info->option_list= key->option_list;
|
key_info->option_list= key->option_list;
|
||||||
extend_option_list(thd, create_info->db_type, !key->old,
|
extend_option_list(thd, create_info->db_type, !key->old,
|
||||||
&key_info->option_list, create_info->db_type->index_options);
|
&key_info->option_list, create_info->db_type->index_options);
|
||||||
@ -4121,37 +4420,11 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
|
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
|
||||||
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
|
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
|
||||||
{
|
{
|
||||||
Key_part_spec *dup_column;
|
|
||||||
|
|
||||||
it.rewind();
|
it.rewind();
|
||||||
field=0;
|
field=0;
|
||||||
while ((sql_field=it++) &&
|
while ((sql_field=it++) &&
|
||||||
lex_string_cmp(scs, &column->field_name, &sql_field->field_name))
|
lex_string_cmp(scs, &column->field_name, &sql_field->field_name))
|
||||||
field++;
|
field++;
|
||||||
/*
|
|
||||||
Either field is not present or field visibility is > INVISIBLE_USER
|
|
||||||
*/
|
|
||||||
if (!sql_field || (sql_field->invisible > INVISIBLE_USER &&
|
|
||||||
!column->generated))
|
|
||||||
{
|
|
||||||
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
if (sql_field->invisible > INVISIBLE_USER &&
|
|
||||||
!(sql_field->flags & VERS_SYSTEM_FIELD) &&
|
|
||||||
!key->invisible && DBUG_EVALUATE_IF("test_invisible_index", 0, 1))
|
|
||||||
{
|
|
||||||
my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
while ((dup_column= cols2++) != column)
|
|
||||||
{
|
|
||||||
if (!lex_string_cmp(scs, &column->field_name, &dup_column->field_name))
|
|
||||||
{
|
|
||||||
my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sql_field->compression_method())
|
if (sql_field->compression_method())
|
||||||
{
|
{
|
||||||
@ -4161,12 +4434,10 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cols2.rewind();
|
cols2.rewind();
|
||||||
switch(key->type) {
|
switch(key->type)
|
||||||
|
{
|
||||||
case Key::FULLTEXT:
|
case Key::FULLTEXT:
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_ft(column,
|
if (ft_key_charset && sql_field->charset != ft_key_charset)
|
||||||
*sql_field) ||
|
|
||||||
(ft_key_charset && sql_field->charset != ft_key_charset))
|
|
||||||
{
|
{
|
||||||
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
|
my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
@ -4174,64 +4445,46 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
ft_key_charset= sql_field->charset;
|
ft_key_charset= sql_field->charset;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::SPATIAL:
|
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_spatial(column,
|
|
||||||
*sql_field) ||
|
|
||||||
sql_field->check_vcol_for_key(thd))
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
|
||||||
{
|
|
||||||
my_message(ER_SPATIAL_CANT_HAVE_NULL,
|
|
||||||
ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Key::PRIMARY:
|
case Key::PRIMARY:
|
||||||
if (sql_field->vcol_info)
|
|
||||||
{
|
|
||||||
my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_primary(column,
|
|
||||||
*sql_field,
|
|
||||||
file))
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
if (!(sql_field->flags & NOT_NULL_FLAG))
|
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||||
{
|
{
|
||||||
/* Implicitly set primary key fields to NOT NULL for ISO conf. */
|
/* Implicitly set primary key fields to NOT NULL for ISO conformance. */
|
||||||
sql_field->flags|= NOT_NULL_FLAG;
|
sql_field->flags|= NOT_NULL_FLAG;
|
||||||
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
|
sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
|
||||||
null_fields--;
|
null_fields--;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Key::MULTIPLE:
|
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_multiple(column,
|
|
||||||
*sql_field,
|
|
||||||
file) ||
|
|
||||||
sql_field->check_vcol_for_key(thd) ||
|
|
||||||
key_add_part_check_null(file, key_info, sql_field, column))
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Key::FOREIGN_KEY:
|
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_foreign(column,
|
|
||||||
*sql_field,
|
|
||||||
file) ||
|
|
||||||
sql_field->check_vcol_for_key(thd) ||
|
|
||||||
key_add_part_check_null(file, key_info, sql_field, column))
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Key::UNIQUE:
|
case Key::UNIQUE:
|
||||||
if (sql_field->type_handler()->Key_part_spec_init_unique(column,
|
case Key::MULTIPLE:
|
||||||
*sql_field, file,
|
case Key::FOREIGN_KEY:
|
||||||
&is_hash_field_needed) ||
|
if (key_add_part_check_null(file, key_info, sql_field, column))
|
||||||
sql_field->check_vcol_for_key(thd) ||
|
DBUG_RETURN(TRUE);
|
||||||
key_add_part_check_null(file, key_info, sql_field, column))
|
if (sql_field->check_vcol_for_key(thd))
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Key::SPATIAL:
|
||||||
|
if (!(sql_field->flags & NOT_NULL_FLAG))
|
||||||
|
{
|
||||||
|
my_message(ER_SPATIAL_CANT_HAVE_NULL,
|
||||||
|
ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (sql_field->check_vcol_for_key(thd))
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const Key_part_spec &kp2: key->columns)
|
||||||
|
{
|
||||||
|
if (column == &kp2)
|
||||||
|
break;
|
||||||
|
if (kp2.field_name.streq(column->field_name))
|
||||||
|
{
|
||||||
|
my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str);
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
|
if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
|
||||||
@ -4246,111 +4499,21 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
key_part_info->fieldnr= field;
|
key_part_info->fieldnr= field;
|
||||||
key_part_info->offset= (uint16) sql_field->offset;
|
key_part_info->offset= (uint16) sql_field->offset;
|
||||||
key_part_info->key_type=sql_field->pack_flag;
|
key_part_info->key_type=sql_field->pack_flag;
|
||||||
uint key_part_length= sql_field->type_handler()->
|
key_part_info->length= column->length;
|
||||||
calc_key_length(*sql_field);
|
|
||||||
|
|
||||||
if (column->length)
|
|
||||||
{
|
|
||||||
if (f_is_blob(sql_field->pack_flag))
|
|
||||||
{
|
|
||||||
key_part_length= MY_MIN(column->length,
|
|
||||||
blob_length_by_type(sql_field->real_field_type())
|
|
||||||
* sql_field->charset->mbmaxlen);
|
|
||||||
if (key_part_length > max_key_length ||
|
|
||||||
key_part_length > file->max_key_part_length())
|
|
||||||
{
|
|
||||||
if (key->type == Key::MULTIPLE)
|
|
||||||
{
|
|
||||||
key_part_length= MY_MIN(max_key_length, file->max_key_part_length());
|
|
||||||
/* not a critical problem */
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
|
||||||
ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY),
|
|
||||||
key_part_length);
|
|
||||||
/* Align key length to multibyte char boundary */
|
|
||||||
key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Catch invalid use of partial keys
|
|
||||||
else if (!f_is_geom(sql_field->pack_flag) &&
|
|
||||||
// is the key partial?
|
|
||||||
column->length != key_part_length &&
|
|
||||||
// is prefix length bigger than field length?
|
|
||||||
(column->length > key_part_length ||
|
|
||||||
// can the field have a partial key?
|
|
||||||
!sql_field->type_handler()->type_can_have_key_part() ||
|
|
||||||
// a packed field can't be used in a partial key
|
|
||||||
f_is_packed(sql_field->pack_flag) ||
|
|
||||||
// does the storage engine allow prefixed search?
|
|
||||||
((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
|
|
||||||
// and is this a 'unique' key?
|
|
||||||
(key_info->flags & HA_NOSAME))))
|
|
||||||
{
|
|
||||||
my_message(ER_WRONG_SUB_KEY, ER_THD(thd, ER_WRONG_SUB_KEY), MYF(0));
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
|
|
||||||
key_part_length= column->length;
|
|
||||||
}
|
|
||||||
else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG) &&
|
|
||||||
!is_hash_field_needed)
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(),
|
|
||||||
column->field_name.str);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
if (key_part_length > file->max_key_part_length() &&
|
|
||||||
key->type != Key::FULLTEXT)
|
|
||||||
{
|
|
||||||
if (key->type == Key::MULTIPLE)
|
|
||||||
{
|
|
||||||
key_part_length= file->max_key_part_length();
|
|
||||||
/* not a critical problem */
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
|
||||||
ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY),
|
|
||||||
key_part_length);
|
|
||||||
/* Align key length to multibyte char boundary */
|
|
||||||
key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (key->type != Key::UNIQUE)
|
|
||||||
{
|
|
||||||
key_part_length= MY_MIN(max_key_length, file->max_key_part_length());
|
|
||||||
my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key->type == Key::UNIQUE
|
|
||||||
&& key_part_length > MY_MIN(max_key_length,
|
|
||||||
file->max_key_part_length()))
|
|
||||||
is_hash_field_needed= true;
|
|
||||||
|
|
||||||
/* We can not store key_part_length more then 2^16 - 1 in frm */
|
|
||||||
if (is_hash_field_needed && column->length > UINT_MAX16)
|
|
||||||
{
|
|
||||||
my_error(ER_TOO_LONG_KEYPART, MYF(0), UINT_MAX16);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
key_part_info->length= (uint16) key_part_length;
|
|
||||||
/* Use packed keys for long strings on the first column */
|
/* Use packed keys for long strings on the first column */
|
||||||
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
|
if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
|
||||||
!((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
|
!((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
|
||||||
(key_part_length >= KEY_DEFAULT_PACK_LENGTH) &&
|
(column->length >= KEY_DEFAULT_PACK_LENGTH) &&
|
||||||
!is_hash_field_needed)
|
!is_hash_field_needed)
|
||||||
{
|
{
|
||||||
key_info->flags|= sql_field->type_handler()->KEY_pack_flags(column_nr);
|
key_info->flags|= sql_field->type_handler()->KEY_pack_flags(column_nr);
|
||||||
}
|
}
|
||||||
/* Check if the key segment is partial, set the key flag accordingly */
|
/* Check if the key segment is partial, set the key flag accordingly */
|
||||||
if (key_part_length != sql_field->type_handler()->
|
if (column->length != sql_field->type_handler()->
|
||||||
calc_key_length(*sql_field) &&
|
calc_key_length(*sql_field) &&
|
||||||
key_part_length != sql_field->type_handler()->max_octet_length())
|
column->length != sql_field->type_handler()->max_octet_length())
|
||||||
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
|
key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
|
||||||
|
|
||||||
key_length+= key_part_length;
|
|
||||||
key_part_info++;
|
key_part_info++;
|
||||||
}
|
}
|
||||||
if (!key_info->name.str || check_column_name(key_info->name.str))
|
if (!key_info->name.str || check_column_name(key_info->name.str))
|
||||||
@ -4360,15 +4523,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
}
|
}
|
||||||
if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY))
|
if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY))
|
||||||
unique_key=1;
|
unique_key=1;
|
||||||
key_info->key_length=(uint16) key_length;
|
|
||||||
if (key_info->key_length > max_key_length && key->type == Key::UNIQUE)
|
|
||||||
is_hash_field_needed= true; // for case "a BLOB UNIQUE"
|
|
||||||
if (key_length > max_key_length && key->type != Key::FULLTEXT &&
|
|
||||||
!is_hash_field_needed)
|
|
||||||
{
|
|
||||||
my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check long unique keys */
|
/* Check long unique keys */
|
||||||
if (is_hash_field_needed)
|
if (is_hash_field_needed)
|
||||||
@ -4380,12 +4534,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
key_info->name.str);
|
key_info->name.str);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
if (key_info->algorithm != HA_KEY_ALG_UNDEF &&
|
|
||||||
key_info->algorithm != HA_KEY_ALG_HASH )
|
|
||||||
{
|
|
||||||
my_error(ER_TOO_LONG_KEY, MYF(0), max_key_length);
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (is_hash_field_needed ||
|
if (is_hash_field_needed ||
|
||||||
(key_info->algorithm == HA_KEY_ALG_HASH &&
|
(key_info->algorithm == HA_KEY_ALG_HASH &&
|
||||||
@ -4425,40 +4573,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
// Check if a duplicate index is defined.
|
// Check if a duplicate index is defined.
|
||||||
check_duplicate_key(thd, key, key_info, &alter_info->key_list);
|
check_duplicate_key(thd, key, key_info, &alter_info->key_list);
|
||||||
|
|
||||||
key_info->without_overlaps= key->without_overlaps;
|
|
||||||
if (key_info->without_overlaps)
|
|
||||||
{
|
|
||||||
if (key_info->algorithm == HA_KEY_ALG_HASH ||
|
|
||||||
key_info->algorithm == HA_KEY_ALG_LONG_HASH)
|
|
||||||
|
|
||||||
{
|
|
||||||
without_overlaps_err:
|
|
||||||
my_error(ER_KEY_CANT_HAVE_WITHOUT_OVERLAPS, MYF(0), key_info->name.str);
|
|
||||||
DBUG_RETURN(true);
|
|
||||||
}
|
|
||||||
key_iterator2.rewind();
|
|
||||||
while ((key2 = key_iterator2++))
|
|
||||||
{
|
|
||||||
if (key2->type != Key::FOREIGN_KEY)
|
|
||||||
continue;
|
|
||||||
DBUG_ASSERT(key != key2);
|
|
||||||
Foreign_key *fk= (Foreign_key*) key2;
|
|
||||||
if (fk->update_opt != FK_OPTION_CASCADE)
|
|
||||||
continue;
|
|
||||||
for (Key_part_spec& kp: key->columns)
|
|
||||||
{
|
|
||||||
for (Key_part_spec& kp2: fk->columns)
|
|
||||||
{
|
|
||||||
if (!lex_string_cmp(scs, &kp.field_name, &kp2.field_name))
|
|
||||||
{
|
|
||||||
goto without_overlaps_err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
create_info->period_info.unique_keys++;
|
|
||||||
}
|
|
||||||
|
|
||||||
key_info++;
|
key_info++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4886,20 +5000,6 @@ static int append_system_key_parts(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
my_error(ER_PERIOD_NOT_FOUND, MYF(0), key->period.str);
|
my_error(ER_PERIOD_NOT_FOUND, MYF(0), key->period.str);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &period_start= create_info->period_info.period.start;
|
|
||||||
const auto &period_end= create_info->period_info.period.end;
|
|
||||||
List_iterator<Key_part_spec> part_it(key->columns);
|
|
||||||
while (Key_part_spec *key_part= part_it++)
|
|
||||||
{
|
|
||||||
if (period_start.streq(key_part->field_name)
|
|
||||||
|| period_end.streq(key_part->field_name))
|
|
||||||
{
|
|
||||||
my_error(ER_KEY_CONTAINS_PERIOD_FIELDS, MYF(0), key->name.str,
|
|
||||||
key_part->field_name.str);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const auto &period= create_info->period_info.period;
|
const auto &period= create_info->period_info.period;
|
||||||
key->columns.push_back(new (thd->mem_root)
|
key->columns.push_back(new (thd->mem_root)
|
||||||
Key_part_spec(&period.end, 0, true));
|
Key_part_spec(&period.end, 0, true));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user