Merge lp:~laurynas-biveinis/percona-server/tokudb-multiple-clust-keys into lp:percona-server/5.6

Proposed by Laurynas Biveinis
Status: Merged
Approved by: Alexey Kopytov
Approved revision: 568
Merged at revision: 571
Proposed branch: lp:~laurynas-biveinis/percona-server/tokudb-multiple-clust-keys
Merge into: lp:percona-server/5.6
Diff against target: 607 lines (+318/-27)
14 files modified
include/my_base.h (+3/-1)
include/mysql_com.h (+2/-0)
mysql-test/r/tokudb_clustering_key_grammar.result (+73/-0)
mysql-test/t/tokudb_clustering_key_grammar.test (+99/-0)
sql/handler.h (+5/-0)
sql/lex.h (+1/-0)
sql/sql_class.h (+2/-1)
sql/sql_parse.cc (+12/-5)
sql/sql_show.cc (+3/-0)
sql/sql_table.cc (+25/-6)
sql/sql_yacc.yy (+61/-11)
sql/table.cc (+21/-1)
sql/unireg.cc (+9/-1)
tests/mysql_client_test.c (+2/-1)
To merge this branch: bzr merge lp:~laurynas-biveinis/percona-server/tokudb-multiple-clust-keys
Reviewer Review Type Date Requested Status
Alexey Kopytov (community) Approve
Laurynas Biveinis Pending
Review via email: mp+212834@code.launchpad.net

This proposal supersedes a proposal from 2014-02-26.

Description of the change

4th MP:

Disallow Key::CLUSTERING alone as a valid key type and enforce Key::MULTIPLE | Key::Clustering instead.
- add_field_to_list: add Key::MULTIPLE if needed
- mysql_prepare_create_table: forbid Key::CLUSTERING, handle Key::MULTIPLE | Key::CLUSTERING, replace all further == Key::MULTIPLE tests with & Key::MULTIPLE
- parser unique_combo_clustering symbol: add Key::MULTIPLE if needed
- setup_key_part_field: do not assume that if a field is a part of a clustering key, it cannot be a part of non-unique key.

Rebase on the current trunk.
http://jenkins.percona.com/job/percona-server-5.6-param/563/

3rd MP:

- If FRM contains SPATIAL | FULLTEXT key, check whether its SE supports clustered keys.
- Forbid UNIQUE UNIQUE and CLUSTERING CLUSTERING where UNIQUE CLUSTERING, CLUSTERING UNIQUE, UNIQUE, or CLUSTERING may appear. Add tests.
- Forbid CONSTRAINT c CLUSTERING, add tests.
- Add support for CLUSTERING as a field attribute, add tests.

http://jenkins.percona.com/job/percona-server-5.6-param/528/. Almost all its failures comes from debug saucy 64, which looks like a broken slave. I have manually downloaded one result file that it claims to diff and it's identical.

2nd MP:

- Extended the testcase to test CREATE CLUSTERING INDEX ON, to test
  CLUSTERING in combination with UNIQUE (and CONSTRAINT if UNIQUE),
  to test LOCK and ALGORITHM clauses for ALTER TABLE ADD INDEX, and
  to test the same clauses without CLUSTERING.
- Declare new handlerton flag HTON_SUPPORTS_CLUSTERED_KEYS.
- Assign values to enum Key::Keytype to support or'ing of enum
  constants.
- In mysql_prepare_create_table(), allow presence of and handle
  Key::CLUSTERING and Key::UNIQUE in a same key->type. Check for
  HTON_SUPPORTS_CLUSTERED_KEYS if Key::CLUSTERING found, and return
  HA_ILLEGAL_HA_CREATE_OPTION if unsupported.
- In mysql_prepare_alter_table(), handle both HA_CLUSTERING and
  HA_NOSAME if both present in the same key_info->flags.
- In parser, replace opt_unique clause with opt_unique_or_clustering
  that allows UNIQUE, CLUSTERING, and a combination of the two where
  previously only UNIQUE was allowed in key definitions and CREATE
  INDEX statement. This also fixes a bug from the previous approach
  which did not allow ALGORITHM and LOCK clauses for ALTER TABLE
  ... CLUSTERING ...

http://jenkins.percona.com/job/percona-server-5.6-param/494/

1st MP:

    Add support for CLUSTERING key type that is a clustering secondary
    key, that is, the whole of the row can be accessed through the index
    without going through the primary clustered index. This implements
    the query parser and index definition persistence bits,
    https://blueprints.launchpad.net/percona-server/+spec/multiple-clustering-keys.

    - New lexer symbol CLUSTERING, new key type in the grammar CREATE TABLE and
      ALTER TABLE ADD INDEX clauses.
    - New key type Key::Keytype::CLUSTERING, handle it in
      INFORMATION_SCHEMA.TABLES, write it out to FRM as a combination of
      spatial and fulltext key types, handle this combination on FRM
      read. This is to avoid a FRM format change.
    - New testcase tokudb_clustering_key_grammar.

http://jenkins.percona.com/job/percona-server-5.6-param/473/

To post a comment you must log in.
Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal

- s/INFORMATION_SCHEMA.TABLES/SHOW CREATE TABLE/ in the revision comment

- I don’t think we should allow creation of non-TokuDB tables with
  secondary clustering keys. Otherwise once the optimizer support is
  reviewed and merged, we will get optimizer making incorrect
  assumptions about secondary clustering keys for tables that don’t
  actually implement it. On top of that, bad and hard-to-diagnose
  things may happen on downgrade or migration to another server flavor;

