Commit cdf72d51 authored by Raghav Kapoor's avatar Raghav Kapoor

BUG#17665767 - FAILING ASSERTION: PRIMARY_KEY_NO == -1 || PRIMARY_KEY_NO == 0

BACKGROUND:
This bug is a followup on Bug#16368875.
The assertion failure happens because in SQL layer the key
does not get promoted to PRIMARY KEY but InnoDB takes it
as PRIMARY KEY.

ANALYSIS:
Here we are trying to create an index on POINT (GEOMETRY)
data type which is a type of BLOB (since GEOMETRY is a
subclass of BLOB).
In general, we can't create an index over GEOMETRY family
type field unless we specify the length of the
keypart (similar to BLOB fields).
Only exception is the POINT field type. The POINT column
max size is 25. The problem is that the field is not treated
as PRIMARY KEY when we create a index on POINT column using
its max column size as key part prefix. The fix would allow
index on POINT column to be treated as PRIMARY KEY.

FIX:
Patch for Bug#16368875 is extended to take into account
GEOMETRY datatype, POINT in particular to consider it
as PRIMARY KEY in SQL layer.
parent d63645c8
...@@ -3459,7 +3459,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3459,7 +3459,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
} }
if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type == if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
Field::GEOM_POINT) Field::GEOM_POINT)
column->length= 25; column->length= MAX_LEN_GEOM_POINT_FIELD;
if (!column->length) if (!column->length)
{ {
my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str); my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
......
...@@ -105,6 +105,9 @@ enum enum_explain_filename_mode ...@@ -105,6 +105,9 @@ enum enum_explain_filename_mode
EXPLAIN_PARTITIONS_AS_COMMENT EXPLAIN_PARTITIONS_AS_COMMENT
}; };
/* Maximum length of GEOM_POINT Field */
#define MAX_LEN_GEOM_POINT_FIELD 25
/* depends on errmsg.txt Database `db`, Table `t` ... */ /* depends on errmsg.txt Database `db`, Table `t` ... */
#define EXPLAIN_FILENAME_MAX_EXTRA_LENGTH 63 #define EXPLAIN_FILENAME_MAX_EXTRA_LENGTH 63
......
...@@ -5603,7 +5603,8 @@ spatial_type: ...@@ -5603,7 +5603,8 @@ spatial_type:
| GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; } | GEOMETRYCOLLECTION { $$= Field::GEOM_GEOMETRYCOLLECTION; }
| POINT_SYM | POINT_SYM
{ {
Lex->length= (char*)"25"; Lex->length= const_cast<char*>(STRINGIFY_ARG
(MAX_LEN_GEOM_POINT_FIELD));
$$= Field::GEOM_POINT; $$= Field::GEOM_POINT;
} }
| MULTIPOINT { $$= Field::GEOM_MULTIPOINT; } | MULTIPOINT { $$= Field::GEOM_MULTIPOINT; }
......
...@@ -1539,6 +1539,17 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head, ...@@ -1539,6 +1539,17 @@ static int open_binary_frm(THD *thd, TABLE_SHARE *share, uchar *head,
table_field->type() == MYSQL_TYPE_BLOB && table_field->type() == MYSQL_TYPE_BLOB &&
table_field->field_length == key_part[i].length) table_field->field_length == key_part[i].length)
continue; continue;
/*
If the key column is of NOT NULL GEOMETRY type, specifically POINT
type whose length is known internally (which is 25). And key part
prefix size is equal to the POINT column max size, then we can
promote it to primary key.
*/
if (!table_field->real_maybe_null() &&
table_field->type() == MYSQL_TYPE_GEOMETRY &&
table_field->get_geometry_type() == Field::GEOM_POINT &&
key_part[i].length == MAX_LEN_GEOM_POINT_FIELD)
continue;
if (table_field->real_maybe_null() || if (table_field->real_maybe_null() ||
table_field->key_length() != key_part[i].length) table_field->key_length() != key_part[i].length)
......
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