MDEV-26938 Support descending indexes internally in InnoDB (server part)

* preserve DESC index property in the parser
* store it in the frm (only for HA_KEY_ALG_BTREE)
* read it from the frm
* show it in SHOW CREATE
* skip DESC indexes in opt_range.cc and opt_sum.cc
* ORDER BY test

This includes a fix of MDEV-27432.
This commit is contained in:
Sergei Golubchik 2021-11-24 16:50:21 +01:00
parent 358921ce32
commit a4cac0e07a
28 changed files with 882 additions and 119 deletions

View file

@ -318,7 +318,7 @@ a3 char(3),
a4 real,
a5 date,
key k1(a2,a3),
key k2(a4 desc,a1),
key k2(a4 /*desc*/,a1),
key k3(a5,a1)
);
create table t2(

View file

@ -206,7 +206,7 @@ create table t1(
a4 real,
a5 date,
key k1(a2,a3),
key k2(a4 desc,a1),
key k2(a4 /*desc*/,a1),
key k3(a5,a1)
);
create table t2(

View file

@ -1,4 +1,3 @@
drop table if exists t1,t2,t3;
SET SQL_WARNINGS=1;
CREATE TABLE t1 (
ID CHAR(32) NOT NULL,
@ -685,3 +684,8 @@ c c
9 10
10 11
drop table t1,t2;
#
# MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
#
create table t1 (a int, b int, key(a), key(a desc));
drop table t1;

View file

@ -1,6 +1,3 @@
--disable_warnings
drop table if exists t1,t2,t3;
--enable_warnings
--source include/have_sequence.inc
SET SQL_WARNINGS=1;
@ -603,3 +600,9 @@ EXPLAIN SELECT t1.c, t2.c FROM t1, t2 WHERE t1.b=t2.a and t1.c=t2.b;
SELECT t1.c, t2.c FROM t1, t2 WHERE t1.b=t2.a and t1.c=t2.b;
drop table t1,t2;
--echo #
--echo # MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
--echo #
create table t1 (a int, b int, key(a), key(a desc));
drop table t1;

View file

@ -1201,8 +1201,8 @@ EXPLAIN SELECT DISTINCT a FROM t1 {
},
{
"index": "a",
"usable": true,
"key_parts": ["a"]
"key_parts": ["a"],
"usable": true
}
],
"best_covering_index_scan": {
@ -1384,8 +1384,8 @@ EXPLAIN SELECT MIN(d) FROM t1 where b=2 and c=3 group by a {
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a", "b", "c", "d"]
"key_parts": ["a", "b", "c", "d"],
"usable": true
}
],
"best_covering_index_scan": {
@ -1583,8 +1583,8 @@ EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id {
"potential_range_indexes": [
{
"index": "id",
"usable": true,
"key_parts": ["id", "a"]
"key_parts": ["id", "a"],
"usable": true
}
],
"best_covering_index_scan": {
@ -1771,8 +1771,8 @@ EXPLAIN SELECT * FROM t1 WHERE a = 20010104e0 GROUP BY id {
"potential_range_indexes": [
{
"index": "id",
"usable": true,
"key_parts": ["id", "a"]
"key_parts": ["id", "a"],
"usable": true
}
],
"best_covering_index_scan": {
@ -2010,13 +2010,13 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
},
{
"index": "a_c",
"usable": true,
"key_parts": ["a", "c"]
"key_parts": ["a", "c"],
"usable": true
},
{
"index": "a_b",
"usable": true,
"key_parts": ["a", "b"]
"key_parts": ["a", "b"],
"usable": true
}
],
"setup_range_conditions": [],
@ -2213,8 +2213,8 @@ explain select * from t1 where a=1 and b=2 order by c limit 1 {
},
{
"index": "a_c",
"usable": true,
"key_parts": ["a", "c"]
"key_parts": ["a", "c"],
"usable": true
},
{
"index": "a_b",
@ -3233,18 +3233,18 @@ explain select * from t1 where pk = 2 and a=5 and b=1 {
"potential_range_indexes": [
{
"index": "pk",
"usable": true,
"key_parts": ["pk"]
"key_parts": ["pk"],
"usable": true
},
{
"index": "pk_a",
"usable": true,
"key_parts": ["pk", "a"]
"key_parts": ["pk", "a"],
"usable": true
},
{
"index": "pk_a_b",
"usable": true,
"key_parts": ["pk", "a", "b"]
"key_parts": ["pk", "a", "b"],
"usable": true
}
],
"best_covering_index_scan": {
@ -3751,8 +3751,8 @@ explain delete from t0 where t0.a<3 {
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a"]
"key_parts": ["a"],
"usable": true
}
],
"setup_range_conditions": [],
@ -3889,8 +3889,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a"]
"key_parts": ["a"],
"usable": true
}
],
"best_covering_index_scan": {
@ -3954,8 +3954,8 @@ explain delete t0,t1 from t0, t1 where t0.a=t1.a and t1.a<3 {
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a"]
"key_parts": ["a"],
"usable": true
}
],
"best_covering_index_scan": {

View file

@ -78,13 +78,13 @@ explain select * from t1 where a=1 or b=1 {
"potential_range_indexes": [
{
"index": "a",
"usable": true,
"key_parts": ["a"]
"key_parts": ["a"],
"usable": true
},
{
"index": "b",
"usable": true,
"key_parts": ["b"]
"key_parts": ["b"],
"usable": true
},
{
"index": "c",

View file

@ -93,13 +93,13 @@ explain select * from t1 where pk1 != 0 and key1 = 1 {
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": true,
"key_parts": ["pk1", "pk2"]
"key_parts": ["pk1", "pk2"],
"usable": true
},
{
"index": "key1",
"usable": true,
"key_parts": ["key1"]
"key_parts": ["key1"],
"usable": true
},
{
"index": "key2",

View file

@ -1,5 +1,4 @@
call mtr.add_suppression("Sort aborted.*");
drop table if exists t1,t2,t3;
call mtr.add_suppression("Out of sort memory; increase server sort buffer size");
CREATE TABLE t1 (
id int(6) DEFAULT '0' NOT NULL,
@ -4487,3 +4486,38 @@ a group_concat(t1.b)
58 1
DROP TABLE t1, t2;
# End of 10.6 tests
#
# MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
#
create table t1 (a int, b int, c int, key r (a desc, b asc));
insert t1 select seq % 10, seq div 10, seq from seq_1_to_55;
insert t1 values (NULL, NULL, NULL), (9, NULL, NULL);
explain select * from t1 force index(r) order by a,b limit 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 57 Using filesort
explain select * from t1 force index(r) order by a desc,b limit 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL r 10 NULL 20
select * from t1 force index(r) order by a desc,b limit 20;
a b c
9 NULL NULL
9 0 9
9 1 19
9 2 29
9 3 39
9 4 49
8 0 8
8 1 18
8 2 28
8 3 38
8 4 48
7 0 7
7 1 17
7 2 27
7 3 37
7 4 47
6 0 6
6 1 16
6 2 26
6 3 36
drop table t1;

View file

@ -3,11 +3,6 @@
#
call mtr.add_suppression("Sort aborted.*");
--disable_warnings
drop table if exists t1,t2,t3;
--enable_warnings
call mtr.add_suppression("Out of sort memory; increase server sort buffer size");
--source include/have_sequence.inc
@ -15,8 +10,6 @@ call mtr.add_suppression("Out of sort memory; increase server sort buffer size")
# Test old ORDER BY bug
#
--source include/have_sequence.inc
CREATE TABLE t1 (
id int(6) DEFAULT '0' NOT NULL,
idservice int(5),
@ -2649,3 +2642,14 @@ eval $query;
DROP TABLE t1, t2;
--echo # End of 10.6 tests
--echo #
--echo # MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
--echo #
create table t1 (a int, b int, c int, key r (a desc, b asc));
insert t1 select seq % 10, seq div 10, seq from seq_1_to_55;
insert t1 values (NULL, NULL, NULL), (9, NULL, NULL);
explain select * from t1 force index(r) order by a,b limit 20;
explain select * from t1 force index(r) order by a desc,b limit 20;
select * from t1 force index(r) order by a desc,b limit 20;
drop table t1;

View file

@ -220,6 +220,41 @@ dd.d1, dd.d2, dd.id limit 1
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 index NULL PRIMARY 4 NULL # Using index
1 PRIMARY t2 eq_ref PRIMARY,id2 PRIMARY 4 func # Using where
2 DEPENDENT SUBQUERY dd range id2,for_latest_sort for_latest_sort 6 NULL # Using where
2 DEPENDENT SUBQUERY dd index id2,for_latest_sort for_latest_sort 14 NULL # Using where
drop table t1,t2;
# End of 10.2 tests
#
# MDEV-26938 Support descending indexes internally in InnoDB
#
create table t1 (a int, b int, c int, key r (a desc, b asc));
insert t1 select seq % 10, seq div 10, seq from seq_1_to_55;
insert t1 values (NULL, NULL, NULL), (9, NULL, NULL);
explain select * from t1 force index(r) order by a,b limit 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 57 Using filesort
explain select * from t1 force index(r) order by a desc,b limit 20;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL r 10 NULL 20
select * from t1 force index(r) order by a desc,b limit 20;
a b c
9 NULL NULL
9 0 9
9 1 19
9 2 29
9 3 39
9 4 49
8 0 8
8 1 18
8 2 28
8 3 38
8 4 48
7 0 7
7 1 17
7 2 27
7 3 37
7 4 47
6 0 6
6 1 16
6 2 26
6 3 36
drop table t1;

View file

@ -1,7 +1,8 @@
#
# ORDER BY handling (e.g. filesort) tests that require innodb
#
-- source include/have_innodb.inc
--source include/have_innodb.inc
--source include/have_sequence.inc
--disable_warnings
drop table if exists t0,t1,t2,t3;
@ -209,3 +210,14 @@ from
drop table t1,t2;
--echo # End of 10.2 tests
--echo #
--echo # MDEV-26938 Support descending indexes internally in InnoDB
--echo #
create table t1 (a int, b int, c int, key r (a desc, b asc));
insert t1 select seq % 10, seq div 10, seq from seq_1_to_55;
insert t1 values (NULL, NULL, NULL), (9, NULL, NULL);
explain select * from t1 force index(r) order by a,b limit 20;
explain select * from t1 force index(r) order by a desc,b limit 20;
select * from t1 force index(r) order by a desc,b limit 20;
drop table t1;

View file

@ -1,4 +1,3 @@
drop table if exists t1;
CREATE TABLE t1 (
a int not null,
b int not null,
@ -783,3 +782,17 @@ a b c
1 1 1
1 NULL NULL
drop table t1;
#
# MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
#
create table t1 (a int, b int, key(a desc)) partition by hash(a) partitions 4;
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
explain select * from t1 order by a limit 3;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL a 5 NULL 3
select * from t1 order by a limit 3;
a b
1 1
2 2
3 3
drop table t1;

View file

@ -1,14 +1,9 @@
#--disable_abort_on_error
#
# Simple test for the partition storage engine
# Focuses on tests of ordered index read
#
-- source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# Ordered index read, int type
#
@ -842,3 +837,12 @@ INSERT into t1 values (1, NULL, NULL), (2, NULL, '10');
select * from t1 where a = 1 order by a desc, b desc;
select * from t1 where a = 1 order by b desc;
drop table t1;
--echo #
--echo # MDEV-13756 Implement descending index: KEY (a DESC, b ASC)
--echo #
create table t1 (a int, b int, key(a desc)) partition by hash(a) partitions 4;
insert into t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
explain select * from t1 order by a limit 3;
select * from t1 order by a limit 3;
drop table t1;

View file

@ -575,7 +575,7 @@ a
2010-02-01 09:31:02
2010-02-01 09:31:03
2010-02-01 09:31:04
CREATE TABLE t2 ( a TIMESTAMP, KEY ( a DESC ) );
CREATE TABLE t2 ( a TIMESTAMP, KEY ( a ) );
INSERT INTO t2 VALUES( '2010-02-01 09:31:01' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:02' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:03' );

View file

@ -386,7 +386,7 @@ EXPLAIN
SELECT * FROM t1 WHERE a >= '2010-02-01 09:31:02.0';
SELECT * FROM t1 WHERE a >= '2010-02-01 09:31:02.0';
CREATE TABLE t2 ( a TIMESTAMP, KEY ( a DESC ) );
CREATE TABLE t2 ( a TIMESTAMP, KEY ( a ) );
INSERT INTO t2 VALUES( '2010-02-01 09:31:01' );
INSERT INTO t2 VALUES( '2010-02-01 09:31:02' );

View file

@ -1,4 +1,4 @@
@@ -13,7 +13,7 @@
@@ -13,212 +13,212 @@
#
# Pre-create several tables
SET SQL_MODE='STRICT_ALL_TABLES';
@ -7,106 +7,347 @@
INSERT INTO t1 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31);
SELECT * FROM t1;
@@ -28,7 +28,7 @@
20
30
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
31
-CREATE TABLE t2(a TINYINT UNSIGNED AUTO_INCREMENT KEY) ENGINE = InnoDB;
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t2(a TINYINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t2 VALUES(-5);
ERROR 22003: Out of range value for column 'a' at row 1
INSERT INTO t2 VALUES(0), (0), (0), (0), (8), (10), (0),
@@ -45,7 +45,7 @@
20
30
(20), (30), (31);
SELECT * FROM t2;
a
-1
-2
-3
-4
-8
-10
-11
-20
-30
31
-CREATE TABLE t3(a SMALLINT AUTO_INCREMENT KEY) ENGINE = InnoDB;
+30
+20
+11
+10
+8
+4
+3
+2
+1
+CREATE TABLE t3(a SMALLINT AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t3 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31), (1024), (4096);
SELECT * FROM t3;
@@ -62,7 +62,7 @@
31
1024
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
-31
-1024
4096
-CREATE TABLE t4(a SMALLINT UNSIGNED AUTO_INCREMENT KEY) ENGINE = InnoDB;
+1024
+31
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t4(a SMALLINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t4 VALUES(-5);
ERROR 22003: Out of range value for column 'a' at row 1
INSERT INTO t4 VALUES(0), (0), (0), (0), (8), (10), (0),
@@ -81,7 +81,7 @@
31
1024
(20), (30), (31), (1024), (4096);
SELECT * FROM t4;
a
-1
-2
-3
-4
-8
-10
-11
-20
-30
-31
-1024
4096
-CREATE TABLE t5(a MEDIUMINT AUTO_INCREMENT KEY) ENGINE = InnoDB;
+1024
+31
+30
+20
+11
+10
+8
+4
+3
+2
+1
+CREATE TABLE t5(a MEDIUMINT AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t5 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31), (1000000), (1000005);
SELECT * FROM t5;
@@ -98,7 +98,7 @@
31
1000000
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
-31
-1000000
1000005
-CREATE TABLE t6(a MEDIUMINT UNSIGNED AUTO_INCREMENT KEY) ENGINE = InnoDB;
+1000000
+31
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t6(a MEDIUMINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t6 VALUES(-5);
ERROR 22003: Out of range value for column 'a' at row 1
INSERT INTO t6 VALUES(0), (0), (0), (0), (8), (10), (0),
@@ -117,7 +117,7 @@
31
1000000
(20), (30), (31), (1000000), (1000005);
SELECT * FROM t6;
a
-1
-2
-3
-4
-8
-10
-11
-20
-30
-31
-1000000
1000005
-CREATE TABLE t7(a INT AUTO_INCREMENT KEY) ENGINE = InnoDB;
+1000000
+31
+30
+20
+11
+10
+8
+4
+3
+2
+1
+CREATE TABLE t7(a INT AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t7 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31), (100000000), (100000008);
SELECT * FROM t7;
@@ -134,7 +134,7 @@
31
100000000
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
-31
-100000000
100000008
-CREATE TABLE t8(a INT UNSIGNED AUTO_INCREMENT KEY) ENGINE = InnoDB;
+100000000
+31
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t8(a INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t8 VALUES(-5);
ERROR 22003: Out of range value for column 'a' at row 1
INSERT INTO t8 VALUES(0), (0), (0), (0), (8), (10), (0),
@@ -153,7 +153,7 @@
31
100000000
(20), (30), (31), (100000000), (100000008);
SELECT * FROM t8;
a
-1
-2
-3
-4
-8
-10
-11
-20
-30
-31
-100000000
100000008
-CREATE TABLE t9(a BIGINT AUTO_INCREMENT KEY) ENGINE = InnoDB;
+100000000
+31
+30
+20
+11
+10
+8
+4
+3
+2
+1
+CREATE TABLE t9(a BIGINT AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t9 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31), (100000000000), (100000000006);
SELECT * FROM t9;
@@ -170,7 +170,7 @@
31
100000000000
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
-31
-100000000000
100000000006
-CREATE TABLE t10(a BIGINT UNSIGNED AUTO_INCREMENT KEY) ENGINE = InnoDB;
+100000000000
+31
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t10(a BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t10 VALUES(-5);
ERROR 22003: Out of range value for column 'a' at row 1
INSERT INTO t10 VALUES(0), (0), (0), (0), (8), (10), (0),
@@ -189,7 +189,7 @@
31
100000000000
(20), (30), (31), (100000000000), (100000000006);
SELECT * FROM t10;
a
-1
-2
-3
-4
-8
-10
-11
-20
-30
-31
-100000000000
100000000006
-CREATE TABLE t11(a FLOAT AUTO_INCREMENT KEY) ENGINE = InnoDB;
+100000000000
+31
+30
+20
+11
+10
+8
+4
+3
+2
+1
+CREATE TABLE t11(a FLOAT AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t11 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31);
SELECT * FROM t11;
@@ -204,7 +204,7 @@
20
30
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
31
-CREATE TABLE t12(a DOUBLE AUTO_INCREMENT KEY) ENGINE = InnoDB;
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
+CREATE TABLE t12(a DOUBLE AUTO_INCREMENT, PRIMARY KEY(a DESC)) ENGINE = InnoDB;
INSERT INTO t12 VALUES(0), (0), (0), (0), (-1), (-10), (0),
(20), (30), (31);
SELECT * FROM t12;
@@ -242,7 +242,7 @@
a
--10
--1
-1
-2
-3
-4
-5
-20
-30
31
+30
+20
+5
+4
+3
+2
+1
+-1
+-10
# Scenario 1: Normal restart, to test if the counters are persisted
# Scenario 2: Delete some values, to test the counters should not be the
# one which is the largest in current table
@@ -242,14 +242,14 @@
SELECT MAX(a) AS `Expect 100000000000` FROM t9;
Expect 100000000000
100000000000
@ -115,6 +356,333 @@
AUTO_INCREMENT = 1234;
# restart
SHOW CREATE TABLE t13;
Table Create Table
t13 CREATE TABLE `t13` (
`a` int(11) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=1234 DEFAULT CHARSET=latin1
INSERT INTO t13 VALUES(0);
SELECT a AS `Expect 1234` FROM t13;
@@ -464,28 +464,28 @@
INSERT INTO t1 VALUES(0), (0);
SELECT * FROM t1;
a
-1
2
+1
INSERT INTO t3 VALUES(0), (0);
SELECT * FROM t3;
a
-1
2
+1
INSERT INTO t5 VALUES(0), (0);
SELECT * FROM t5;
a
-1
2
+1
INSERT INTO t7 VALUES(0), (0);
SELECT * FROM t7;
a
-1
2
+1
INSERT INTO t9 VALUES(0), (0);
SELECT * FROM t9;
a
-1
2
+1
# Ensure that all changes before the server is killed are persisted.
set global innodb_flush_log_at_trx_commit=1;
TRUNCATE TABLE t1;
@@ -498,63 +498,63 @@
INSERT INTO t19 VALUES(0), (0);
SELECT * FROM t19;
a
-1
2
+1
# restart
INSERT INTO t1 VALUES(0), (0);
SELECT * FROM t1;
a
-1
2
+1
INSERT INTO t3 VALUES(0), (0);
SELECT * FROM t3;
a
-1
2
+1
INSERT INTO t5 VALUES(0), (0);
SELECT * FROM t5;
a
-1
2
+1
INSERT INTO t7 VALUES(0), (0);
SELECT * FROM t7;
a
-1
2
+1
INSERT INTO t19 VALUES(0), (0);
SELECT * FROM t19;
a
-1
-2
-3
4
+3
+2
+1
DELETE FROM t19 WHERE a = 4;
RENAME TABLE t19 to t9;
INSERT INTO t9 VALUES(0), (0);
SELECT * FROM t9;
a
-1
-2
-3
-5
6
+5
+3
+2
+1
TRUNCATE TABLE t9;
INSERT INTO t9 VALUES(0), (0);
SELECT * FROM t9;
a
-1
2
+1
# Scenario 8: Test ALTER TABLE operations
INSERT INTO t3 VALUES(0), (0), (100), (200), (1000);
SELECT * FROM t3;
a
-1
-2
-3
-4
-100
-200
1000
+200
+100
+4
+3
+2
+1
DELETE FROM t3 WHERE a > 300;
SELECT MAX(a) AS `Expect 200` FROM t3;
Expect 200
@@ -566,7 +566,7 @@
Table Create Table
t3 CREATE TABLE `t3` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=latin1
INSERT INTO t3 VALUES(0);
SELECT MAX(a) AS `Expect 201` FROM t3;
@@ -579,7 +579,7 @@
Table Create Table
t3 CREATE TABLE `t3` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=500 DEFAULT CHARSET=latin1
INSERT INTO t3 VALUES(0);
SELECT MAX(a) AS `Expect 500` FROM t3;
@@ -591,13 +591,13 @@
Table Create Table
t3 CREATE TABLE `t3` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=100 DEFAULT CHARSET=latin1
INSERT INTO t3 VALUES(0), (0);
SELECT * FROM t3;
a
-100
101
+100
INSERT INTO t3 VALUES(150), (180);
UPDATE t3 SET a = 200 WHERE a = 150;
INSERT INTO t3 VALUES(220);
@@ -607,7 +607,7 @@
Table Create Table
t3 CREATE TABLE `t3` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=221 DEFAULT CHARSET=latin1
INSERT INTO t3 VALUES(0);
SELECT MAX(a) AS `Expect 221` FROM t3;
@@ -619,7 +619,7 @@
Table Create Table
t3 CREATE TABLE `t3` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=120 DEFAULT CHARSET=latin1
# MDEV-6076: Test adding an AUTO_INCREMENT COLUMN
CREATE TABLE mdev6076a (b INT) ENGINE=InnoDB;
@@ -669,18 +669,18 @@
INSERT INTO t_inplace SELECT * FROM t3;
SELECT * FROM t_inplace;
a
-100
-101
-120
-121
-122
-200
210
+200
+122
+121
+120
+101
+100
SHOW CREATE TABLE t_inplace;
Table Create Table
t_inplace CREATE TABLE `t_inplace` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=211 DEFAULT CHARSET=latin1
# This will keep the autoinc counter
ALTER TABLE t_inplace AUTO_INCREMENT = 250, ALGORITHM = INPLACE;
@@ -689,7 +689,7 @@
Table Create Table
t_inplace CREATE TABLE `t_inplace` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=latin1
# This should keep the autoinc counter as well
ALTER TABLE t_inplace ADD COLUMN b INT, ALGORITHM = INPLACE;
@@ -699,16 +699,16 @@
t_inplace CREATE TABLE `t_inplace` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=latin1
DELETE FROM t_inplace WHERE a > 150;
SELECT * FROM t_inplace;
a b
-100 NULL
-101 NULL
-120 NULL
-121 NULL
122 NULL
+121 NULL
+120 NULL
+101 NULL
+100 NULL
# This should reset the autoinc counter to the one specified
# Since it's smaller than current one but bigger than existing
# biggest counter in the table
@@ -719,7 +719,7 @@
t_inplace CREATE TABLE `t_inplace` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=180 DEFAULT CHARSET=latin1
# This should reset the autoinc counter to the next value of
# current max counter in the table, since the specified value
@@ -730,7 +730,7 @@
Table Create Table
t_inplace CREATE TABLE `t_inplace` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=123 DEFAULT CHARSET=latin1
INSERT INTO t_inplace VALUES(0), (0);
SELECT MAX(a) AS `Expect 124` FROM t_inplace;
@@ -757,18 +757,18 @@
INSERT INTO t_copy SELECT * FROM t3;
SELECT * FROM t_copy;
a
-100
-101
-120
-121
-122
-200
210
+200
+122
+121
+120
+101
+100
SHOW CREATE TABLE t_copy;
Table Create Table
t_copy CREATE TABLE `t_copy` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=211 DEFAULT CHARSET=latin1
# This will keep the autoinc counter
ALTER TABLE t_copy AUTO_INCREMENT = 250, ALGORITHM = COPY;
@@ -777,7 +777,7 @@
Table Create Table
t_copy CREATE TABLE `t_copy` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=latin1
# This should keep the autoinc counter as well
ALTER TABLE t_copy ADD COLUMN b INT, ALGORITHM = COPY;
@@ -787,16 +787,16 @@
t_copy CREATE TABLE `t_copy` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=250 DEFAULT CHARSET=latin1
DELETE FROM t_copy WHERE a > 150;
SELECT * FROM t_copy;
a b
-100 NULL
-101 NULL
-120 NULL
-121 NULL
122 NULL
+121 NULL
+120 NULL
+101 NULL
+100 NULL
# This should reset the autoinc counter to the one specified
# Since it's smaller than current one but bigger than existing
# biggest counter in the table
@@ -807,7 +807,7 @@
t_copy CREATE TABLE `t_copy` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
`b` int(11) DEFAULT NULL,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=180 DEFAULT CHARSET=latin1
# This should reset the autoinc counter to the next value of
# current max counter in the table, since the specified value
@@ -818,7 +818,7 @@
Table Create Table
t_copy CREATE TABLE `t_copy` (
`a` smallint(6) NOT NULL AUTO_INCREMENT,
- PRIMARY KEY (`a`)
+ PRIMARY KEY (`a` DESC)
) ENGINE=InnoDB AUTO_INCREMENT=123 DEFAULT CHARSET=latin1
INSERT INTO t_copy VALUES(0), (0);
SELECT MAX(a) AS `Expect 124` FROM t_copy;
@@ -842,7 +842,7 @@
126
DROP TABLE t_copy, it_copy;
@ -124,7 +692,7 @@
set SQL_MODE = NO_AUTO_VALUE_ON_ZERO;
INSERT INTO t30 VALUES(NULL, 1), (200, 2), (0, 3);
INSERT INTO t30(b) VALUES(4), (5), (6), (7);
@@ -869,7 +869,7 @@
@@ -869,20 +869,20 @@
set global innodb_flush_log_at_trx_commit=1;
CREATE TABLE t31 (a INT) ENGINE = InnoDB;
INSERT INTO t31 VALUES(1), (2);
@ -133,8 +701,17 @@
INSERT INTO t31 VALUES(3, 0), (4, NULL), (5, NULL);
INSERT INTO t31 VALUES(6, 0);
ERROR 23000: Duplicate entry '0' for key 'PRIMARY'
@@ -882,7 +882,7 @@
SELECT * FROM t31;
a b
-3 0
-1 1
-2 2
-4 3
5 4
+4 3
+2 2
+1 1
+3 0
SET SQL_MODE = 0;
# Scenario 10: Rollback would not rollback the counter
-CREATE TABLE t32 (a BIGINT AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB;
@ -151,6 +728,26 @@
INSERT INTO t33 VALUES(1, NULL);
INSERT INTO t33 VALUES(2, NULL);
INSERT INTO t33 VALUES(2, NULL);
@@ -920,13 +920,13 @@
INSERT INTO t31(a) VALUES(6), (0);
SELECT * FROM t31;
a b
-3 0
-1 1
-2 2
-4 3
-5 4
-6 5
0 6
+6 5
+5 4
+4 3
+2 2
+1 1
+3 0
DROP TABLE t31;
set SQL_MODE = NO_AUTO_VALUE_ON_ZERO;
DELETE FROM t30 WHERE a = 0;
@@ -965,7 +965,7 @@
DROP TABLE t33;
CREATE TABLE t33 (
@ -160,3 +757,13 @@
ALTER TABLE t33 DISCARD TABLESPACE;
restore: t33 .ibd and .cfg files
ALTER TABLE t33 IMPORT TABLESPACE;
@@ -975,7 +975,7 @@
4
SELECT * FROM t33;
a b
-10 1
-2 2
3 4
+2 2
+10 1
DROP TABLE t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t30, t32, t33;

View file

@ -1969,7 +1969,7 @@ Table Create Table
t1 CREATE TABLE `t1` (
`id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
UNIQUE KEY `id` (`id` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t1;
#

View file

@ -194,9 +194,20 @@ ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT in
CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
UNIQUE KEY FTS_DOC_ID_INDEX(FTS_DOC_ID DESC), FULLTEXT(b))
ENGINE=InnoDB;
DROP TABLE t1;
ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
UNIQUE KEY FTS_DOC_ID_INDEX(FTS_DOC_ID DESC)) ENGINE=InnoDB;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
`b` text DEFAULT NULL,
`FTS_DOC_ID` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`a`),
UNIQUE KEY `FTS_DOC_ID_INDEX` (`FTS_DOC_ID` DESC)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE;
ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=COPY;
ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
DROP TABLE t1;

View file

@ -122,17 +122,16 @@ engine=innodb;
--echo # MDEV-26938 Support descending indexes internally in InnoDB
--echo #
# Unfortunately, the HA_REVERSE_SORT flag is not being stored in the .frm file.
#FIXME: --error ER_INNODB_FT_WRONG_DOCID_INDEX
--error ER_INNODB_FT_WRONG_DOCID_INDEX
CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
UNIQUE KEY FTS_DOC_ID_INDEX(FTS_DOC_ID DESC), FULLTEXT(b))
ENGINE=InnoDB;
DROP TABLE t1;
CREATE TABLE t1(a INT PRIMARY KEY, b TEXT, FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
UNIQUE KEY FTS_DOC_ID_INDEX(FTS_DOC_ID DESC)) ENGINE=InnoDB;
#FIXME: --error ER_INNODB_FT_WRONG_DOCID_INDEX
SHOW CREATE TABLE t1;
--error ER_INNODB_FT_WRONG_DOCID_INDEX
ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=INPLACE;
#FIXME: --error ER_INNODB_FT_WRONG_DOCID_INDEX
--error ER_INNODB_FT_WRONG_DOCID_INDEX
ALTER TABLE t1 ADD FULLTEXT INDEX(b), ALGORITHM=COPY;
DROP TABLE t1;

View file

@ -342,7 +342,7 @@ tab CREATE TABLE `tab` (
`c7` geometrycollection DEFAULT NULL,
`c8` geometry DEFAULT NULL,
UNIQUE KEY `idx2` (`c8`(5)),
KEY `idx1` (`c2`(5)) USING BTREE,
KEY `idx1` (`c2`(5) DESC) USING BTREE,
KEY `idx3` (`c3`(5)) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
#check the data after modify
@ -778,7 +778,7 @@ tab3 CREATE TABLE `tab3` (
`c7` geometrycollection DEFAULT NULL,
`c8` geometry DEFAULT NULL,
UNIQUE KEY `idx2` (`c8`(5)),
KEY `idx1` (`c2`(5)) USING BTREE,
KEY `idx1` (`c2`(5) DESC) USING BTREE,
KEY `idx3` (`c3`(5)) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=16
#check index with WKB function

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2018, 2020, MariaDB
Copyright (c) 2018, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -573,6 +573,9 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec)
/* loop over every key part */
do
{
const int GREATER= key_part->key_part_flag & HA_REVERSE_SORT ? -1 : +1;
const int LESS= -GREATER;
field= key_part->field;
if (key_part->null_bit)
@ -593,12 +596,12 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec)
; /* Fall through, no NULL fields */
else
{
DBUG_RETURN(+1);
DBUG_RETURN(GREATER);
}
}
else if (!sec_is_null)
{
DBUG_RETURN(-1);
DBUG_RETURN(LESS);
}
else
goto next_loop; /* Both were NULL */
@ -612,7 +615,7 @@ int key_rec_cmp(void *key_p, uchar *first_rec, uchar *second_rec)
*/
if ((result= field->cmp_prefix(field->ptr+first_diff, field->ptr+sec_diff,
key_part->length)))
DBUG_RETURN(result);
DBUG_RETURN(result * GREATER);
next_loop:
key_part++;
key_part_num++;

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates.
Copyright (c) 2008, 2020, MariaDB
Copyright (c) 2008, 2021, MariaDB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -2805,11 +2805,11 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
}
trace_idx_details.add("usable", true);
param.key[param.keys]=key_parts;
key_part_info= key_info->key_part;
uint cur_key_len= 0;
Json_writer_array trace_keypart(thd, "key_parts");
bool unusable_has_desc_keyparts= false;
for (uint part= 0 ; part < n_key_parts ;
part++, key_parts++, key_part_info++)
{
@ -2824,8 +2824,17 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
/* Only HA_PART_KEY_SEG is used */
key_parts->flag= (uint8) key_part_info->key_part_flag;
if (key_part_info->key_part_flag & HA_REVERSE_SORT)
unusable_has_desc_keyparts= true;
trace_keypart.add(key_parts->field->field_name);
}
trace_keypart.end();
trace_idx_details.add("usable", !unusable_has_desc_keyparts);
if (unusable_has_desc_keyparts) // TODO MDEV-13756
{
key_parts= param.key[param.keys];
continue;
}
param.real_keynr[param.keys++]=idx;
if (cur_key_len > max_key_len)
max_key_len= cur_key_len;

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates.
Copyright (c) 2008, 2017, MariaDB Corporation.
Copyright (c) 2008, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -953,6 +953,9 @@ static bool find_key_for_maxmin(bool max_fl, TABLE_REF *ref,
part->length < part_field->key_length())
break;
if (part->key_part_flag & HA_REVERSE_SORT)
break; // TODO MDEV-27576
if (field->eq(part->field))
{
ref->key= idx;

View file

@ -290,9 +290,9 @@ class Key_part_spec :public Sql_alloc {
public:
LEX_CSTRING field_name;
uint length;
bool generated;
bool generated, asc;
Key_part_spec(const LEX_CSTRING *name, uint len, bool gen= false)
: field_name(*name), length(len), generated(gen)
: field_name(*name), length(len), generated(gen), asc(1)
{}
bool operator==(const Key_part_spec& other) const;
/**

View file

@ -2369,6 +2369,8 @@ int show_create_table_ex(THD *thd, TABLE_LIST *table_list,
packet->append_parenthesized((long) key_part->length /
key_part->field->charset()->mbmaxlen);
}
if (key_part->key_part_flag & HA_REVERSE_SORT)
packet->append(STRING_WITH_LEN(" DESC"));
}
if (key_info->without_overlaps)

View file

@ -2281,7 +2281,7 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
static bool key_cmp(const Key_part_spec &a, const Key_part_spec &b)
{
return a.length == b.length &&
return a.length == b.length && a.asc == b.asc &&
!lex_string_cmp(system_charset_info, &a.field_name, &b.field_name);
}
@ -3328,6 +3328,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
key_part_info->key_part_flag= column->asc ? 0 : HA_REVERSE_SORT;
uint key_part_length= sql_field->type_handler()->
calc_key_length(*sql_field);
@ -6335,6 +6336,14 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
return Compare_keys::NotEqual;
}
/*
Check the descending flag for index field.
*/
if ((new_part->key_part_flag ^ key_part->key_part_flag) & HA_REVERSE_SORT)
{
return Compare_keys::NotEqual;
}
auto compare= table->file->compare_key_parts(
*table->field[key_part->fieldnr - 1], new_field, *key_part, *new_part);
result= merge(result, compare);
@ -8386,9 +8395,10 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
key_part_length= 0; // Use whole field
}
key_part_length /= kfield->charset()->mbmaxlen;
key_parts.push_back(new (thd->mem_root) Key_part_spec(&cfield->field_name,
key_part_length, true),
thd->mem_root);
Key_part_spec *kps= new (thd->mem_root) Key_part_spec(&cfield->field_name,
key_part_length, true);
kps->asc= !(key_part->key_part_flag & HA_REVERSE_SORT);
key_parts.push_back(kps, thd->mem_root);
if (!(cfield->invisible == INVISIBLE_SYSTEM && cfield->vers_sys_field()))
user_keyparts= true;
}

View file

@ -6803,10 +6803,12 @@ ignorability:
key_list:
key_list ',' key_part order_dir
{
$3->asc= $4;
Lex->last_key->columns.push_back($3, thd->mem_root);
}
| key_part order_dir
{
$1->asc= $2;
Lex->last_key->columns.push_back($1, thd->mem_root);
}
;

View file

@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, MariaDB Corporation.
Copyright (c) 2009, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -685,6 +685,13 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
DBUG_PRINT("loop", ("flags: %lu key_parts: %d key_part: %p",
key->flags, key->user_defined_key_parts,
key->key_part));
/* For SPATIAL, FULLTEXT and HASH indexes (anything other than B-tree),
ignore the ASC/DESC attribute of columns. */
const uchar ha_reverse_sort=
key->algorithm > HA_KEY_ALG_BTREE || key->flags & (HA_FULLTEXT|HA_SPATIAL)
? 0 : HA_REVERSE_SORT;
for (key_part=key->key_part,key_part_end=key_part+key->user_defined_key_parts ;
key_part != key_part_end ;
key_part++)
@ -697,7 +704,8 @@ static uint pack_keys(uchar *keybuff, uint key_count, KEY *keyinfo,
int2store(pos,key_part->fieldnr+1+FIELD_NAME_USED);
offset= (uint) (key_part->offset+data_offset+1);
int2store(pos+2, offset);
pos[4]=0; // Sort order
key_part->key_part_flag &= ha_reverse_sort;
pos[4]= (uchar)(key_part->key_part_flag);
int2store(pos+5,key_part->key_type);
int2store(pos+7,key_part->length);
pos+=9;