- I see there’s no support for UNIQUE CLUSTERING KEYs. Let’s fix it if
  it’s an oversight, or document if it’s a known limitation?

- any specific reasons to add another reserved keyword to the parser?

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

Grammar rules for CLUSTERING do not include opt_index_lock_algorithm, which suggests that

ALTER TABLE t1 ADD CLUSTERING INDEX b (b), LOCK=EXCLUSIVE, ALGORITHM=COPY;

syntax is not supported. It probably should be.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

CREATE CLUSTERING INDEX b ON t1 (b)

syntax is not tested by the testcase.

CREATE CLUSTERING INDEX b ON t1 (b) LOCK=EXCLUSIVE ALGORITHM=COPY

fails with a parse error due to that missing opt_index_lock_algorithm.

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

> - s/INFORMATION_SCHEMA.TABLES/SHOW CREATE TABLE/ in the revision
> comment

Fixed.

> - I don’t think we should allow creation of non-TokuDB tables with
> secondary clustering keys. Otherwise once the optimizer support is
> reviewed and merged, we will get optimizer making incorrect
> assumptions about secondary clustering keys for tables that don’t
> actually implement it. On top of that, bad and hard-to-diagnose
> things may happen on downgrade or migration to another server
> flavor;

I agree and this was how I implemented it the first time before
Tokutek asked me to change to be treated as a hint. I didn't think of
downgrade/migration issues then or I wouldn't have changed. (I don't
see how the optimizer could make incorrect assumptions because no
other storage engine would return HA_CLUSTERING in index_flags()).

Added a handlerton flag HTON_SUPPORTS_CLUSTERED_KEYS. This is
different from e.g. HA_CAN_RTREE etc, which are handler flags, but the
property of supporting clustered keys seems to me to be global and not
of table level for a SE.

For error message I reused ER_ILLEGAL_HA_CREATE_OPTION ("Table storage
engine 'InnoDB' does not support the create option 'CLUSTERING'")

> - I see there’s no support for UNIQUE CLUSTERING KEYs. Let’s fix it if
> it’s an oversight, or document if it’s a known limitation?

An oversight on my part, not sure about Tokutek. Syntax extended as
follows. Where previously "UNIQUE" was accepted as a valid modifier,
"CLUSTERING" is accepted too, as well as "UNIQUE CLUSTERING" and
"CLUSTERING UNIQUE":
- CREATE UNIQUE INDEX;
- as a part of key definition:
  - CREATE TABLE (..., [CONSTRAINT ... ] UNIQUE KEY ...,)
  - ALTER TABLE ADD [CONSTRAINT ...] UNIQUE KEY

The way the grammar was changed, it accepts "UNIQUE UNIQUE" and
"CLUSTERING CLUSTERING" too. IMHO benign.

Also now it is possible to create such "constraints" as CONSTRAINT c1
CLUSTERING KEY, which is not really a constraint at all, but again
IMHO benign and I don't see an easy way to forbid it without blowing
up shift/reduce conflict count in the parser.

One place where the syntax was not extended was field attribute
syntax:
  - CREATE TABLE (..., b INT UNIQUE CLUSTERING KEY, ...).
It appeared to require more changes to the parser, and can be done in
a follow-up if really needed.

>
> - any specific reasons to add another reserved keyword to the
> parser?

I have reviewed the existing keywords and couldn't choose any IMHO
suitable replacement candidate. Also, I'm not sure Tokutek would
appreciate a forced mass search-replace in their testsuite that also
makes 5.5 to 5.6 upmerges less automatic.

Revision history for this message
Alexey Kopytov (akopytov) wrote : Posted in a previous version of this proposal
Download full text (4.2 KiB)

>> - s/INFORMATION_SCHEMA.TABLES/SHOW CREATE TABLE/ in the revision
>> comment
>
> Fixed.
>
>> - I don’t think we should allow creation of non-TokuDB tables with
>> secondary clustering keys. Otherwise once the optimizer support is
>> reviewed and merged, we will get optimizer making incorrect
>> assumptions about secondary clustering keys for tables that don’t
>> actually implement it. On top of that, bad and hard-to-diagnose
>> things may happen on downgrade or migration to another server
>> flavor;
>
> I agree and this was how I implemented it the first time before
> Tokutek asked me to change to be treated as a hint. I didn't think of
> downgrade/migration issues then or I wouldn't have changed. (I don't
> see how the optimizer could make incorrect assumptions because no
> other storage engine would return HA_CLUSTERING in index_flags()).
>

The best way to handle this has been implemented in MariaDB via
SE-specific options in CREATE/ALTER. I doubt we should port those
extensions as a part of this work, just pointing out that the way we are
implementing it will inevitably have unwanted side effects.

Wrt optimizer changes: there’s code in the optimizer that takes flags
from key definition into account (rather than just flags returned by the
storage engine). For example, some code checks key definition flags and
assumes it to be a regular key if none if the previous checks for
specific flags return true. If you allow CLUSTERING keys for storage
engine that don’t support them, you still get the HA_CLUSTERING key set
in key definition flags.

