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: no longer in the source branch.
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
=== modified file 'include/my_base.h'
--- include/my_base.h 2014-02-17 11:12:40 +0000
+++ include/my_base.h 2014-03-26 12:37:51 +0000
@@ -258,11 +258,13 @@
258#define HA_SPATIAL 1024 /* For spatial search */258#define HA_SPATIAL 1024 /* For spatial search */
259#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */259#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
260#define HA_GENERATED_KEY 8192 /* Automaticly generated key */260#define HA_GENERATED_KEY 8192 /* Automaticly generated key */
261#define HA_CLUSTERING (1<<31) /* TokuDB CLUSTERING key */
261262
262 /* The combination of the above can be used for key type comparison. */263 /* The combination of the above can be used for key type comparison. */
263#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \264#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \
264 HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \265 HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
265 HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)266 HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \
267 HA_CLUSTERING)
266268
267/*269/*
268 Key contains partial segments.270 Key contains partial segments.
269271
=== modified file 'include/mysql_com.h'
--- include/mysql_com.h 2013-08-14 03:57:21 +0000
+++ include/mysql_com.h 2014-03-26 12:37:51 +0000
@@ -126,6 +126,8 @@
126#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */126#define FIELD_FLAGS_COLUMN_FORMAT 24 /* Field column format, bit 24-25 */
127#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT)127#define FIELD_FLAGS_COLUMN_FORMAT_MASK (3 << FIELD_FLAGS_COLUMN_FORMAT)
128#define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */128#define FIELD_IS_DROPPED (1<< 26) /* Intern: Field is being dropped */
129#define CLUSTERING_FLAG (1 << 27) /* Field has a secondary clustering
130 key */
129131
130#define REFRESH_GRANT 1 /* Refresh grant tables */132#define REFRESH_GRANT 1 /* Refresh grant tables */
131#define REFRESH_LOG 2 /* Start on new log file */133#define REFRESH_LOG 2 /* Start on new log file */
132134
=== added file 'mysql-test/r/tokudb_clustering_key_grammar.result'
--- mysql-test/r/tokudb_clustering_key_grammar.result 1970-01-01 00:00:00 +0000
+++ mysql-test/r/tokudb_clustering_key_grammar.result 2014-03-26 12:37:51 +0000
@@ -0,0 +1,73 @@
1CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING KEY b (b)) ENGINE=InnoDB;
2ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
3CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
4ALTER TABLE t1 ADD CLUSTERING INDEX b (b);
5ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
6CREATE CLUSTERING INDEX b ON t1 (b) LOCK=EXCLUSIVE ALGORITHM=COPY;
7ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
8ALTER TABLE t1 ADD CLUSTERING INDEX b (b), LOCK=EXCLUSIVE, ALGORITHM=COPY;
9ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
10CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
11ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
12CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
13ERROR 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
14CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING CLUSTERING KEY b (b)) ENGINE=InnoDB;
15ERROR 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
16CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
17ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
18CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
19ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
20CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
21ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
22CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
23ERROR 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
24CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING KEY b (b)) ENGINE=InnoDB;
25ERROR 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
26ALTER TABLE t1 ADD UNIQUE CLUSTERING INDEX b (b);
27ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
28ALTER TABLE t1 ADD CLUSTERING UNIQUE INDEX b (b);
29ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
30ALTER TABLE t1 ADD UNIQUE UNIQUE INDEX b (b);
31ERROR 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
32ALTER TABLE t1 ADD CLUSTERING CLUSTERING INDEX b (b);
33ERROR 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
34ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE CLUSTERING INDEX b (b);
35ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
36ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING UNIQUE INDEX b (b);
37ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
38ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE UNIQUE INDEX b (b);
39ERROR 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
40ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING INDEX b (b);
41ERROR 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
42DROP TABLE t1;
43CREATE TABLE t1 (a INT CLUSTERING) ENGINE=InnoDB;
44ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
45CREATE TABLE t1 (a INT CLUSTERING KEY) ENGINE=InnoDB;
46ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
47CREATE TABLE t1 (a INT CLUSTERING UNIQUE) ENGINE=InnoDB;
48ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
49CREATE TABLE t1 (a INT CLUSTERING UNIQUE KEY) ENGINE=InnoDB;
50ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
51CREATE TABLE t1 (a INT UNIQUE CLUSTERING) ENGINE=InnoDB;
52ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
53CREATE TABLE t1 (a INT UNIQUE CLUSTERING KEY) ENGINE=InnoDB;
54ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'CLUSTERING'
55CREATE TABLE CLUSTERING(a INT) ENGINE=InnoDB;
56ERROR 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
57CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, g INT, UNIQUE KEY b (b)) ENGINE=InnoDB;
58ALTER TABLE t1 ADD UNIQUE INDEX c (c), LOCK=EXCLUSIVE, ALGORITHM=COPY;
59ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE INDEX g (g);
60ALTER TABLE t1 ADD INDEX d (d);
61CREATE INDEX e ON t1 (e) LOCK=EXCLUSIVE ALGORITHM=COPY;
62CREATE UNIQUE INDEX f ON t1 (f);
63DROP TABLE t1;
64CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY b (b)) ENGINE=InnoDB;
65DROP TABLE t1;
66CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE b (b)) ENGINE=InnoDB;
67DROP TABLE t1;
68CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE b (b)) ENGINE=InnoDB;
69DROP TABLE t1;
70CREATE TABLE t1 (a INT UNIQUE) ENGINE=InnoDB;
71DROP TABLE t1;
72CREATE TABLE t1 (a INT UNIQUE KEY) ENGINE=InnoDB;
73DROP TABLE t1;
074
=== added file 'mysql-test/t/tokudb_clustering_key_grammar.test'
--- mysql-test/t/tokudb_clustering_key_grammar.test 1970-01-01 00:00:00 +0000
+++ mysql-test/t/tokudb_clustering_key_grammar.test 2014-03-26 12:37:51 +0000
@@ -0,0 +1,99 @@
1#
2# Test that TokuDB CLUSTERING key grammar addition syntax is understood (does not fail with
3# ER_PARSE_ERROR), but that non-supporting storage engines reject it by returning
4# ER_ILLEGAL_HA_CREATE_OPTION.
5#
6--source include/have_innodb.inc
7
8--error ER_ILLEGAL_HA_CREATE_OPTION
9CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING KEY b (b)) ENGINE=InnoDB;
10
11CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
12
13--error ER_ILLEGAL_HA_CREATE_OPTION
14ALTER TABLE t1 ADD CLUSTERING INDEX b (b);
15
16--error ER_ILLEGAL_HA_CREATE_OPTION
17CREATE CLUSTERING INDEX b ON t1 (b) LOCK=EXCLUSIVE ALGORITHM=COPY;
18
19--error ER_ILLEGAL_HA_CREATE_OPTION
20ALTER TABLE t1 ADD CLUSTERING INDEX b (b), LOCK=EXCLUSIVE, ALGORITHM=COPY;
21
22# CLUSTERING can be combined with UNIQUE, but neither of them can be combined with itself.
23# CLUSTERING cannot be the sole key type for a CONSTRAINT.
24
25--error ER_ILLEGAL_HA_CREATE_OPTION
26CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
27--error ER_PARSE_ERROR
28CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
29--error ER_PARSE_ERROR
30CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING CLUSTERING KEY b (b)) ENGINE=InnoDB;
31--error ER_ILLEGAL_HA_CREATE_OPTION
32CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
33--error ER_ILLEGAL_HA_CREATE_OPTION
34CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE CLUSTERING KEY b (b)) ENGINE=InnoDB;
35--error ER_ILLEGAL_HA_CREATE_OPTION
36CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING UNIQUE KEY b (b)) ENGINE=InnoDB;
37--error ER_PARSE_ERROR
38CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE UNIQUE KEY b (b)) ENGINE=InnoDB;
39--error ER_PARSE_ERROR
40CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 CLUSTERING KEY b (b)) ENGINE=InnoDB;
41--error ER_ILLEGAL_HA_CREATE_OPTION
42ALTER TABLE t1 ADD UNIQUE CLUSTERING INDEX b (b);
43--error ER_ILLEGAL_HA_CREATE_OPTION
44ALTER TABLE t1 ADD CLUSTERING UNIQUE INDEX b (b);
45--error ER_PARSE_ERROR
46ALTER TABLE t1 ADD UNIQUE UNIQUE INDEX b (b);
47--error ER_PARSE_ERROR
48ALTER TABLE t1 ADD CLUSTERING CLUSTERING INDEX b (b);
49--error ER_ILLEGAL_HA_CREATE_OPTION
50ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE CLUSTERING INDEX b (b);
51--error ER_ILLEGAL_HA_CREATE_OPTION
52ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING UNIQUE INDEX b (b);
53--error ER_PARSE_ERROR
54ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE UNIQUE INDEX b (b);
55--error ER_PARSE_ERROR
56ALTER TABLE t1 ADD CONSTRAINT c1 CLUSTERING INDEX b (b);
57
58DROP TABLE t1;
59
60# Test CLUSTERING as a field attribute, alone and in combination with UNIQUE
61
62--error ER_ILLEGAL_HA_CREATE_OPTION
63CREATE TABLE t1 (a INT CLUSTERING) ENGINE=InnoDB;
64--error ER_ILLEGAL_HA_CREATE_OPTION
65CREATE TABLE t1 (a INT CLUSTERING KEY) ENGINE=InnoDB;
66--error ER_ILLEGAL_HA_CREATE_OPTION
67CREATE TABLE t1 (a INT CLUSTERING UNIQUE) ENGINE=InnoDB;
68--error ER_ILLEGAL_HA_CREATE_OPTION
69CREATE TABLE t1 (a INT CLUSTERING UNIQUE KEY) ENGINE=InnoDB;
70--error ER_ILLEGAL_HA_CREATE_OPTION
71CREATE TABLE t1 (a INT UNIQUE CLUSTERING) ENGINE=InnoDB;
72--error ER_ILLEGAL_HA_CREATE_OPTION
73CREATE TABLE t1 (a INT UNIQUE CLUSTERING KEY) ENGINE=InnoDB;
74
75# CLUSTERING is not allowed as an identifier due to causing extra shift/reduce parser conflicts
76--error ER_PARSE_ERROR
77CREATE TABLE CLUSTERING(a INT) ENGINE=InnoDB;
78
79
80# Check that the grammar changes have not broken related CLUSTERING-less clauses
81
82CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT, g INT, UNIQUE KEY b (b)) ENGINE=InnoDB;
83ALTER TABLE t1 ADD UNIQUE INDEX c (c), LOCK=EXCLUSIVE, ALGORITHM=COPY;
84ALTER TABLE t1 ADD CONSTRAINT c1 UNIQUE INDEX g (g);
85ALTER TABLE t1 ADD INDEX d (d);
86CREATE INDEX e ON t1 (e) LOCK=EXCLUSIVE ALGORITHM=COPY;
87CREATE UNIQUE INDEX f ON t1 (f);
88DROP TABLE t1;
89CREATE TABLE t1 (a INT PRIMARY KEY, b INT, KEY b (b)) ENGINE=InnoDB;
90DROP TABLE t1;
91CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE b (b)) ENGINE=InnoDB;
92DROP TABLE t1;
93CREATE TABLE t1 (a INT PRIMARY KEY, b INT, CONSTRAINT c1 UNIQUE b (b)) ENGINE=InnoDB;
94DROP TABLE t1;
95
96CREATE TABLE t1 (a INT UNIQUE) ENGINE=InnoDB;
97DROP TABLE t1;
98CREATE TABLE t1 (a INT UNIQUE KEY) ENGINE=InnoDB;
99DROP TABLE t1;
0100
=== modified file 'sql/handler.h'
--- sql/handler.h 2014-02-27 12:29:47 +0000
+++ sql/handler.h 2014-03-26 12:37:51 +0000
@@ -1031,6 +1031,11 @@
1031*/1031*/
1032#define HTON_SUPPORTS_ONLINE_BACKUPS (1 << 11)1032#define HTON_SUPPORTS_ONLINE_BACKUPS (1 << 11)
10331033
1034/**
1035 Engine supports secondary clustered keys.
1036*/
1037#define HTON_SUPPORTS_CLUSTERED_KEYS (1 << 12)
1038
1034enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,1039enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
1035 ISO_REPEATABLE_READ, ISO_SERIALIZABLE};1040 ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
10361041
10371042
=== modified file 'sql/lex.h'
--- sql/lex.h 2013-12-16 12:54:12 +0000
+++ sql/lex.h 2014-03-26 12:37:51 +0000
@@ -115,6 +115,7 @@
115 { "CLIENT", SYM(CLIENT_SYM)},115 { "CLIENT", SYM(CLIENT_SYM)},
116 { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)},116 { "CLIENT_STATISTICS", SYM(CLIENT_STATS_SYM)},
117 { "CLOSE", SYM(CLOSE_SYM)},117 { "CLOSE", SYM(CLOSE_SYM)},
118 { "CLUSTERING", SYM(CLUSTERING_SYM)},
118 { "COALESCE", SYM(COALESCE)},119 { "COALESCE", SYM(COALESCE)},
119 { "CODE", SYM(CODE_SYM)},120 { "CODE", SYM(CODE_SYM)},
120 { "COLLATE", SYM(COLLATE_SYM)},121 { "COLLATE", SYM(COLLATE_SYM)},
121122
=== modified file 'sql/sql_class.h'
--- sql/sql_class.h 2014-03-03 17:51:33 +0000
+++ sql/sql_class.h 2014-03-26 12:37:51 +0000
@@ -294,7 +294,8 @@
294294
295class Key :public Sql_alloc {295class Key :public Sql_alloc {
296public:296public:
297 enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};297 enum Keytype { PRIMARY= 0, UNIQUE= 1, MULTIPLE= 2, FULLTEXT= 4, SPATIAL= 8,
298 FOREIGN_KEY= 16, CLUSTERING= 32 };
298 enum Keytype type;299 enum Keytype type;
299 KEY_CREATE_INFO key_create_info;300 KEY_CREATE_INFO key_create_info;
300 List<Key_part_spec> columns;301 List<Key_part_spec> columns;
301302
=== modified file 'sql/sql_parse.cc'
--- sql/sql_parse.cc 2014-03-17 07:06:47 +0000
+++ sql/sql_parse.cc 2014-03-26 12:37:51 +0000
@@ -6921,13 +6921,20 @@
6921 lex->alter_info.key_list.push_back(key);6921 lex->alter_info.key_list.push_back(key);
6922 lex->col_list.empty();6922 lex->col_list.empty();
6923 }6923 }
6924 if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))6924 if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG | CLUSTERING_FLAG))
6925 {6925 {
6926 Key *key;6926 Key::Keytype keytype;
6927 if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
6928 keytype= Key::UNIQUE;
6929 else
6930 keytype= Key::MULTIPLE;
6931 if (type_modifier & CLUSTERING_FLAG)
6932 keytype= (enum Key::Keytype)(keytype | Key::CLUSTERING);
6933 DBUG_ASSERT(keytype != Key::MULTIPLE);
6934
6927 lex->col_list.push_back(new Key_part_spec(*field_name, 0));6935 lex->col_list.push_back(new Key_part_spec(*field_name, 0));
6928 key= new Key(Key::UNIQUE, null_lex_str,6936 Key *key= new Key(keytype, null_lex_str, &default_key_create_info, 0,
6929 &default_key_create_info, 0,6937 lex->col_list);
6930 lex->col_list);
6931 lex->alter_info.key_list.push_back(key);6938 lex->alter_info.key_list.push_back(key);
6932 lex->col_list.empty();6939 lex->col_list.empty();
6933 }6940 }
69346941
=== modified file 'sql/sql_show.cc'
--- sql/sql_show.cc 2014-03-03 17:51:33 +0000
+++ sql/sql_show.cc 2014-03-26 12:37:51 +0000
@@ -1525,6 +1525,8 @@
1525 packet->append(STRING_WITH_LEN("FULLTEXT KEY "));1525 packet->append(STRING_WITH_LEN("FULLTEXT KEY "));
1526 else if (key_info->flags & HA_SPATIAL)1526 else if (key_info->flags & HA_SPATIAL)
1527 packet->append(STRING_WITH_LEN("SPATIAL KEY "));1527 packet->append(STRING_WITH_LEN("SPATIAL KEY "));
1528 else if (key_info->flags & HA_CLUSTERING)
1529 packet->append(STRING_WITH_LEN("CLUSTERING KEY "));
1528 else1530 else
1529 packet->append(STRING_WITH_LEN("KEY "));1531 packet->append(STRING_WITH_LEN("KEY "));
15301532
@@ -5227,6 +5229,7 @@
5227 store_column_type(table, field, cs, IS_COLUMNS_DATA_TYPE);5229 store_column_type(table, field, cs, IS_COLUMNS_DATA_TYPE);
5228 pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :5230 pos=(uchar*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
5229 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :5231 (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
5232 (field->flags & CLUSTERING_FLAG) ? "CLU" :
5230 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");5233 (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
5231 table->field[IS_COLUMNS_COLUMN_KEY]->store((const char*) pos,5234 table->field[IS_COLUMNS_COLUMN_KEY]->store((const char*) pos,
5232 strlen((const char*) pos), cs);5235 strlen((const char*) pos), cs);
52335236
=== modified file 'sql/sql_table.cc'
--- sql/sql_table.cc 2014-02-17 11:12:40 +0000
+++ sql/sql_table.cc 2014-03-26 12:37:51 +0000
@@ -3757,7 +3757,7 @@
3757 break;3757 break;
3758 }3758 }
37593759
3760 switch (key->type) {3760 switch ((unsigned)key->type) {
3761 case Key::MULTIPLE:3761 case Key::MULTIPLE:
3762 key_info->flags= 0;3762 key_info->flags= 0;
3763 break;3763 break;
@@ -3780,6 +3780,23 @@
3780 case Key::FOREIGN_KEY:3780 case Key::FOREIGN_KEY:
3781 key_number--; // Skip this key3781 key_number--; // Skip this key
3782 continue;3782 continue;
3783 case Key::CLUSTERING | Key::UNIQUE:
3784 case Key::CLUSTERING | Key::MULTIPLE:
3785 if (unlikely(!ha_check_storage_engine_flag(
3786 file->ht, HTON_SUPPORTS_CLUSTERED_KEYS)))
3787 {
3788 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
3789 ha_resolve_storage_engine_name(file->ht), "CLUSTERING");
3790 DBUG_RETURN(TRUE);
3791 }
3792 if (key->type & Key::UNIQUE)
3793 key_info->flags= HA_NOSAME;
3794 else
3795 key_info->flags= 0;
3796 key_info->flags|= HA_CLUSTERING;
3797 break;
3798 case Key::CLUSTERING:
3799 DBUG_ASSERT(0);
3783 default:3800 default:
3784 key_info->flags = HA_NOSAME;3801 key_info->flags = HA_NOSAME;
3785 break;3802 break;
@@ -4021,7 +4038,7 @@
4021 key_part_length= min(max_key_length, file->max_key_part_length());4038 key_part_length= min(max_key_length, file->max_key_part_length());
4022 if (max_field_size)4039 if (max_field_size)
4023 key_part_length= min(key_part_length, max_field_size);4040 key_part_length= min(key_part_length, max_field_size);
4024 if (key->type == Key::MULTIPLE)4041 if (key->type & Key::MULTIPLE)
4025 {4042 {
4026 /* not a critical problem */4043 /* not a critical problem */
4027 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,4044 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -4073,7 +4090,7 @@
4073 key->type != Key::FULLTEXT)4090 key->type != Key::FULLTEXT)
4074 {4091 {
4075 key_part_length= file->max_key_part_length();4092 key_part_length= file->max_key_part_length();
4076 if (key->type == Key::MULTIPLE)4093 if (key->type & Key::MULTIPLE)
4077 {4094 {
4078 /* not a critical problem */4095 /* not a critical problem */
4079 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,4096 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@@ -7235,7 +7252,9 @@
7235 key_type= Key::FULLTEXT;7252 key_type= Key::FULLTEXT;
7236 else7253 else
7237 key_type= Key::MULTIPLE;7254 key_type= Key::MULTIPLE;
7238 7255 if (key_info->flags & HA_CLUSTERING)
7256 key_type= (enum Key::Keytype)(key_type | Key::CLUSTERING);
7257
7239 if (index_column_dropped)7258 if (index_column_dropped)
7240 {7259 {
7241 /*7260 /*
@@ -7251,7 +7270,7 @@
7251 key_parts);7270 key_parts);
7252 new_key_list.push_back(key);7271 new_key_list.push_back(key);
72537272
7254 if (skip_secondary && key_type == Key::MULTIPLE) {7273 if (skip_secondary && key_type & Key::MULTIPLE) {
7255 delayed_key_list.push_back(key);7274 delayed_key_list.push_back(key);
7256 }7275 }
7257 }7276 }
@@ -7264,7 +7283,7 @@
72647283
7265 if (key->type != Key::FOREIGN_KEY)7284 if (key->type != Key::FOREIGN_KEY)
7266 {7285 {
7267 if (skip_secondary && key->type == Key::MULTIPLE) {7286 if (skip_secondary && key->type & Key::MULTIPLE) {
7268 delayed_key_list.push_back(key);7287 delayed_key_list.push_back(key);
7269 }7288 }
7270 }7289 }
72717290
=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy 2014-02-25 07:30:22 +0000
+++ sql/sql_yacc.yy 2014-03-26 12:37:51 +0000
@@ -1029,7 +1029,7 @@
1029 Currently there are 161 shift/reduce conflicts.1029 Currently there are 161 shift/reduce conflicts.
1030 We should not introduce new conflicts any more.1030 We should not introduce new conflicts any more.
1031*/1031*/
1032%expect 1621032%expect 164
10331033
1034/*1034/*
1035 Comments for TOKENS.1035 Comments for TOKENS.
@@ -1114,6 +1114,7 @@
1114%token CLIENT_SYM1114%token CLIENT_SYM
1115%token CLIENT_STATS_SYM1115%token CLIENT_STATS_SYM
1116%token CLOSE_SYM /* SQL-2003-R */1116%token CLOSE_SYM /* SQL-2003-R */
1117%token CLUSTERING_SYM
1117%token COALESCE /* SQL-2003-N */1118%token COALESCE /* SQL-2003-N */
1118%token CODE_SYM1119%token CODE_SYM
1119%token COLLATE_SYM /* SQL-2003-R */1120%token COLLATE_SYM /* SQL-2003-R */
@@ -1794,7 +1795,8 @@
1794 option_type opt_var_type opt_var_ident_type1795 option_type opt_var_type opt_var_ident_type
17951796
1796%type <key_type>1797%type <key_type>
1797 normal_key_type opt_unique constraint_key_type fulltext spatial1798 normal_key_type opt_unique_combo_clustering constraint_key_type
1799 fulltext spatial unique_opt_clustering unique_combo_clustering unique clustering
17981800
1799%type <key_alg>1801%type <key_alg>
1800 btree_or_rtree1802 btree_or_rtree
@@ -2445,7 +2447,7 @@
2445 }2447 }
2446 create_table_set_open_action_and_adjust_tables(lex);2448 create_table_set_open_action_and_adjust_tables(lex);
2447 }2449 }
2448 | CREATE opt_unique INDEX_SYM ident key_alg ON table_ident2450 | CREATE opt_unique_combo_clustering INDEX_SYM ident key_alg ON table_ident
2449 {2451 {
2450 if (add_create_index_prepare(Lex, $7))2452 if (add_create_index_prepare(Lex, $7))
2451 MYSQL_YYABORT;2453 MYSQL_YYABORT;
@@ -6348,6 +6350,13 @@
6348 | opt_constraint constraint_key_type opt_ident key_alg6350 | opt_constraint constraint_key_type opt_ident key_alg
6349 '(' key_list ')' normal_key_options6351 '(' key_list ')' normal_key_options
6350 {6352 {
6353 if (($1.length != 0)
6354 && ((enum Key::Keytype)$2 == (Key::CLUSTERING | Key::MULTIPLE)))
6355 {
6356 /* Forbid "CONSTRAINT c CLUSTERING" */
6357 my_parse_error(ER(ER_SYNTAX_ERROR));
6358 MYSQL_YYABORT;
6359 }
6351 if (add_create_index (Lex, $2, $3.str ? $3 : $1))6360 if (add_create_index (Lex, $2, $3.str ? $3 : $1))
6352 MYSQL_YYABORT;6361 MYSQL_YYABORT;
6353 }6362 }
@@ -6747,16 +6756,22 @@
6747 lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;6756 lex->type|= PRI_KEY_FLAG | NOT_NULL_FLAG;
6748 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;6757 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
6749 }6758 }
6750 | UNIQUE_SYM6759 | unique_combo_clustering
6751 {6760 {
6752 LEX *lex=Lex;6761 LEX *lex=Lex;
6753 lex->type|= UNIQUE_FLAG; 6762 if ($1 & Key::UNIQUE)
6763 lex->type|= UNIQUE_FLAG;
6764 if ($1 & Key::CLUSTERING)
6765 lex->type|= CLUSTERING_FLAG;
6754 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;6766 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
6755 }6767 }
6756 | UNIQUE_SYM KEY_SYM6768 | unique_combo_clustering KEY_SYM
6757 {6769 {
6758 LEX *lex=Lex;6770 LEX *lex=Lex;
6759 lex->type|= UNIQUE_KEY_FLAG; 6771 if ($1 & Key::UNIQUE)
6772 lex->type|= UNIQUE_KEY_FLAG;
6773 if ($1 & Key::CLUSTERING)
6774 lex->type|= CLUSTERING_FLAG;
6760 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX; 6775 lex->alter_info.flags|= Alter_info::ALTER_ADD_INDEX;
6761 }6776 }
6762 | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }6777 | COMMENT_SYM TEXT_STRING_sys { Lex->comment= $2; }
@@ -7139,7 +7154,8 @@
71397154
7140constraint_key_type:7155constraint_key_type:
7141 PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }7156 PRIMARY_SYM KEY_SYM { $$= Key::PRIMARY; }
7142 | UNIQUE_SYM opt_key_or_index { $$= Key::UNIQUE; }7157 | unique_combo_clustering opt_key_or_index { $$= $1; }
7158
7143 ;7159 ;
71447160
7145key_or_index:7161key_or_index:
@@ -7158,9 +7174,43 @@
7158 | INDEXES {}7174 | INDEXES {}
7159 ;7175 ;
71607176
7161opt_unique:7177opt_unique_combo_clustering:
7162 /* empty */ { $$= Key::MULTIPLE; }7178 /* empty */ { $$= Key::MULTIPLE; }
7163 | UNIQUE_SYM { $$= Key::UNIQUE; }7179 | unique_combo_clustering
7180 ;
7181
7182unique_combo_clustering:
7183 clustering
7184 {
7185 $$= (enum Key::Keytype)($1 | Key::MULTIPLE);
7186 }
7187 | unique_opt_clustering
7188 {
7189 $$= $1;
7190 }
7191 ;
7192
7193unique_opt_clustering:
7194 unique
7195 {
7196 $$= $1;
7197 }
7198 | unique clustering
7199 {
7200 $$= (enum Key::Keytype)($1 | $2);
7201 }
7202 | clustering unique
7203 {
7204 $$= (enum Key::Keytype)($1 | $2);
7205 }
7206 ;
7207
7208unique:
7209 UNIQUE_SYM { $$= Key::UNIQUE; }
7210 ;
7211
7212clustering:
7213 CLUSTERING_SYM { $$= Key::CLUSTERING; }
7164 ;7214 ;
71657215
7166fulltext:7216fulltext:
71677217
=== modified file 'sql/table.cc'
--- sql/table.cc 2014-03-17 10:59:40 +0000
+++ sql/table.cc 2014-03-26 12:37:51 +0000
@@ -854,11 +854,19 @@
854 KEY_PART_INFO *key_part= &keyinfo->key_part[key_part_n];854 KEY_PART_INFO *key_part= &keyinfo->key_part[key_part_n];
855 Field *field= key_part->field;855 Field *field= key_part->field;
856856
857 /* Flag field as unique if it is the only keypart in a unique index */857 /* Flag field as unique and/or clustering if it is the only keypart in a
858 unique/clustering index */
858 if (key_part_n == 0 && key_n != primary_key_n)859 if (key_part_n == 0 && key_n != primary_key_n)
860 {
859 field->flags |= (((keyinfo->flags & HA_NOSAME) &&861 field->flags |= (((keyinfo->flags & HA_NOSAME) &&
860 (keyinfo->user_defined_key_parts == 1)) ?862 (keyinfo->user_defined_key_parts == 1)) ?
861 UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);863 UNIQUE_KEY_FLAG : MULTIPLE_KEY_FLAG);
864
865 if (((keyinfo->flags & HA_CLUSTERING) &&
866 (keyinfo->user_defined_key_parts == 1)))
867 field->flags|= CLUSTERING_FLAG;
868 }
869
862 if (key_part_n == 0)870 if (key_part_n == 0)
863 field->key_start.set_bit(key_n);871 field->key_start.set_bit(key_n);
864 if (field->key_length() == key_part->length &&872 if (field->key_length() == key_part->length &&
@@ -1133,6 +1141,18 @@
1133 if (new_frm_ver >= 3)1141 if (new_frm_ver >= 3)
1134 {1142 {
1135 keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;1143 keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
1144 /* Replace HA_FULLTEXT & HA_SPATIAL with HA_CLUSTERING. This way we
1145 support TokuDB clustering key definitions without changing the FRM
1146 format. */
1147 if (keyinfo->flags & HA_SPATIAL && keyinfo->flags & HA_FULLTEXT)
1148 {
1149 if (!ha_check_storage_engine_flag(share->db_type(),
1150 HTON_SUPPORTS_CLUSTERED_KEYS))
1151 goto err;
1152 keyinfo->flags|= HA_CLUSTERING;
1153 keyinfo->flags&= ~HA_SPATIAL;
1154 keyinfo->flags&= ~HA_FULLTEXT;
1155 }
1136 keyinfo->key_length= (uint) uint2korr(strpos+2);1156 keyinfo->key_length= (uint) uint2korr(strpos+2);
1137 keyinfo->user_defined_key_parts= (uint) strpos[4];1157 keyinfo->user_defined_key_parts= (uint) strpos[4];
1138 keyinfo->algorithm= (enum ha_key_alg) strpos[5];1158 keyinfo->algorithm= (enum ha_key_alg) strpos[5];
11391159
=== modified file 'sql/unireg.cc'
--- sql/unireg.cc 2014-02-17 11:12:40 +0000
+++ sql/unireg.cc 2014-03-26 12:37:51 +0000
@@ -628,7 +628,15 @@
628 key_parts=0;628 key_parts=0;
629 for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)629 for (key=keyinfo,end=keyinfo+key_count ; key != end ; key++)
630 {630 {
631 int2store(pos, (key->flags ^ HA_NOSAME));631 /* Replace HA_CLUSTERING with HA_SPATIAL | HA_FULLTEXT to allow storing
632 TokuDB keys without changing the FRM format. */
633 uint16 key_flags= (uint16)key->flags;
634 if (key->flags & HA_CLUSTERING)
635 {
636 key_flags|= HA_SPATIAL;
637 key_flags|= HA_FULLTEXT;
638 }
639 int2store(pos, (key_flags ^ HA_NOSAME));
632 int2store(pos+2,key->key_length);640 int2store(pos+2,key->key_length);
633 pos[4]= (uchar) key->user_defined_key_parts;641 pos[4]= (uchar) key->user_defined_key_parts;
634 pos[5]= (uchar) key->algorithm;642 pos[5]= (uchar) key->algorithm;
635643
=== modified file 'tests/mysql_client_test.c'
--- tests/mysql_client_test.c 2013-08-14 03:57:21 +0000
+++ tests/mysql_client_test.c 2014-03-26 12:37:51 +0000
@@ -4676,7 +4676,8 @@
4676 fprintf(stdout, "\n MULTIPLE_KEY_FLAG");4676 fprintf(stdout, "\n MULTIPLE_KEY_FLAG");
4677 if (field->flags & AUTO_INCREMENT_FLAG)4677 if (field->flags & AUTO_INCREMENT_FLAG)
4678 fprintf(stdout, "\n AUTO_INCREMENT_FLAG");4678 fprintf(stdout, "\n AUTO_INCREMENT_FLAG");
46794679 if (field->flags & CLUSTERING_FLAG)
4680 fprintf(stdout, "\n CLUSTERING_FLAG");
4680 }4681 }
4681 }4682 }
4682 mysql_free_result(result);4683 mysql_free_result(result);

Subscribers

People subscribed via source and target branches