summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-06-11 07:54:37 +0400
committerAlexander Barkov <bar@mariadb.com>2019-06-11 07:54:37 +0400
commitf42bda6d7578297c016279abcc7e177237206724 (patch)
tree01db4eed8dfe737a85aa8a0bcecf89e0f09b5579
parent163665640afb153c173d272eae98b0b63950cd83 (diff)
downloadmariadb-git-f42bda6d7578297c016279abcc7e177237206724.tar.gz
MDEV-19727 Add Type_handler::Key_part_spec_init_ft
-rw-r--r--mysql-test/main/column_compression.result16
-rw-r--r--mysql-test/main/column_compression.test29
-rw-r--r--mysql-test/main/type_varchar.result29
-rw-r--r--mysql-test/main/type_varchar.test23
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sql_table.cc67
-rw-r--r--sql/sql_type.h12
7 files changed, 162 insertions, 19 deletions
diff --git a/mysql-test/main/column_compression.result b/mysql-test/main/column_compression.result
index c783e7fd1e9..228b26dc67d 100644
--- a/mysql-test/main/column_compression.result
+++ b/mysql-test/main/column_compression.result
@@ -1486,3 +1486,19 @@ WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
COLUMN_TYPE
varchar(1000) /*!100301 COMPRESSED*/
DROP TABLE t1;
+#
+# End of 10.3 tests
+#
+#
+# Start of 10.5 tests
+#
+#
+# MDEV-19727 Add Type_handler::Key_part_spec_init_ft
+#
+CREATE TABLE t1 (a VARCHAR(1000) COMPRESSED, FULLTEXT INDEX(a));
+ERROR HY000: Compressed column 'a' can't be used in key specification
+CREATE TABLE t1 (a TEXT COMPRESSED, FULLTEXT INDEX(a));
+ERROR HY000: Compressed column 'a' can't be used in key specification
+#
+# End of 10.5 tests
+#
diff --git a/mysql-test/main/column_compression.test b/mysql-test/main/column_compression.test
index c9d0014ab9e..183fc38151c 100644
--- a/mysql-test/main/column_compression.test
+++ b/mysql-test/main/column_compression.test
@@ -181,3 +181,32 @@ SHOW CREATE TABLE t1;
SELECT COLUMN_TYPE FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1';
DROP TABLE t1;
+
+--echo #
+--echo # End of 10.3 tests
+--echo #
+
+
+--echo #
+--echo # Start of 10.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-19727 Add Type_handler::Key_part_spec_init_ft
+--echo #
+
+#
+# Indexes on COMPRESSED columns are generally prohibited, so we don't have
+# to override Type_handler_xxx_compressed::Key_part_spec_init_ft().
+# Note, we could support FULLTEXT indexes on compressed columns eventually.
+#
+
+--error ER_COMPRESSED_COLUMN_USED_AS_KEY
+CREATE TABLE t1 (a VARCHAR(1000) COMPRESSED, FULLTEXT INDEX(a));
+
+--error ER_COMPRESSED_COLUMN_USED_AS_KEY
+CREATE TABLE t1 (a TEXT COMPRESSED, FULLTEXT INDEX(a));
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
diff --git a/mysql-test/main/type_varchar.result b/mysql-test/main/type_varchar.result
index 8911d36a020..214fb0a5b0f 100644
--- a/mysql-test/main/type_varchar.result
+++ b/mysql-test/main/type_varchar.result
@@ -723,3 +723,32 @@ SET sql_mode=DEFAULT;
#
# End of 10.4 tests
#
+#
+# Start of 10.5 tests
+#
+#
+# MDEV-15592 Column COMPRESSED should select a 'high order' datatype
+#
+TRUNCATE TABLE vchar;
+SHOW CREATE TABLE vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30)/*old*/ DEFAULT NULL,
+ `c` char(3) DEFAULT NULL,
+ `e` enum('abc','def','ghi') DEFAULT NULL,
+ `t` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE vchar ADD FULLTEXT INDEX(v);
+SHOW CREATE TABLE vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30) DEFAULT NULL,
+ `c` char(3) DEFAULT NULL,
+ `e` enum('abc','def','ghi') DEFAULT NULL,
+ `t` text DEFAULT NULL,
+ FULLTEXT KEY `v` (`v`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE vchar;
+#
+# End of 10.5 tests
+#
diff --git a/mysql-test/main/type_varchar.test b/mysql-test/main/type_varchar.test
index 86f16afc56f..ab02549394a 100644
--- a/mysql-test/main/type_varchar.test
+++ b/mysql-test/main/type_varchar.test
@@ -359,3 +359,26 @@ SET sql_mode=DEFAULT;
--echo #
--echo # End of 10.4 tests
--echo #
+
+--echo #
+--echo # Start of 10.5 tests
+--echo #
+
+--echo #
+--echo # MDEV-15592 Column COMPRESSED should select a 'high order' datatype
+--echo #
+
+#
+# Old VARCHAR is automatically upgraded to new VARCHAR.
+# So we don't have to override Type_handler_var_string::Key_part_spec_init_ft()
+#
+copy_file $MYSQL_TEST_DIR/std_data/vchar.frm $MYSQLD_DATADIR/test/vchar.frm;
+TRUNCATE TABLE vchar;
+SHOW CREATE TABLE vchar;
+ALTER TABLE vchar ADD FULLTEXT INDEX(v);
+SHOW CREATE TABLE vchar;
+DROP TABLE vchar;
+
+--echo #
+--echo # End of 10.5 tests
+--echo #
diff --git a/sql/sql_string.h b/sql/sql_string.h
index caefee7ec09..3c112c94fe9 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -138,6 +138,11 @@ public:
CHARSET_INFO *charset() const { return m_charset; }
uint mbminlen() const { return m_charset->mbminlen; }
uint mbmaxlen() const { return m_charset->mbmaxlen; }
+ bool is_good_for_ft() const
+ {
+ // Binary and UCS2/UTF16/UTF32 are not supported
+ return m_charset != &my_charset_bin && m_charset->mbminlen == 1;
+ }
size_t numchars(const char *str, const char *end) const
{
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index a5c6f1336c5..65de2ff6b11 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3361,6 +3361,45 @@ mysql_add_invisible_index(THD *thd, List<Key> *key_list,
key_list->push_back(key, thd->mem_root);
return key;
}
+
+
+bool Type_handler_string::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ /*
+ Set length to 0. It's set to the real column width later for CHAR.
+ It has to be the correct col width for CHAR, as its data are not
+ prefixed with length (unlike blobs).
+ */
+ part->length= 0;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
+bool Type_handler_varchar::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ part->length= 0;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
+bool
+Type_handler_blob_common::Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def)
+ const
+{
+ /*
+ Set keyseg length to 1 for blobs.
+ It's ignored in ft code: the data length is taken from the length prefix.
+ */
+ part->length= 1;
+ return !Charset(def.charset).is_good_for_ft();
+}
+
+
/*
Preparation for table creation
@@ -3894,28 +3933,18 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
cols2.rewind();
if (key->type == Key::FULLTEXT)
{
- if ((sql_field->real_field_type() != MYSQL_TYPE_STRING &&
- sql_field->real_field_type() != MYSQL_TYPE_VARCHAR &&
- !f_is_blob(sql_field->pack_flag)) ||
- sql_field->charset == &my_charset_bin ||
- sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
- (ft_key_charset && sql_field->charset != ft_key_charset))
- {
- my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
- DBUG_RETURN(-1);
- }
- ft_key_charset=sql_field->charset;
- /*
- for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
- code anyway, and 0 (set to column width later) for char's. it has
- to be correct col width for char's, as char data are not prefixed
- with length (unlike blobs, where ft code takes data length from a
- data prefix, ignoring column->length).
- */
- column->length= MY_TEST(f_is_blob(sql_field->pack_flag));
+ if (sql_field->type_handler()->Key_part_spec_init_ft(column,
+ *sql_field) ||
+ (ft_key_charset && sql_field->charset != ft_key_charset))
+ {
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
+ DBUG_RETURN(-1);
+ }
+ ft_key_charset=sql_field->charset;
}
else
{
+
column->length*= sql_field->charset->mbmaxlen;
if (key->type == Key::SPATIAL)
diff --git a/sql/sql_type.h b/sql/sql_type.h
index 7daefcb10d7..0376cd84443 100644
--- a/sql/sql_type.h
+++ b/sql/sql_type.h
@@ -34,6 +34,7 @@ C_MODE_END
class Field;
class Column_definition;
class Column_definition_attributes;
+class Key_part_spec;
class Item;
class Item_const;
class Item_literal;
@@ -3456,6 +3457,11 @@ public:
virtual bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const= 0;
+ virtual bool Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def) const
+ {
+ return true; // Error
+ }
virtual Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
@@ -6002,6 +6008,8 @@ public:
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
@@ -6084,6 +6092,8 @@ public:
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def) const;
Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr,
const Type_all_attributes &attr,
@@ -6157,6 +6167,8 @@ public:
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
+ bool Key_part_spec_init_ft(Key_part_spec *part,
+ const Column_definition &def) const;
bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,