> Added a handlerton flag HTON_SUPPORTS_CLUSTERED_KEYS. This is
> different from e.g. HA_CAN_RTREE etc, which are handler flags, but the
> property of supporting clustered keys seems to me to be global and not
> of table level for a SE.
>
> For error message I reused ER_ILLEGAL_HA_CREATE_OPTION ("Table storage
> engine 'InnoDB' does not support the create option 'CLUSTERING'")
>

That looks good in general. Please also add code that enforces this
restriction to open_binary_frm(). I.e. it should fail with an error if a
non-InnoDB table happens to contain both HA_SPATIAL and HA_FULLTEXT
flags for an index.

>> - I see there’s no support for UNIQUE CLUSTERING KEYs. Let’s fix it if
>> it’s an oversight, or document if it’s a known limitation?
>
> An oversight on my part, not sure about Tokutek. Syntax extended as

Are you going to report it to Tokutek?

> follows. Where previously "UNIQUE" was accepted as a valid modifier,
> "CLUSTERING" is accepted too, as well as "UNIQUE CLUSTERING" and
> "CLUSTERING UNIQUE":
> - CREATE UNIQUE INDEX;
> - as a part of key definition:
> - CREATE TABLE (..., [CONSTRAINT ... ] UNIQUE KEY ...,)
> - ALTER TABLE ADD [CONSTRAINT ...] UNIQUE KEY
>
> The way the grammar was changed, it accepts "UNIQUE UNIQUE" and
> "CLUSTERING CLUSTERING" too. IMHO benign.
>

Hm, doesn’t look that benign to me. UNIQUE UNIQUE is invalid SQL which a
user may want to be aware of. It would be aware before the change. It
will not be aware after the change.

> Also now it is possible to create such "constraints" as CONSTRAINT c1
> CLUSTERING KEY, which is not really a constraint at a...

Read more...

review: Needs Fixing
Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal
Download full text (6.1 KiB)

> The best way to handle this has been implemented in MariaDB via
> SE-specific options in CREATE/ALTER. I doubt we should port those
> extensions as a part of this work, just pointing out that the way we are
> implementing it will inevitably have unwanted side effects.

Fully agreed.

> Wrt optimizer changes: there’s code in the optimizer that takes flags
> from key definition into account (rather than just flags returned by the
> storage engine). For example, some code checks key definition flags and
> assumes it to be a regular key if none if the previous checks for
> specific flags return true. If you allow CLUSTERING keys for storage
> engine that don’t support them, you still get the HA_CLUSTERING key set
> in key definition flags.

OK, I see.

> > Added a handlerton flag HTON_SUPPORTS_CLUSTERED_KEYS. This is
> > different from e.g. HA_CAN_RTREE etc, which are handler flags, but the
> > property of supporting clustered keys seems to me to be global and not
> > of table level for a SE.
> >
> > For error message I reused ER_ILLEGAL_HA_CREATE_OPTION ("Table storage
> > engine 'InnoDB' does not support the create option 'CLUSTERING'")
> >
>
> That looks good in general. Please also add code that enforces this
> restriction to open_binary_frm(). I.e. it should fail with an error if a
> non-InnoDB table happens to contain both HA_SPATIAL and HA_FULLTEXT
> flags for an index.

Done. Should this happen, it should return ER_NOT_FORM_FILE.

> >> - I see there’s no support for UNIQUE CLUSTERING KEYs. Let’s fix it if
> >> it’s an oversight, or document if it’s a known limitation?
> >
> > An oversight on my part, not sure about Tokutek. Syntax extended as
>
> Are you going to report it to Tokutek?

Yes.

> > follows. Where previously "UNIQUE" was accepted as a valid modifier,
> > "CLUSTERING" is accepted too, as well as "UNIQUE CLUSTERING" and
> > "CLUSTERING UNIQUE":
> > - CREATE UNIQUE INDEX;
> > - as a part of key definition:
> > - CREATE TABLE (..., [CONSTRAINT ... ] UNIQUE KEY ...,)
> > - ALTER TABLE ADD [CONSTRAINT ...] UNIQUE KEY
> >
> > The way the grammar was changed, it accepts "UNIQUE UNIQUE" and
> > "CLUSTERING CLUSTERING" too. IMHO benign.
> >
>
> Hm, doesn’t look that benign to me. UNIQUE UNIQUE is invalid SQL which a
> user may want to be aware of. It would be aware before the change. It
> will not be aware after the change.

OK, fixed, added tests too.

> > Also now it is possible to create such "constraints" as CONSTRAINT c1
> > CLUSTERING KEY, which is not really a constraint at all, but again
> > IMHO benign and I don't see an easy way to forbid it without blowing
> > up shift/reduce conflict count in the parser.
> >
>
> I don’t see a point in supporting CONSTRAINT c1 CLUSTERING KEY.

I don't see a point neither, but "constraint" is hard to distinguish
from "key" in the parser grammar, so it was a side effect of adding
clustering support for the keys. I have tried two fixes. One was
based on syntax changes only, but I couldn't avoid bumping
shift/reduce conflict count. Thus I settled for a semantic action
hack. There are some differences in error reporting between the two
("-" is the syntactical fix, "+" the pushed seman...

Read more...

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

Rebased on the current trunk. No changes.

Revision history for this message
Laurynas Biveinis (laurynas-biveinis) wrote : Posted in a previous version of this proposal

Allowing to OR Key::Keytype flags together (Keytype::CLUSTERING acting as a modifier for Keytype::UNIQUE) resulted in ambiguous flag values for clustering non-unique keys, which are not forbidden in TokuDB. In some places these became Keytype::MULTIPLE | Keytype::CLUSTERING, in others Keytype::CLUSTERING alone. I'm about to fix this by eliminating Keytype::CLUSTERING alone:
- add_field_to_list: add Key::MULTIPLE if needed
- mysql_prepare_create_table: forbid Key::CLUSTERING, handle Key::MULTIPLE | Key::CLUSTERING, replace all further == Key::MULTIPLE tests with & Key::MULTIPLE
- parser unique_combo_clustering symbol: add Key::MULTIPLE if needed
- setup_key_part_field: do not assume that if a field is a part of a clustering key, it cannot be a part of non-unique key.

review: Needs Fixing
Revision history for this message
Alexey Kopytov (akopytov) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/my_base.h'
2--- include/my_base.h 2014-02-17 11:12:40 +0000
3+++ include/my_base.h 2014-03-26 12:37:51 +0000
4@@ -258,11 +258,13 @@
5 #define HA_SPATIAL 1024 /* For spatial search */
6 #define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
7 #define HA_GENERATED_KEY 8192 /* Automaticly generated key */
8+#define HA_CLUSTERING (1<<31) /* TokuDB CLUSTERING key */
9
10 /* The combination of the above can be used for key type comparison. */
11 #define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \
12 HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
13- HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)
14+ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \
15+ HA_CLUSTERING)
16
17 /*
18 Key contains partial segments.
19
20=== modified file 'include/mysql_com.h'
21--- include/mysql_com.h 2013-08-14 03:57:21 +0000
22+++ include/mysql_com.h 2014-03-26 12:37:51 +0000
23@@ -126,6 +126,8 @@
24 #define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */
25 #define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT)
26 #define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */
27+#define CLUSTERING_FLAG (1 << 27) /* Field has a secondary clustering
28+ key */
29
30 #define REFRESH_GRANT 1 /* Refresh grant tables */
31 #define REFRESH_LOG 2 /* Start on new log file */
32
33=== added file 'mysql-test/r/tokudb_clustering_key_grammar.result'
34--- mysql-test/r/tokudb_clustering_key_grammar.result 1970-01-01 00:00:00 +0000
35+++ mysql-test/r/tokudb_clustering_key_grammar.result 2014-03-26 12:37:51 +0000
36@@ -0,0 +1,73 @@
37+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING KEY b (b)) ENGINE=InnoDB;
38+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
39+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
40+ALTER TABLE t1 ADD CLUSTERING INDEX b (b);
41+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
42+CREATE CLUSTERING INDEX b ON t1 (b) LOCK=EXCLUSIVE ALGORITHM=COPY;
43+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
44+ALTER TABLE t1 ADD CLUSTERING INDEX b (b), LOCK=EXCLUSIVE, ALGORITHM=COPY;
45+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
46+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
47+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
48+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
49+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE KEY b (b)) ENGINE=InnoDB' at line 1
50+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING CLUSTERING KEY b (b)) ENGINE=InnoDB;
51+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CLUSTERING KEY b (b)) ENGINE=InnoDB' at line 1
52+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
53+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
54+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
55+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
56+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
57+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
58+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
59+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE KEY b (b)) ENGINE=InnoDB' at line 1
60+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING KEY b (b)) ENGINE=InnoDB;
61+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') ENGINE=InnoDB' at line 1
62+ALTER TABLE t1 ADD UNIQUE CLUSTERING INDEX b (b);
63+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
64+ALTER TABLE t1 ADD CLUSTERING UNIQUE INDEX b (b);
65+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
66+ALTER TABLE t1 ADD UNIQUE UNIQUE INDEX b (b);
67+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE INDEX b (b)' at line 1
68+ALTER TABLE t1 ADD CLUSTERING CLUSTERING INDEX b (b);
69+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CLUSTERING INDEX b (b)' at line 1
70+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE CLUSTERING INDEX b (b);
71+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
72+ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING UNIQUE INDEX b (b);
73+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
74+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE UNIQUE INDEX b (b);
75+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UNIQUE INDEX b (b)' at line 1
76+ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING INDEX b (b);
77+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
78+DROP TABLE t1;
79+CREATE TABLE t1 (a INT CLUSTERING) ENGINE=InnoDB;
80+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
81+CREATE TABLE t1 (a INT CLUSTERING KEY) ENGINE=InnoDB;
82+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
83+CREATE TABLE t1 (a INT CLUSTERING UNIQUE) ENGINE=InnoDB;
84+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
85+CREATE TABLE t1 (a INT CLUSTERING UNIQUE KEY) ENGINE=InnoDB;
86+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
87+CREATE TABLE t1 (a INT UNIQUE CLUSTERING) ENGINE=InnoDB;
88+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
89+CREATE TABLE t1 (a INT UNIQUE CLUSTERING KEY) ENGINE=InnoDB;
90+ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
91+CREATE TABLE CLUSTERING(a INT) ENGINE=InnoDB;
92+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'CLUSTERING(a INT) ENGINE=InnoDB' at line 1
93+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, g INT, UNIQUE KEY b (b)) ENGINE=InnoDB;
94+ALTER TABLE t1 ADD UNIQUE INDEX c (c), LOCK=EXCLUSIVE, ALGORITHM=COPY;
95+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE INDEX g (g);
96+ALTER TABLE t1 ADD INDEX d (d);
97+CREATE INDEX e ON t1 (e) LOCK=EXCLUSIVE ALGORITHM=COPY;
98+CREATE UNIQUE INDEX f ON t1 (f);
99+DROP TABLE t1;
100+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY b (b)) ENGINE=InnoDB;
101+DROP TABLE t1;
102+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE b (b)) ENGINE=InnoDB;
103+DROP TABLE t1;
104+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE b (b)) ENGINE=InnoDB;
105+DROP TABLE t1;
106+CREATE TABLE t1 (a INT UNIQUE) ENGINE=InnoDB;
107+DROP TABLE t1;
108+CREATE TABLE t1 (a INT UNIQUE KEY) ENGINE=InnoDB;
109+DROP TABLE t1;
110
111=== added file 'mysql-test/t/tokudb_clustering_key_grammar.test'
112--- mysql-test/t/tokudb_clustering_key_grammar.test 1970-01-01 00:00:00 +0000
113+++ mysql-test/t/tokudb_clustering_key_grammar.test 2014-03-26 12:37:51 +0000
114@@ -0,0 +1,99 @@
115+#
116+# Test that TokuDB CLUSTERING key grammar addition syntax is understood (does not fail with
117+# ER_PARSE_ERROR), but that non-supporting storage engines reject it by returning
118+# ER_ILLEGAL_HA_CREATE_OPTION.
119+#
120+--source include/have_innodb.inc
121+
122+--error ER_ILLEGAL_HA_CREATE_OPTION
123+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING KEY b (b)) ENGINE=InnoDB;
124+
125+CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
126+
127+--error ER_ILLEGAL_HA_CREATE_OPTION
128+ALTER TABLE t1 ADD CLUSTERING INDEX b (b);
129+
130+--error ER_ILLEGAL_HA_CREATE_OPTION
131+CREATE CLUSTERING INDEX b ON t1 (b) LOCK=EXCLUSIVE ALGORITHM=COPY;
132+
133+--error ER_ILLEGAL_HA_CREATE_OPTION
134+ALTER TABLE t1 ADD CLUSTERING INDEX b (b), LOCK=EXCLUSIVE, ALGORITHM=COPY;
135+
136+# CLUSTERING can be combined with UNIQUE, but neither of them can be combined with itself.
137+# CLUSTERING cannot be the sole key type for a CONSTRAINT.
138+
139+--error ER_ILLEGAL_HA_CREATE_OPTION
140+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
141+--error ER_PARSE_ERROR
142+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
143+--error ER_PARSE_ERROR
144+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING CLUSTERING KEY b (b)) ENGINE=InnoDB;
145+--error ER_ILLEGAL_HA_CREATE_OPTION
146+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
147+--error ER_ILLEGAL_HA_CREATE_OPTION
148+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
149+--error ER_ILLEGAL_HA_CREATE_OPTION
150+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
151+--error ER_PARSE_ERROR
152+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
153+--error ER_PARSE_ERROR
154+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING KEY b (b)) ENGINE=InnoDB;
155+--error ER_ILLEGAL_HA_CREATE_OPTION
156+ALTER TABLE t1 ADD UNIQUE CLUSTERING INDEX b (b);
157+--error ER_ILLEGAL_HA_CREATE_OPTION
158+ALTER TABLE t1 ADD CLUSTERING UNIQUE INDEX b (b);
159+--error ER_PARSE_ERROR
160+ALTER TABLE t1 ADD UNIQUE UNIQUE INDEX b (b);
161+--error ER_PARSE_ERROR
162+ALTER TABLE t1 ADD CLUSTERING CLUSTERING INDEX b (b);
163+--error ER_ILLEGAL_HA_CREATE_OPTION
164+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE CLUSTERING INDEX b (b);
165+--error ER_ILLEGAL_HA_CREATE_OPTION
166+ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING UNIQUE INDEX b (b);
167+--error ER_PARSE_ERROR
168+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE UNIQUE INDEX b (b);
169+--error ER_PARSE_ERROR
170+ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING INDEX b (b);
171+
172+DROP TABLE t1;
173+
174+# Test CLUSTERING as a field attribute, alone and in combination with UNIQUE
175+
176+--error ER_ILLEGAL_HA_CREATE_OPTION
177+CREATE TABLE t1 (a INT CLUSTERING) ENGINE=InnoDB;
178+--error ER_ILLEGAL_HA_CREATE_OPTION
179+CREATE TABLE t1 (a INT CLUSTERING KEY) ENGINE=InnoDB;
180+--error ER_ILLEGAL_HA_CREATE_OPTION
181+CREATE TABLE t1 (a INT CLUSTERING UNIQUE) ENGINE=InnoDB;
182+--error ER_ILLEGAL_HA_CREATE_OPTION
183+CREATE TABLE t1 (a INT CLUSTERING UNIQUE KEY) ENGINE=InnoDB;
184+--error ER_ILLEGAL_HA_CREATE_OPTION
185+CREATE TABLE t1 (a INT UNIQUE CLUSTERING) ENGINE=InnoDB;
186+--error ER_ILLEGAL_HA_CREATE_OPTION
187+CREATE TABLE t1 (a INT UNIQUE CLUSTERING KEY) ENGINE=InnoDB;
188+
189+# CLUSTERING is not allowed as an identifier due to causing extra shift/reduce parser conflicts
190+--error ER_PARSE_ERROR
191+CREATE TABLE CLUSTERING(a INT) ENGINE=InnoDB;
192+
193+
194+# Check that the grammar changes have not broken related CLUSTERING-less clauses
195+
196+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, g INT, UNIQUE KEY b (b)) ENGINE=InnoDB;
197+ALTER TABLE t1 ADD UNIQUE INDEX c (c), LOCK=EXCLUSIVE, ALGORITHM=COPY;
198+ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE INDEX g (g);
199+ALTER TABLE t1 ADD INDEX d (d);
200+CREATE INDEX e ON t1 (e) LOCK=EXCLUSIVE ALGORITHM=COPY;
201+CREATE UNIQUE INDEX f ON t1 (f);
202+DROP TABLE t1;
203+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY b (b)) ENGINE=InnoDB;
204+DROP TABLE t1;
205+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE b (b)) ENGINE=InnoDB;
206+DROP TABLE t1;
207+CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE b (b)) ENGINE=InnoDB;
208+DROP TABLE t1;
209+
210+CREATE TABLE t1 (a INT UNIQUE) ENGINE=InnoDB;
211+DROP TABLE t1;
212+CREATE TABLE t1 (a INT UNIQUE KEY) ENGINE=InnoDB;
213+DROP TABLE t1;
214
215=== modified file 'sql/handler.h'
216--- sql/handler.h 2014-02-27 12:29:47 +0000
217+++ sql/handler.h 2014-03-26 12:37:51 +0000
218@@ -1031,6 +1031,11 @@
219 */
220 #define HTON_SUPPORTS_ONLINE_BACKUPS (1 << 11)
221
222+/**
223+ Engine supports secondary clustered keys.
224+*/
225+#define HTON_SUPPORTS_CLUSTERED_KEYS (1 << 12)
226+
227 enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
228 ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
229
230
231=== modified file 'sql/lex.h'
232--- sql/lex.h 2013-12-16 12:54:12 +0000
233+++ sql/lex.h 2014-03-26 12:37:51 +0000
234@@ -115,6 +115,7 @@
235 { "CLIENT", SYM(CLIENT_SYM)},
236 { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)},
237 { "CLOSE", SYM(CLOSE_SYM)},
238+ { "CLUSTERING", SYM(CLUSTERING_SYM)},
239 { "COALESCE", SYM(COALESCE)},
240 { "CODE", SYM(CODE_SYM)},
241 { "COLLATE", SYM(COLLATE_SYM)},
242
243=== modified file 'sql/sql_class.h'
244--- sql/sql_class.h 2014-03-03 17:51:33 +0000
245+++ sql/sql_class.h 2014-03-26 12:37:51 +0000
246@@ -294,7 +294,8 @@
247
248 class Key :public Sql_alloc {
249 public:
250- enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
251+ enum Keytype { PRIMARY= 0, UNIQUE= 1, MULTIPLE= 2, FULLTEXT= 4, SPATIAL= 8,
252+ FOREIGN_KEY= 16, CLUSTERING= 32 };
253 enum Keytype type;
254 KEY_CREATE_INFO key_create_info;
255 List<Key_part_spec> columns;
256
257=== modified file 'sql/sql_parse.cc'
258--- sql/sql_parse.cc 2014-03-17 07:06:47 +0000
259+++ sql/sql_parse.cc 2014-03-26 12:37:51 +0000
260@@ -6921,13 +6921,20 @@
261 lex->alter_info.key_list.push_back(key);
262 lex->col_list.empty();
263 }
264- if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
265+ if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG | CLUSTERING_FLAG))
266 {
267- Key *key;
268+ Key::Keytype keytype;
269+ if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
270+ keytype= Key::UNIQUE;
271+ else
272+ keytype= Key::MULTIPLE;
273+ if (type_modifier & CLUSTERING_FLAG)
274+ keytype= (enum Key::Keytype)(keytype | Key::CLUSTERING);
275+ DBUG_ASSERT(keytype != Key::MULTIPLE);
276+
277 lex->col_list.push_back(new Key_part_spec(*field_name, 0));
278- key= new Key(Key::UNIQUE, null_lex_str,
279- &default_key_create_info, 0,
280- lex->col_list);
281+ Key *key= new Key(keytype, null_lex_str, &default_key_create_info, 0,
282+ lex->col_list);
283 lex->alter_info.key_list.push_back(key);
284 lex->col_list.empty();
285 }
286
287=== modified file 'sql/sql_show.cc'
288--- sql/sql_show.cc 2014-03-03 17:51:33 +0000
289+++ sql/sql_show.cc 2014-03-26 12:37:51 +0000
290@@ -1525,6 +1525,8 @@
291 packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
292 else if (key_info->flags & HA_SPATIAL)
293 packet->append(STRING_WITH_LEN("SPATIAL KEY "));
294+ else if (key_info->flags & HA_CLUSTERING)
295+ packet->append(STRING_WITH_LEN("CLUSTERING KEY "));
296 else
297 packet->append(STRING_WITH_LEN("KEY "));
298
299@@ -5227,6 +5229,7 @@
300 store_column_type(table, field, cs, IS_COLUMNS_DATA_TYPE);
301 pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
302 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
303+ (field->flags & CLUSTERING_FLAG) ? "CLU" :
304 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
305 table->field[IS_COLUMNS_COLUMN_KEY]->store((const char*) pos,
306 strlen((const char*) pos), cs);
307
308=== modified file 'sql/sql_table.cc'
309--- sql/sql_table.cc 2014-02-17 11:12:40 +0000
310+++ sql/sql_table.cc 2014-03-26 12:37:51 +0000
311@@ -3757,7 +3757,7 @@
312 break;
313 }
314
315- switch (key->type) {
316+ switch ((unsigned)key->type) {
317 case Key::MULTIPLE:
318 key_info->flags= 0;
319 break;
320@@ -3780,6 +3780,23 @@
321 case Key::FOREIGN_KEY:
322 key_number--; // Skip this key
323 continue;
324+ case Key::CLUSTERING | Key::UNIQUE:
325+ case Key::CLUSTERING | Key::MULTIPLE:
326+ if (unlikely(!ha_check_storage_engine_flag(
327+ file->ht, HTON_SUPPORTS_CLUSTERED_KEYS)))
328+ {
329+ my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
330+ ha_resolve_storage_engine_name(file->ht), "CLUSTERING");
331+ DBUG_RETURN(TRUE);
332+ }
333+ if (key->type & Key::UNIQUE)
334+ key_info->flags= HA_NOSAME;
335+ else
336+ key_info->flags= 0;
337+ key_info->flags|= HA_CLUSTERING;
338+ break;
339+ case Key::CLUSTERING:
340+ DBUG_ASSERT(0);
341 default:
342 key_info->flags = HA_NOSAME;
343 break;
344@@ -4021,7 +4038,7 @@
345 key_part_length= min(max_key_length, file->max_key_part_length());
346 if (max_field_size)
347 key_part_length= min(key_part_length, max_field_size);
348- if (key->type == Key::MULTIPLE)
349+ if (key->type & Key::MULTIPLE)
350 {
351 /* not a critical problem */
352 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
353@@ -4073,7 +4090,7 @@
354 key->type != Key::FULLTEXT)
355 {
356 key_part_length= file->max_key_part_length();
357- if (key->type == Key::MULTIPLE)
358+ if (key->type & Key::MULTIPLE)
359 {
360 /* not a critical problem */
361 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
362@@ -7235,7 +7252,9 @@
363 key_type= Key::FULLTEXT;
364 else
365 key_type= Key::MULTIPLE;
366-
367+ if (key_info->flags & HA_CLUSTERING)
368+ key_type= (enum Key::Keytype)(key_type | Key::CLUSTERING);
369+
370 if (index_column_dropped)
371 {
372 /*
373@@ -7251,7 +7270,7 @@
374 key_parts);
375 new_key_list.push_back(key);
376
377- if (skip_secondary && key_type == Key::MULTIPLE) {
378+ if (skip_secondary && key_type & Key::MULTIPLE) {
379 delayed_key_list.push_back(key);
380 }
381 }
382@@ -7264,7 +7283,7 @@
383
384 if (key->type != Key::FOREIGN_KEY)
385 {
386- if (skip_secondary && key->type == Key::MULTIPLE) {
387+ if (skip_secondary && key->type & Key::MULTIPLE) {
388 delayed_key_list.push_back(key);
389 }
390 }
391
392=== modified file 'sql/sql_yacc.yy'
393--- sql/sql_yacc.yy 2014-02-25 07:30:22 +0000
394+++ sql/sql_yacc.yy 2014-03-26 12:37:51 +0000
395@@ -1029,7 +1029,7 @@
396 Currently there are 161 shift/reduce conflicts.
397 We should not introduce new conflicts any more.
398 */
399-%expect 162
400+%expect 164
401
402 /*
403 Comments for TOKENS.
404@@ -1114,6 +1114,7 @@
405 %token CLIENT_SYM
406 %token CLIENT_STATS_SYM
407 %token CLOSE_SYM /* SQL-2003-R */
408+%token CLUSTERING_SYM
409 %token COALESCE /* SQL-2003-N */
410 %token CODE_SYM
411 %token COLLATE_SYM /* SQL-2003-R */
412@@ -1794,7 +1795,8 @@
413 option_type opt_var_type opt_var_ident_type
414
415 %type <key_type>
416- normal_key_type opt_unique constraint_key_type fulltext spatial
417+ normal_key_type opt_unique_combo_clustering constraint_key_type
418+ fulltext spatial unique_opt_clustering unique_combo_clustering unique clustering
419
420 %type <key_alg>
421 btree_or_rtree
422@@ -2445,7 +2447,7 @@
423 }
424 create_table_set_open_action_and_adjust_tables(lex);
425 }
426- | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident
427+ | CREATE opt_unique_combo_clustering INDEX_SYM ident key_alg ON table_ident
428 {
429 if (add_create_index_prepare(Lex, $7))
430 MYSQL_YYABORT;
431@@ -6348,6 +6350,13 @@
432 | opt_constraint constraint_key_type opt_ident key_alg
433 '(' key_list ')' normal_key_options
434 {
435+ if (($1.length != 0)
436+ && ((enum Key::Keytype)$2 == (Key::CLUSTERING | Key::MULTIPLE)))
437+ {
438+ /* Forbid "CONSTRAINT c CLUSTERING" */
439+ my_parse_error(ER(ER_SYNTAX_ERROR));
440+ MYSQL_YYABORT;
441+ }
442 if (add_create_index (Lex, $2, $3.str ? $3 : $1))
443 MYSQL_YYABORT;
444 }
445@@ -6747,16 +6756,22 @@
446 lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
447 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
448 }
449- | UNIQUE_SYM
450+ | unique_combo_clustering
451 {
452 LEX *lex=Lex;
453- lex->type|= UNIQUE_FLAG;
454+ if ($1 & Key::UNIQUE)
455+ lex->type|= UNIQUE_FLAG;
456+ if ($1 & Key::CLUSTERING)
457+ lex->type|= CLUSTERING_FLAG;
458 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
459 }
460- | UNIQUE_SYM KEY_SYM
461+ | unique_combo_clustering KEY_SYM
462 {
463 LEX *lex=Lex;
464- lex->type|= UNIQUE_KEY_FLAG;
465+ if ($1 & Key::UNIQUE)
466+ lex->type|= UNIQUE_KEY_FLAG;
467+ if ($1 & Key::CLUSTERING)
468+ lex->type|= CLUSTERING_FLAG;
469 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
470 }
471 | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
472@@ -7139,7 +7154,8 @@
473
474 constraint_key_type:
475 PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
476- | UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; }
477+ | unique_combo_clustering opt_key_or_index { $$= $1; }
478+
479 ;
480
481 key_or_index:
482@@ -7158,9 +7174,43 @@
483 | INDEXES {}
484 ;
485
486-opt_unique:
487- /* empty */ { $$= Key::MULTIPLE; }
488- | UNIQUE_SYM { $$= Key::UNIQUE; }
489+opt_unique_combo_clustering:
490+ /* empty */ { $$= Key::MULTIPLE; }
491+ | unique_combo_clustering
492+ ;
493+
494+unique_combo_clustering:
495+ clustering
496+ {
497+ $$= (enum Key::Keytype)($1 | Key::MULTIPLE);
498+ }
499+ | unique_opt_clustering
500+ {
501+ $$= $1;
502+ }
503+ ;
504+
505+unique_opt_clustering:
506+ unique
507+ {
508+ $$= $1;
509+ }
510+ | unique clustering
511+ {
512+ $$= (enum Key::Keytype)($1 | $2);
513+ }
514+ | clustering unique
515+ {
516+ $$= (enum Key::Keytype)($1 | $2);
517+ }
518+ ;
519+
520+unique:
521+ UNIQUE_SYM { $$= Key::UNIQUE; }
522+ ;
523+
524+clustering:
525+ CLUSTERING_SYM { $$= Key::CLUSTERING; }
526 ;
527
528 fulltext:
529
530=== modified file 'sql/table.cc'
531--- sql/table.cc 2014-03-17 10:59:40 +0000
532+++ sql/table.cc 2014-03-26 12:37:51 +0000
533@@ -854,11 +854,19 @@
534 KEY_PART_INFO *key_part= &keyinfo->key_part[key_part_n];
535 Field *field= key_part->field;
536
537- /* Flag field as unique if it is the only keypart in a unique index */
538+ /* Flag field as unique and/or clustering if it is the only keypart in a
539+ unique/clustering index */
540 if (key_part_n == 0 && key_n != primary_key_n)
541+ {
542 field->flags |= (((keyinfo->flags & HA_NOSAME) &&
543 (keyinfo->user_defined_key_parts == 1)) ?
544 UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
545+
546+ if (((keyinfo->flags & HA_CLUSTERING) &&
547+ (keyinfo->user_defined_key_parts == 1)))
548+ field->flags|= CLUSTERING_FLAG;
549+ }
550+
551 if (key_part_n == 0)
552 field->key_start.set_bit(key_n);
553 if (field->key_length() == key_part->length &&
554@@ -1133,6 +1141,18 @@
555 if (new_frm_ver >= 3)
556 {
557 keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
558+ /* Replace HA_FULLTEXT & HA_SPATIAL with HA_CLUSTERING. This way we
559+ support TokuDB clustering key definitions without changing the FRM
560+ format. */
561+ if (keyinfo->flags & HA_SPATIAL && keyinfo->flags & HA_FULLTEXT)
562+ {
563+ if (!ha_check_storage_engine_flag(share->db_type(),
564+ HTON_SUPPORTS_CLUSTERED_KEYS))
565+ goto err;
566+ keyinfo->flags|= HA_CLUSTERING;
567+ keyinfo->flags&= ~HA_SPATIAL;
568+ keyinfo->flags&= ~HA_FULLTEXT;
569+ }
570 keyinfo->key_length= (uint) uint2korr(strpos+2);
571 keyinfo->user_defined_key_parts= (uint) strpos[4];
572 keyinfo->algorithm= (enum ha_key_alg) strpos[5];
573
574=== modified file 'sql/unireg.cc'
575--- sql/unireg.cc 2014-02-17 11:12:40 +0000
576+++ sql/unireg.cc 2014-03-26 12:37:51 +0000
577@@ -628,7 +628,15 @@
578 key_parts=0;
579 for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
580 {
581- int2store(pos, (key->flags ^ HA_NOSAME));
582+ /* Replace HA_CLUSTERING with HA_SPATIAL | HA_FULLTEXT to allow storing
583+ TokuDB keys without changing the FRM format. */
584+ uint16 key_flags= (uint16)key->flags;
585+ if (key->flags & HA_CLUSTERING)
586+ {
587+ key_flags|= HA_SPATIAL;
588+ key_flags|= HA_FULLTEXT;
589+ }
590+ int2store(pos, (key_flags ^ HA_NOSAME));
591 int2store(pos+2,key->key_length);
592 pos[4]= (uchar) key->user_defined_key_parts;
593 pos[5]= (uchar) key->algorithm;
594
595=== modified file 'tests/mysql_client_test.c'
596--- tests/mysql_client_test.c 2013-08-14 03:57:21 +0000
597+++ tests/mysql_client_test.c 2014-03-26 12:37:51 +0000
598@@ -4676,7 +4676,8 @@
599 fprintf(stdout, "\n MULTIPLE_KEY_FLAG");
600 if (field->flags & AUTO_INCREMENT_FLAG)
601 fprintf(stdout, "\n AUTO_INCREMENT_FLAG");
602-
603+ if (field->flags & CLUSTERING_FLAG)
604+ fprintf(stdout, "\n CLUSTERING_FLAG");
605 }
606 }
607 mysql_free_result(result);

Subscribers

People subscribed via source and target branches