Commit ec921065 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

Post-merge fixes.

Note: One sp.test still fails (prime), and rpl_server_id2.test fails (will be fixed by guilhem ASAP).
parent bf45960e
...@@ -2,7 +2,7 @@ drop table if exists t0, t1, t2, t3,t4; ...@@ -2,7 +2,7 @@ drop table if exists t0, t1, t2, t3,t4;
create table t0 create table t0
( (
key1 int not null, key1 int not null,
INDEX i1(key1), INDEX i1(key1)
); );
alter table t0 add key2 int not null, add index i2(key2); alter table t0 add key2 int not null, add index i2(key2);
alter table t0 add key3 int not null, add index i3(key3); alter table t0 add key3 int not null, add index i3(key3);
...@@ -217,7 +217,7 @@ key3 int not null, ...@@ -217,7 +217,7 @@ key3 int not null,
index i1a (key1a, key1b), index i1a (key1a, key1b),
index i1b (key1b, key1a), index i1b (key1b, key1a),
index i2_1(key2, key2_1), index i2_1(key2, key2_1),
index i2_2(key2, key2_1), index i2_2(key2, key2_1)
); );
insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0; insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0;
select * from t4 where key1a = 3 or key1b = 4; select * from t4 where key1a = 3 or key1b = 4;
......
...@@ -6,7 +6,7 @@ key2 int, ...@@ -6,7 +6,7 @@ key2 int,
filler char(200), filler char(200),
filler2 char(200), filler2 char(200),
index(key1), index(key1),
index(key2), index(key2)
) engine=bdb; ) engine=bdb;
select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 ); select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
pk key1 key2 filler filler2 pk key1 key2 filler filler2
......
...@@ -4,7 +4,7 @@ create table t1 ...@@ -4,7 +4,7 @@ create table t1
key1 int not null, key1 int not null,
key2 int not null, key2 int not null,
INDEX i1(key1), INDEX i1(key1),
INDEX i2(key2), INDEX i2(key2)
) engine=innodb; ) engine=innodb;
explain select * from t1 where key1 < 5 or key2 > 197; explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
......
...@@ -6,7 +6,7 @@ key2 int, ...@@ -6,7 +6,7 @@ key2 int,
filler char(200), filler char(200),
filler2 char(200), filler2 char(200),
index(key1), index(key1),
index(key2), index(key2)
) engine=innodb; ) engine=innodb;
select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 ); select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
pk key1 key2 filler filler2 pk key1 key2 filler filler2
......
...@@ -10,7 +10,7 @@ stop slave; ...@@ -10,7 +10,7 @@ stop slave;
change master to master_port=SLAVE_PORT; change master to master_port=SLAVE_PORT;
show slave status; show slave status;
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 4 None 0 No NULL 127.0.0.1 root SLAVE_PORT 1 4 slave-relay-bin.000001 4 No No # 0 0 0 95 None 0 No NULL
start slave; start slave;
insert into t1 values (1); insert into t1 values (1);
show status like "slave_running"; show status like "slave_running";
......
...@@ -35,7 +35,7 @@ call foo()| ...@@ -35,7 +35,7 @@ call foo()|
ERROR 42000: PROCEDURE foo does not exist ERROR 42000: PROCEDURE foo does not exist
drop procedure if exists foo| drop procedure if exists foo|
Warnings: Warnings:
Warning 1297 PROCEDURE foo does not exist Warning 1298 PROCEDURE foo does not exist
show create procedure foo| show create procedure foo|
ERROR 42000: PROCEDURE foo does not exist ERROR 42000: PROCEDURE foo does not exist
create procedure foo() create procedure foo()
...@@ -71,7 +71,7 @@ declare y int; ...@@ -71,7 +71,7 @@ declare y int;
set x = y; set x = y;
end| end|
Warnings: Warnings:
Warning 1303 Referring to uninitialized variable y Warning 1304 Referring to uninitialized variable y
drop procedure foo| drop procedure foo|
create procedure foo() create procedure foo()
return 42| return 42|
......
...@@ -364,7 +364,7 @@ set sql_log_bin=1; ...@@ -364,7 +364,7 @@ set sql_log_bin=1;
set sql_log_off=1; set sql_log_off=1;
set sql_log_update=1; set sql_log_update=1;
Warnings: Warnings:
Note 1307 The update log is deprecated and replaced by the binary log. SET SQL_LOG_UPDATE has been ignored. Note 1308 The update log is deprecated and replaced by the binary log. SET SQL_LOG_UPDATE has been ignored.
set sql_low_priority_updates=1; set sql_low_priority_updates=1;
set sql_max_join_size=200; set sql_max_join_size=200;
select @@sql_max_join_size,@@max_join_size; select @@sql_max_join_size,@@max_join_size;
......
...@@ -10,7 +10,7 @@ drop table if exists t0, t1, t2, t3,t4; ...@@ -10,7 +10,7 @@ drop table if exists t0, t1, t2, t3,t4;
create table t0 create table t0
( (
key1 int not null, key1 int not null,
INDEX i1(key1), INDEX i1(key1)
); );
--disable_query_log --disable_query_log
...@@ -192,7 +192,7 @@ create table t4 ( ...@@ -192,7 +192,7 @@ create table t4 (
index i1b (key1b, key1a), index i1b (key1b, key1a),
index i2_1(key2, key2_1), index i2_1(key2, key2_1),
index i2_2(key2, key2_1), index i2_2(key2, key2_1)
); );
insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0; insert into t4 select key1,key1,key1 div 10, key1 % 10, key1 % 10, key1 from t0;
......
...@@ -14,7 +14,7 @@ create table t1 ( ...@@ -14,7 +14,7 @@ create table t1 (
filler char(200), filler char(200),
filler2 char(200), filler2 char(200),
index(key1), index(key1),
index(key2), index(key2)
) engine=bdb; ) engine=bdb;
......
...@@ -13,7 +13,7 @@ create table t1 ...@@ -13,7 +13,7 @@ create table t1
key2 int not null, key2 int not null,
INDEX i1(key1), INDEX i1(key1),
INDEX i2(key2), INDEX i2(key2)
) engine=innodb; ) engine=innodb;
--disable_query_log --disable_query_log
......
...@@ -14,7 +14,7 @@ create table t1 ( ...@@ -14,7 +14,7 @@ create table t1 (
filler char(200), filler char(200),
filler2 char(200), filler2 char(200),
index(key1), index(key1),
index(key2), index(key2)
) engine=innodb; ) engine=innodb;
......
...@@ -32,18 +32,18 @@ create function func1() returns int ...@@ -32,18 +32,18 @@ create function func1() returns int
return 42| return 42|
# Can't create recursively # Can't create recursively
--error 1295 --error 1296
create procedure foo() create procedure foo()
create procedure bar() set @x=3| create procedure bar() set @x=3|
--error 1295 --error 1296
create procedure foo() create procedure foo()
create function bar() returns double return 2.3| create function bar() returns double return 2.3|
# Already exists # Already exists
--error 1296 --error 1297
create procedure proc1() create procedure proc1()
set @x = 42| set @x = 42|
--error 1296 --error 1297
create function func1() returns int create function func1() returns int
return 42| return 42|
...@@ -51,39 +51,39 @@ drop procedure proc1| ...@@ -51,39 +51,39 @@ drop procedure proc1|
drop function func1| drop function func1|
# Does not exist # Does not exist
--error 1297 --error 1298
alter procedure foo| alter procedure foo|
--error 1297 --error 1298
alter function foo| alter function foo|
--error 1297 --error 1298
drop procedure foo| drop procedure foo|
--error 1297 --error 1298
drop function foo| drop function foo|
--error 1297 --error 1298
call foo()| call foo()|
drop procedure if exists foo| drop procedure if exists foo|
--error 1297 --error 1298
show create procedure foo| show create procedure foo|
# LEAVE/ITERATE with no match # LEAVE/ITERATE with no match
--error 1300 --error 1301
create procedure foo() create procedure foo()
foo: loop foo: loop
leave bar; leave bar;
end loop| end loop|
--error 1300 --error 1301
create procedure foo() create procedure foo()
foo: loop foo: loop
iterate bar; iterate bar;
end loop| end loop|
--error 1300 --error 1301
create procedure foo() create procedure foo()
foo: begin foo: begin
iterate foo; iterate foo;
end| end|
# Redefining label # Redefining label
--error 1301 --error 1302
create procedure foo() create procedure foo()
foo: loop foo: loop
foo: loop foo: loop
...@@ -92,7 +92,7 @@ foo: loop ...@@ -92,7 +92,7 @@ foo: loop
end loop foo| end loop foo|
# End label mismatch # End label mismatch
--error 1302 --error 1303
create procedure foo() create procedure foo()
foo: loop foo: loop
set @x=2; set @x=2;
...@@ -107,12 +107,12 @@ end| ...@@ -107,12 +107,12 @@ end|
drop procedure foo| drop procedure foo|
# RETURN in FUNCTION only # RETURN in FUNCTION only
--error 1305 --error 1306
create procedure foo() create procedure foo()
return 42| return 42|
# Doesn't allow queries in FUNCTIONs (for now :-( ) # Doesn't allow queries in FUNCTIONs (for now :-( )
--error 1306 --error 1307
create function foo() returns int create function foo() returns int
begin begin
declare x int; declare x int;
...@@ -126,19 +126,19 @@ create procedure p(x int) ...@@ -126,19 +126,19 @@ create procedure p(x int)
create function f(x int) returns int create function f(x int) returns int
return x+42| return x+42|
--error 1310 --error 1311
call p()| call p()|
--error 1310 --error 1311
call p(1, 2)| call p(1, 2)|
--error 1310 --error 1311
select f()| select f()|
--error 1310 --error 1311
select f(1, 2)| select f(1, 2)|
drop procedure p| drop procedure p|
drop function f| drop function f|
--error 1311 --error 1312
create procedure p(val int, out res int) create procedure p(val int, out res int)
begin begin
declare x int default 0; declare x int default 0;
...@@ -152,7 +152,7 @@ begin ...@@ -152,7 +152,7 @@ begin
end if; end if;
end| end|
--error 1311 --error 1312
create procedure p(val int, out res int) create procedure p(val int, out res int)
begin begin
declare x int default 0; declare x int default 0;
...@@ -167,7 +167,7 @@ begin ...@@ -167,7 +167,7 @@ begin
end if; end if;
end| end|
--error 1312 --error 1313
create function f(val int) returns int create function f(val int) returns int
begin begin
declare x int; declare x int;
...@@ -185,12 +185,12 @@ begin ...@@ -185,12 +185,12 @@ begin
end if; end if;
end| end|
--error 1313 --error 1314
select f(10)| select f(10)|
drop function f| drop function f|
--error 1314 --error 1315
create procedure p() create procedure p()
begin begin
declare c cursor for insert into test.t1 values ("foo", 42); declare c cursor for insert into test.t1 values ("foo", 42);
...@@ -199,7 +199,7 @@ begin ...@@ -199,7 +199,7 @@ begin
close c; close c;
end| end|
--error 1315 --error 1316
create procedure p() create procedure p()
begin begin
declare x int; declare x int;
...@@ -209,7 +209,7 @@ begin ...@@ -209,7 +209,7 @@ begin
close c; close c;
end| end|
--error 1316 --error 1317
create procedure p() create procedure p()
begin begin
declare c cursor for select * from test.t; declare c cursor for select * from test.t;
...@@ -231,7 +231,7 @@ begin ...@@ -231,7 +231,7 @@ begin
open c; open c;
close c; close c;
end| end|
--error 1317 --error 1318
call p()| call p()|
drop procedure p| drop procedure p|
...@@ -243,11 +243,11 @@ begin ...@@ -243,11 +243,11 @@ begin
close c; close c;
close c; close c;
end| end|
--error 1318 --error 1319
call p()| call p()|
drop procedure p| drop procedure p|
--error 1297 --error 1298
alter procedure bar3 sql security invoker| alter procedure bar3 sql security invoker|
--error 1059 --error 1059
alter procedure bar3 name alter procedure bar3 name
...@@ -261,7 +261,7 @@ drop table if exists t1| ...@@ -261,7 +261,7 @@ drop table if exists t1|
create table t1 (val int, x float)| create table t1 (val int, x float)|
insert into t1 values (42, 3.1), (19, 1.2)| insert into t1 values (42, 3.1), (19, 1.2)|
--error 1319 --error 1320
create procedure p() create procedure p()
begin begin
declare x int; declare x int;
...@@ -281,7 +281,7 @@ begin ...@@ -281,7 +281,7 @@ begin
fetch c into x; fetch c into x;
close c; close c;
end| end|
--error 1320 --error 1321
call p()| call p()|
drop procedure p| drop procedure p|
...@@ -296,34 +296,34 @@ begin ...@@ -296,34 +296,34 @@ begin
fetch c into x, y, z; fetch c into x, y, z;
close c; close c;
end| end|
--error 1320 --error 1321
call p()| call p()|
drop procedure p| drop procedure p|
--error 1322 --error 1323
create procedure p(in x int, x char(10)) create procedure p(in x int, x char(10))
begin begin
end| end|
--error 1322 --error 1323
create function p(x int, x char(10)) create function p(x int, x char(10))
begin begin
end| end|
--error 1323 --error 1324
create procedure p() create procedure p()
begin begin
declare x float; declare x float;
declare x int; declare x int;
end| end|
--error 1324 --error 1325
create procedure p() create procedure p()
begin begin
declare c condition for 1064; declare c condition for 1064;
declare c condition for 1065; declare c condition for 1065;
end| end|
--error 1325 --error 1326
create procedure p() create procedure p()
begin begin
declare c cursor for select * from t1; declare c cursor for select * from t1;
...@@ -331,18 +331,18 @@ begin ...@@ -331,18 +331,18 @@ begin
end| end|
# USE is not allowed # USE is not allowed
--error 1328 --error 1329
create procedure u() create procedure u()
use sptmp| use sptmp|
# Enforced standard order of declarations # Enforced standard order of declarations
--error 1329 --error 1330
create procedure p() create procedure p()
begin begin
declare c cursor for select * from t1; declare c cursor for select * from t1;
declare x int; declare x int;
end| end|
--error 1329 --error 1330
create procedure p() create procedure p()
begin begin
declare x int; declare x int;
...@@ -350,7 +350,7 @@ begin ...@@ -350,7 +350,7 @@ begin
declare foo condition for sqlstate '42S99'; declare foo condition for sqlstate '42S99';
end| end|
--error 1330 --error 1331
create procedure p() create procedure p()
begin begin
declare x int; declare x int;
...@@ -375,13 +375,13 @@ drop procedure bug1965| ...@@ -375,13 +375,13 @@ drop procedure bug1965|
# #
# BUG#1966 # BUG#1966
# #
--error 1319 --error 1320
select 1 into a| select 1 into a|
# #
# BUG#336 # BUG#336
# #
--error 1327 --error 1328
create procedure bug336(id char(16)) create procedure bug336(id char(16))
begin begin
declare x int; declare x int;
...@@ -391,7 +391,7 @@ end| ...@@ -391,7 +391,7 @@ end|
# #
# BUG#1654 # BUG#1654
# #
--error 1306 --error 1307
create function bug1654() create function bug1654()
returns int returns int
return (select sum(t.data) from test.t2 t)| return (select sum(t.data) from test.t2 t)|
...@@ -429,7 +429,7 @@ begin ...@@ -429,7 +429,7 @@ begin
fetch c1 into v1; fetch c1 into v1;
end| end|
--error 1318 --error 1319
call bug2259()| call bug2259()|
drop procedure bug2259| drop procedure bug2259|
...@@ -485,7 +485,7 @@ begin ...@@ -485,7 +485,7 @@ begin
end case; end case;
return 2; return 2;
end| end|
--error 1331 --error 1332
select bug3287()| select bug3287()|
drop function bug3287| drop function bug3287|
...@@ -496,7 +496,7 @@ when 0 then ...@@ -496,7 +496,7 @@ when 0 then
when 1 then when 1 then
insert into test.t1 values (x, 1.1); insert into test.t1 values (x, 1.1);
end case| end case|
--error 1331 --error 1332
call bug3287(2)| call bug3287(2)|
drop procedure bug3287| drop procedure bug3287|
......
...@@ -177,11 +177,11 @@ public: ...@@ -177,11 +177,11 @@ public:
if (maybe_null && *min_value) if (maybe_null && *min_value)
{ {
**min_key=1; **min_key=1;
bzero(*min_key+1,length); bzero(*min_key+1,length-1);
} }
else else
memcpy(*min_key,min_value,length+(int) maybe_null); memcpy(*min_key,min_value,length);
(*min_key)+= length+(int) maybe_null; (*min_key)+= length;
} }
if (!(max_flag & NO_MAX_RANGE) && if (!(max_flag & NO_MAX_RANGE) &&
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX))) !(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
...@@ -189,18 +189,18 @@ public: ...@@ -189,18 +189,18 @@ public:
if (maybe_null && *max_value) if (maybe_null && *max_value)
{ {
**max_key=1; **max_key=1;
bzero(*max_key+1,length); bzero(*max_key+1,length-1);
} }
else else
memcpy(*max_key,max_value,length+(int) maybe_null); memcpy(*max_key,max_value,length);
(*max_key)+= length+(int) maybe_null; (*max_key)+= length;
} }
} }
void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag) void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{ {
SEL_ARG *key_tree= first(); SEL_ARG *key_tree= first();
key_tree->store(key[key_tree->part].part_length, key_tree->store(key[key_tree->part].store_length,
range_key,*range_key_flag,range_key,NO_MAX_RANGE); range_key,*range_key_flag,range_key,NO_MAX_RANGE);
*range_key_flag|= key_tree->min_flag; *range_key_flag|= key_tree->min_flag;
if (key_tree->next_key_part && if (key_tree->next_key_part &&
...@@ -213,7 +213,7 @@ public: ...@@ -213,7 +213,7 @@ public:
void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag) void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{ {
SEL_ARG *key_tree= last(); SEL_ARG *key_tree= last();
key_tree->store(key[key_tree->part].part_length, key_tree->store(key[key_tree->part].store_length,
range_key, NO_MIN_RANGE, range_key,*range_key_flag); range_key, NO_MIN_RANGE, range_key,*range_key_flag);
(*range_key_flag)|= key_tree->max_flag; (*range_key_flag)|= key_tree->max_flag;
if (key_tree->next_key_part && if (key_tree->next_key_part &&
...@@ -959,6 +959,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -959,6 +959,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
MEM_ROOT *old_root,alloc; MEM_ROOT *old_root,alloc;
SEL_TREE *tree; SEL_TREE *tree;
KEY_PART *key_parts; KEY_PART *key_parts;
KEY *key_info;
PARAM param; PARAM param;
/* set up parameter that is passed to all functions */ /* set up parameter that is passed to all functions */
...@@ -985,24 +986,26 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use, ...@@ -985,24 +986,26 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC,&alloc); my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
for (idx=0 ; idx < head->keys ; idx++) key_info= head->key_info;
for (idx=0 ; idx < head->keys ; idx++, key_info++)
{ {
KEY_PART_INFO *key_part_info;
if (!keys_to_use.is_set(idx)) if (!keys_to_use.is_set(idx))
continue; continue;
KEY *key_info= &head->key_info[idx];
if (key_info->flags & HA_FULLTEXT) if (key_info->flags & HA_FULLTEXT)
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
param.key[param.keys]=key_parts; param.key[param.keys]=key_parts;
for (uint part=0 ; part < key_info->key_parts ; part++,key_parts++) key_part_info= key_info->key_part;
for (uint part=0 ; part < key_info->key_parts ;
part++, key_parts++, key_part_info++)
{ {
key_parts->key=param.keys; key_parts->key= param.keys;
key_parts->part=part; key_parts->part= part;
key_parts->part_length= key_info->key_part[part].length; key_parts->length= key_part_info->length;
key_parts->field= key_info->key_part[part].field; key_parts->store_length= key_part_info->store_length;
key_parts->null_bit= key_info->key_part[part].null_bit; key_parts->field= key_part_info->field;
if (key_parts->field->type() == FIELD_TYPE_BLOB) key_parts->null_bit= key_part_info->null_bit;
key_parts->part_length+=HA_KEY_BLOB_LENGTH;
key_parts->image_type = key_parts->image_type =
(key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW; (key_info->flags & HA_SPATIAL) ? Field::itMBR : Field::itRAW;
} }
...@@ -1348,7 +1351,7 @@ static int get_index_merge_params(PARAM *param, key_map& needed_reg, ...@@ -1348,7 +1351,7 @@ static int get_index_merge_params(PARAM *param, key_map& needed_reg,
else else
{ {
double n_blocks= double n_blocks=
ceil((double)(longlong)param->table->file->data_file_length / IO_SIZE); ceil((double) ((longlong)param->table->file->data_file_length / IO_SIZE));
double busy_blocks= double busy_blocks=
n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, (double) records_for_unique)); n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, (double) records_for_unique));
...@@ -1776,18 +1779,26 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -1776,18 +1779,26 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
DBUG_RETURN(0); // Can only optimize strings DBUG_RETURN(0); // Can only optimize strings
offset=maybe_null; offset=maybe_null;
length=key_part->part_length; length=key_part->store_length;
if (field->type() == FIELD_TYPE_BLOB)
if (length != key_part->length + maybe_null)
{ {
offset+=HA_KEY_BLOB_LENGTH; /* key packed with length prefix */
field_length=key_part->part_length-HA_KEY_BLOB_LENGTH; offset+= HA_KEY_BLOB_LENGTH;
field_length= length - HA_KEY_BLOB_LENGTH;
} }
else else
{ {
if (length < field_length) if (unlikely(length < field_length))
length=field_length; // Only if overlapping key {
/*
This can only happen in a table created with UNIREG where one key
overlaps many fields
*/
length= field_length;
}
else else
field_length=length; field_length= length;
} }
length+=offset; length+=offset;
if (!(min_str= (char*) alloc_root(param->mem_root, length*2))) if (!(min_str= (char*) alloc_root(param->mem_root, length*2)))
...@@ -1800,7 +1811,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -1800,7 +1811,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
res->ptr(), res->length(), res->ptr(), res->length(),
((Item_func_like*)(param->cond))->escape, ((Item_func_like*)(param->cond))->escape,
wild_one, wild_many, wild_one, wild_many,
field_length, field_length-maybe_null,
min_str+offset, max_str+offset, min_str+offset, max_str+offset,
&min_length, &max_length); &min_length, &max_length);
if (like_error) // Can't optimize with LIKE if (like_error) // Can't optimize with LIKE
...@@ -1838,13 +1849,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -1838,13 +1849,13 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
if (field->key_type() == HA_KEYTYPE_VARTEXT) if (field->key_type() == HA_KEYTYPE_VARTEXT)
copies= 2; copies= 2;
str= str2= (char*) alloc_root(param->mem_root, str= str2= (char*) alloc_root(param->mem_root,
(key_part->part_length+maybe_null)*copies+1); (key_part->store_length)*copies+1);
if (!str) if (!str)
DBUG_RETURN(0); DBUG_RETURN(0);
if (maybe_null) if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null *str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null,key_part->part_length, field->get_key_image(str+maybe_null, key_part->length,
field->charset(),key_part->image_type); field->charset(), key_part->image_type);
if (copies == 2) if (copies == 2)
{ {
/* /*
...@@ -1853,16 +1864,17 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -1853,16 +1864,17 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
all rows between 'X' and 'X ...' all rows between 'X' and 'X ...'
*/ */
uint length= uint2korr(str+maybe_null); uint length= uint2korr(str+maybe_null);
str2= str+ key_part->part_length + maybe_null; str2= str+ key_part->store_length;
/* remove end space */ /* remove end space */
while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ') while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
length--; length--;
int2store(str+maybe_null, length); int2store(str+maybe_null, length);
/* Create key that is space filled */ /* Create key that is space filled */
memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null); memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null, my_fill_8bit(field->charset(),
key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' '); str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH); key_part->length-length, ' ');
int2store(str2+maybe_null, key_part->length);
} }
if (!(tree=new SEL_ARG(field,str,str2))) if (!(tree=new SEL_ARG(field,str,str2)))
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // out of memory
...@@ -1889,39 +1901,39 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part, ...@@ -1889,39 +1901,39 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_EQUALS_FUNC: case Item_func::SP_EQUALS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_EQUAL;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_DISJOINT_FUNC: case Item_func::SP_DISJOINT_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_DISJOINT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_INTERSECTS_FUNC: case Item_func::SP_INTERSECTS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_TOUCHES_FUNC: case Item_func::SP_TOUCHES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_CROSSES_FUNC: case Item_func::SP_CROSSES_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_WITHIN_FUNC: case Item_func::SP_WITHIN_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_WITHIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_CONTAINS_FUNC: case Item_func::SP_CONTAINS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_CONTAIN;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
case Item_func::SP_OVERLAPS_FUNC: case Item_func::SP_OVERLAPS_FUNC:
tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512; tree->min_flag=GEOM_FLAG | HA_READ_MBR_INTERSECT;// NEAR_MIN;//512;
tree->max_flag=NO_MAX_RANGE; tree->max_flag=NO_MAX_RANGE;
break; break;
default: default:
break; break;
...@@ -3055,7 +3067,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree, ...@@ -3055,7 +3067,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
uint tmp_min_flag,tmp_max_flag,keynr; uint tmp_min_flag,tmp_max_flag,keynr;
char *tmp_min_key=min_key,*tmp_max_key=max_key; char *tmp_min_key=min_key,*tmp_max_key=max_key;
key_tree->store(param->key[idx][key_tree->part].part_length, key_tree->store(param->key[idx][key_tree->part].store_length,
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag); &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
uint min_key_length= (uint) (tmp_min_key- param->min_key); uint min_key_length= (uint) (tmp_min_key- param->min_key);
uint max_key_length= (uint) (tmp_max_key- param->max_key); uint max_key_length= (uint) (tmp_max_key- param->max_key);
...@@ -3152,9 +3164,20 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree, ...@@ -3152,9 +3164,20 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree,
{ {
QUICK_RANGE_SELECT *quick; QUICK_RANGE_SELECT *quick;
DBUG_ENTER("get_quick_select"); DBUG_ENTER("get_quick_select");
if ((quick=new QUICK_RANGE_SELECT(param->thd, param->table,
param->real_keynr[idx],test(parent_alloc),
parent_alloc)))
if (param->table->key_info[param->real_keynr[idx]].flags & HA_SPATIAL)
quick=new QUICK_RANGE_SELECT_GEOM(param->thd, param->table,
param->real_keynr[idx],
test(parent_alloc),
parent_alloc);
else
quick=new QUICK_RANGE_SELECT(param->thd, param->table,
param->real_keynr[idx],
test(parent_alloc), parent_alloc);
if (quick)
{ {
if (quick->error || if (quick->error ||
get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0, get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0,
...@@ -3194,7 +3217,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key, ...@@ -3194,7 +3217,7 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
return 1; return 1;
} }
char *tmp_min_key=min_key,*tmp_max_key=max_key; char *tmp_min_key=min_key,*tmp_max_key=max_key;
key_tree->store(key[key_tree->part].part_length, key_tree->store(key[key_tree->part].store_length,
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag); &tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
if (key_tree->next_key_part && if (key_tree->next_key_part &&
...@@ -3314,19 +3337,17 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) ...@@ -3314,19 +3337,17 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
{ {
for (const char *end=key+length ; for (const char *end=key+length ;
key < end; key < end;
key+= key_part++->part_length) key+= key_part++->store_length)
{ {
if (key_part->null_bit) if (key_part->null_bit && *key)
{ return 1;
if (*key++)
return 1;
}
} }
return 0; return 0;
} }
/**************************************************************************** /****************************************************************************
** Create a QUICK RANGE based on a key Create a QUICK RANGE based on a key
****************************************************************************/ ****************************************************************************/
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
...@@ -3370,9 +3391,8 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, ...@@ -3370,9 +3391,8 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
{ {
key_part->part=part; key_part->part=part;
key_part->field= key_info->key_part[part].field; key_part->field= key_info->key_part[part].field;
key_part->part_length= key_info->key_part[part].length; key_part->length= key_info->key_part[part].length;
if (key_part->field->type() == FIELD_TYPE_BLOB) key_part->store_length= key_info->key_part[part].store_length;
key_part->part_length+=HA_KEY_BLOB_LENGTH;
key_part->null_bit= key_info->key_part[part].null_bit; key_part->null_bit= key_info->key_part[part].null_bit;
} }
if (insert_dynamic(&quick->ranges,(gptr)&range)) if (insert_dynamic(&quick->ranges,(gptr)&range))
...@@ -3539,117 +3559,88 @@ int QUICK_RANGE_SELECT::get_next() ...@@ -3539,117 +3559,88 @@ int QUICK_RANGE_SELECT::get_next()
for (;;) for (;;)
{ {
int result; int result;
key_range start_key, end_key;
if (range) if (range)
{ // Already read through key {
result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ? // Already read through key
file->index_next_same(record, (byte*) range->min_key, result= file->read_range_next(test(range->flag & EQ_RANGE));
range->min_length) : if (result != HA_ERR_END_OF_FILE)
file->index_next(record));
if (!result)
{
if ((range->flag & GEOM_FLAG) || !cmp_next(*cur_range))
DBUG_RETURN(0);
}
else if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result); DBUG_RETURN(result);
} }
if (!cur_range) if (!cur_range)
range= *(cur_range= (QUICK_RANGE**)ranges.buffer); range= *(cur_range= (QUICK_RANGE**) ranges.buffer);
else else
range= range=
(cur_range == ((QUICK_RANGE**)ranges.buffer + ranges.elements - 1))? (cur_range == ((QUICK_RANGE**) ranges.buffer + ranges.elements - 1)) ?
NULL: *(++cur_range); (QUICK_RANGE*) 0 : *(++cur_range);
if (!range) if (!range)
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
if (range->flag & GEOM_FLAG)
{
if ((result = file->index_read(record,
(byte*) (range->min_key),
range->min_length,
(ha_rkey_function)(range->flag ^
GEOM_FLAG))))
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
continue;
}
DBUG_RETURN(0);
}
if (range->flag & NO_MIN_RANGE) // Read first record start_key.key= (const byte*) range->min_key;
{ start_key.length= range->min_length;
int local_error; start_key.flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
if ((local_error=file->index_first(record))) (range->flag & EQ_RANGE) ?
DBUG_RETURN(local_error); // Empty table HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
if (cmp_next(range) == 0) end_key.key= (const byte*) range->max_key;
DBUG_RETURN(0); end_key.length= range->max_length;
range=0; // No matching records; go to next range /*
continue; We use READ_AFTER_KEY here because if we are reading on a key
} prefix we want to find all keys with this prefix
if ((result = file->index_read(record, */
(byte*) (range->min_key + end_key.flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
test(range->flag & GEOM_FLAG)), HA_READ_AFTER_KEY);
range->min_length,
(range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT)))
{ result= file->read_range_first(range->min_length ? &start_key : 0,
if (result != HA_ERR_KEY_NOT_FOUND) range->max_length ? &end_key : 0,
DBUG_RETURN(result); sorted);
range=0; // Not found, to next range if (range->flag == (UNIQUE_RANGE | EQ_RANGE))
continue; range=0; // Stop searching
}
if (cmp_next(range) == 0) if (result != HA_ERR_END_OF_FILE)
{ DBUG_RETURN(result);
if (range->flag == (UNIQUE_RANGE | EQ_RANGE)) range=0; // No matching rows; go to next range
range=0; // Stop searching
DBUG_RETURN(0); // Found key is in range
}
range=0; // To next range
} }
} }
/* /* Get next for geometrical indexes */
Compare if found key is over max-value
Returns 0 if key <= range->max_key
*/
int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg) int QUICK_RANGE_SELECT_GEOM::get_next()
{ {
if (range_arg->flag & NO_MAX_RANGE) DBUG_ENTER("QUICK_RANGE_SELECT_GEOM::get_next");
return 0; /* key can't be to large */
KEY_PART *key_part=key_parts; for (;;)
for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= key_part++->part_length)
{ {
int cmp; int result;
if (key_part->null_bit) if (range)
{ {
if (*key++) // Already read through key
{ result= file->index_next_same(record, (byte*) range->min_key,
if (!key_part->field->is_null()) range->min_length);
return 1; if (result != HA_ERR_END_OF_FILE)
continue; DBUG_RETURN(result);
}
else if (key_part->field->is_null())
return 0;
} }
if ((cmp=key_part->field->key_cmp((byte*) key, key_part->part_length)) < 0)
return 0; if (!cur_range)
if (cmp > 0) range= *(cur_range= (QUICK_RANGE**) ranges.buffer);
return 1; else
range=
(cur_range == ((QUICK_RANGE**) ranges.buffer + ranges.elements - 1)) ?
(QUICK_RANGE*) 0 : *(++cur_range);
if (!range)
DBUG_RETURN(HA_ERR_END_OF_FILE); // All ranges used
result= file->index_read(record,
(byte*) range->min_key,
range->min_length,
(ha_rkey_function)(range->flag ^ GEOM_FLAG));
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
} }
return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
} }
...@@ -3833,6 +3824,47 @@ int QUICK_SELECT_DESC::get_next() ...@@ -3833,6 +3824,47 @@ int QUICK_SELECT_DESC::get_next()
} }
/*
Compare if found key is over max-value
Returns 0 if key <= range->max_key
*/
int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg)
{
if (range_arg->flag & NO_MAX_RANGE)
return 0; /* key can't be to large */
KEY_PART *key_part=key_parts;
uint store_length;
for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= store_length, key_part++)
{
int cmp;
store_length= key_part->store_length;
if (key_part->null_bit)
{
if (*key)
{
if (!key_part->field->is_null())
return 1;
continue;
}
else if (key_part->field->is_null())
return 0;
key++; // Skip null byte
store_length--;
}
if ((cmp=key_part->field->key_cmp((byte*) key, key_part->length)) < 0)
return 0;
if (cmp > 0)
return 1;
}
return (range_arg->flag & NEAR_MAX) ? 1 : 0; // Exact match
}
/* /*
Returns 0 if found key is inside range (found key >= range->min_key). Returns 0 if found key is inside range (found key >= range->min_key).
*/ */
...@@ -3843,15 +3875,18 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg) ...@@ -3843,15 +3875,18 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg)
return 0; /* key can't be to small */ return 0; /* key can't be to small */
KEY_PART *key_part = key_parts; KEY_PART *key_part = key_parts;
uint store_length;
for (char *key = range_arg->min_key, *end = key + range_arg->min_length; for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
key < end; key < end;
key += key_part++->part_length) key += store_length, key_part++)
{ {
int cmp; int cmp;
store_length= key_part->store_length;
if (key_part->null_bit) if (key_part->null_bit)
{ {
// this key part allows null values; NULL is lower than everything else // this key part allows null values; NULL is lower than everything else
if (*key++) if (*key)
{ {
// the range is expecting a null value // the range is expecting a null value
if (!key_part->field->is_null()) if (!key_part->field->is_null())
...@@ -3860,9 +3895,11 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg) ...@@ -3860,9 +3895,11 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg)
} }
else if (key_part->field->is_null()) else if (key_part->field->is_null())
return 1; // null -- outside the range return 1; // null -- outside the range
key++;
store_length--;
} }
if ((cmp = key_part->field->key_cmp((byte*) key, if ((cmp = key_part->field->key_cmp((byte*) key,
key_part->part_length)) > 0) key_part->length)) > 0)
return 0; return 0;
if (cmp < 0) if (cmp < 0)
return 1; return 1;
...@@ -3890,23 +3927,20 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg) ...@@ -3890,23 +3927,20 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg)
bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg,
uint used_key_parts) uint used_key_parts)
{ {
uint offset,end; uint offset, end;
KEY_PART *key_part = key_parts, KEY_PART *key_part = key_parts,
*key_part_end= key_part+used_key_parts; *key_part_end= key_part+used_key_parts;
for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ; for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
offset < end && key_part != key_part_end ; offset < end && key_part != key_part_end ;
offset += key_part++->part_length) offset+= key_part++->store_length)
{ {
uint null_length=test(key_part->null_bit);
if (!memcmp((char*) range_arg->min_key+offset, if (!memcmp((char*) range_arg->min_key+offset,
(char*) range_arg->max_key+offset, (char*) range_arg->max_key+offset,
key_part->part_length + null_length)) key_part->store_length))
{
offset+=null_length;
continue; continue;
}
if (null_length && range_arg->min_key[offset]) if (key_part->null_bit && range_arg->min_key[offset])
return 1; // min_key is null and max_key isn't return 1; // min_key is null and max_key isn't
// Range doesn't cover NULL. This is ok if there is no more null parts // Range doesn't cover NULL. This is ok if there is no more null parts
break; break;
...@@ -3948,33 +3982,34 @@ static void ...@@ -3948,33 +3982,34 @@ static void
print_key(KEY_PART *key_part,const char *key,uint used_length) print_key(KEY_PART *key_part,const char *key,uint used_length)
{ {
char buff[1024]; char buff[1024];
const char *key_end= key+used_length;
String tmp(buff,sizeof(buff),&my_charset_bin); String tmp(buff,sizeof(buff),&my_charset_bin);
uint store_length;
for (uint length=0; for (; key < key_end; key+=store_length, key_part++)
length < used_length ;
length+=key_part->part_length, key+=key_part->part_length, key_part++)
{ {
Field *field=key_part->field; Field *field= key_part->field;
if (length != 0) store_length= key_part->store_length;
fputc('/',DBUG_FILE);
if (field->real_maybe_null()) if (field->real_maybe_null())
{ {
length++; // null byte is not in part_length if (*key)
if (*key++)
{ {
fwrite("NULL",sizeof(char),4,DBUG_FILE); fwrite("NULL",sizeof(char),4,DBUG_FILE);
continue; continue;
} }
key++; // Skip null byte
store_length--;
} }
field->set_key_image((char*) key,key_part->part_length - field->set_key_image((char*) key, key_part->length, field->charset());
((field->type() == FIELD_TYPE_BLOB) ? field->val_str(&tmp);
HA_KEY_BLOB_LENGTH : 0),
field->charset());
field->val_str(&tmp,&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE); fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
if (key+store_length < key_end)
fputc('/',DBUG_FILE);
} }
} }
static void print_quick_sel_imerge(QUICK_INDEX_MERGE_SELECT *quick, static void print_quick_sel_imerge(QUICK_INDEX_MERGE_SELECT *quick,
const key_map *needed_reg) const key_map *needed_reg)
{ {
...@@ -3994,6 +4029,7 @@ static void print_quick_sel_imerge(QUICK_INDEX_MERGE_SELECT *quick, ...@@ -3994,6 +4029,7 @@ static void print_quick_sel_imerge(QUICK_INDEX_MERGE_SELECT *quick,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void print_quick_sel_range(QUICK_RANGE_SELECT *quick, void print_quick_sel_range(QUICK_RANGE_SELECT *quick,
const key_map *needed_reg) const key_map *needed_reg)
{ {
......
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
typedef struct st_key_part { typedef struct st_key_part {
uint16 key,part,part_length; uint16 key,part, store_length, length;
uint8 null_bit; uint8 null_bit;
Field *field; Field *field;
Field::imagetype image_type; Field::imagetype image_type;
...@@ -74,6 +74,7 @@ class QUICK_RANGE :public Sql_alloc { ...@@ -74,6 +74,7 @@ class QUICK_RANGE :public Sql_alloc {
class QUICK_SELECT_I class QUICK_SELECT_I
{ {
public: public:
bool sorted;
ha_rows records; /* estimate of # of records to be retrieved */ ha_rows records; /* estimate of # of records to be retrieved */
double read_time; /* time to perform this retrieval */ double read_time; /* time to perform this retrieval */
TABLE *head; TABLE *head;
...@@ -170,6 +171,17 @@ public: ...@@ -170,6 +171,17 @@ public:
}; };
class QUICK_RANGE_SELECT_GEOM: public QUICK_RANGE_SELECT
{
public:
QUICK_RANGE_SELECT_GEOM(THD *thd, TABLE *table, uint index_arg,
bool no_alloc, MEM_ROOT *parent_alloc)
:QUICK_RANGE_SELECT(thd, table, index_arg, no_alloc, parent_alloc)
{};
virtual int get_next();
};
/* /*
QUICK_INDEX_MERGE_SELECT - index_merge access method quick select. QUICK_INDEX_MERGE_SELECT - index_merge access method quick select.
......
...@@ -464,16 +464,15 @@ void init_slave_skip_errors(const char* arg) ...@@ -464,16 +464,15 @@ void init_slave_skip_errors(const char* arg)
} }
void st_relay_log_info::inc_group_relay_log_pos(ulonglong val, void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
ulonglong log_pos, bool skip_lock=0)
bool skip_lock)
{ {
if (!skip_lock) if (!skip_lock)
pthread_mutex_lock(&data_lock); pthread_mutex_lock(&data_lock);
inc_event_relay_log_pos(val); inc_event_relay_log_pos();
group_relay_log_pos= event_relay_log_pos; group_relay_log_pos= event_relay_log_pos;
strmake(group_relay_log_name,event_relay_log_name, strmake(group_relay_log_name,event_relay_log_name,
sizeof(group_relay_log_name)-1); sizeof(group_relay_log_name)-1);
notify_group_relay_log_name_update(); notify_group_relay_log_name_update();
...@@ -487,6 +486,28 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong val, ...@@ -487,6 +486,28 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong val,
not advance as it should on the non-transactional slave (it advances by not advance as it should on the non-transactional slave (it advances by
big leaps, whereas it should advance by small leaps). big leaps, whereas it should advance by small leaps).
*/ */
/*
In 4.x we used the event's len to compute the positions here. This is
wrong if the event was 3.23/4.0 and has been converted to 5.0, because
then the event's len is not what is was in the master's binlog, so this
will make a wrong group_master_log_pos (yes it's a bug in 3.23->4.0
replication: Exec_master_log_pos is wrong). Only way to solve this is to
have the original offset of the end of the event the relay log. This is
what we do in 5.0: log_pos has become "end_log_pos" (because the real use
of log_pos in 4.0 was to compute the end_log_pos; so better to store
end_log_pos instead of begin_log_pos.
If we had not done this fix here, the problem would also have appeared
when the slave and master are 5.0 but with different event length (for
example the slave is more recent than the master and features the event
UID). It would give false MASTER_POS_WAIT, false Exec_master_log_pos in
SHOW SLAVE STATUS, and so the user would do some CHANGE MASTER using this
value which would lead to badly broken replication.
Even the relay_log_pos will be corrupted in this case, because the len is
the relay log is not "val".
With the end_log_pos solution, we avoid computations involving lengthes.
*/
DBUG_PRINT("info", ("log_pos=%lld group_master_log_pos=%lld",
log_pos,group_master_log_pos));
if (log_pos) // 3.23 binlogs don't have log_posx if (log_pos) // 3.23 binlogs don't have log_posx
{ {
#if MYSQL_VERSION_ID < 50000 #if MYSQL_VERSION_ID < 50000
...@@ -500,10 +521,10 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong val, ...@@ -500,10 +521,10 @@ void st_relay_log_info::inc_group_relay_log_pos(ulonglong val,
Yes this is a hack but it's just to make 3.23->4.x replication work; Yes this is a hack but it's just to make 3.23->4.x replication work;
3.23->5.0 replication is working much better. 3.23->5.0 replication is working much better.
*/ */
group_master_log_pos= log_pos + val - group_master_log_pos= log_pos -
(mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0); (mi->old_format ? (LOG_EVENT_HEADER_LEN - OLD_HEADER_LEN) : 0);
#else #else
group_master_log_pos= log_pos+ val; group_master_log_pos= log_pos;
#endif /* MYSQL_VERSION_ID < 5000 */ #endif /* MYSQL_VERSION_ID < 5000 */
} }
pthread_cond_broadcast(&data_cond); pthread_cond_broadcast(&data_cond);
...@@ -2540,13 +2561,13 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name, ...@@ -2540,13 +2561,13 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
goto err; goto err;
} }
int cmp_result;
/* The "compare and wait" main loop */ /* The "compare and wait" main loop */
while (!thd->killed && while (!thd->killed &&
init_abort_pos_wait == abort_pos_wait && init_abort_pos_wait == abort_pos_wait &&
slave_running) slave_running)
{ {
bool pos_reached;
int cmp_result= 0;
/* /*
group_master_log_name can be "", if we are just after a fresh group_master_log_name can be "", if we are just after a fresh
......
...@@ -283,12 +283,14 @@ typedef struct st_relay_log_info ...@@ -283,12 +283,14 @@ typedef struct st_relay_log_info
until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN; until_log_names_cmp_result= UNTIL_LOG_NAMES_CMP_UNKNOWN;
} }
inline void inc_event_relay_log_pos(ulonglong val) inline void inc_event_relay_log_pos()
{ {
event_relay_log_pos+= val; event_relay_log_pos= future_event_relay_log_pos;
} }
void inc_group_relay_log_pos(ulonglong val, ulonglong log_pos, bool skip_lock=0); void inc_group_relay_log_pos(ulonglong log_pos,
bool skip_lock=0);
int wait_for_pos(THD* thd, String* log_name, longlong log_pos, int wait_for_pos(THD* thd, String* log_name, longlong log_pos,
longlong timeout); longlong timeout);
void close_temporary_tables(); void close_temporary_tables();
......
...@@ -206,8 +206,8 @@ sp_head::operator delete(void *ptr, size_t size) ...@@ -206,8 +206,8 @@ sp_head::operator delete(void *ptr, size_t size)
} }
sp_head::sp_head() sp_head::sp_head()
: Sql_alloc(), m_has_return(FALSE), m_simple_case(FALSE), : Sql_alloc(), m_returns_cs(NULL), m_has_return(FALSE), m_simple_case(FALSE),
m_multi_results(FALSE), m_free_list(NULL), m_returns_cs(NULL) m_multi_results(FALSE), m_free_list(NULL)
{ {
DBUG_ENTER("sp_head::sp_head"); DBUG_ENTER("sp_head::sp_head");
......
...@@ -3434,6 +3434,7 @@ unsent_create_error: ...@@ -3434,6 +3434,7 @@ unsent_create_error:
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
st_sp_security_context save_ctx; st_sp_security_context save_ctx;
#endif #endif
ha_rows select_limit;
uint smrx; uint smrx;
LINT_INIT(smrx); LINT_INIT(smrx);
...@@ -3468,9 +3469,12 @@ unsent_create_error: ...@@ -3468,9 +3469,12 @@ unsent_create_error:
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_change_security_context(thd, sp, &save_ctx); sp_change_security_context(thd, sp, &save_ctx);
#endif #endif
select_limit= thd->variables.select_limit;
thd->variables.select_limit= HA_POS_ERROR;
res= sp->execute_procedure(thd, &lex->value_list); res= sp->execute_procedure(thd, &lex->value_list);
thd->variables.select_limit= select_limit;
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_restore_security_context(thd, sp, &save_ctx); sp_restore_security_context(thd, sp, &save_ctx);
#endif #endif
......
...@@ -6976,7 +6976,7 @@ static void test_explain_bug() ...@@ -6976,7 +6976,7 @@ static void test_explain_bug()
"","","",NAME_LEN,0); "","","",NAME_LEN,0);
verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_VAR_STRING, verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_VAR_STRING,
"","","",NAME_LEN*32,0); "","","",NAME_LEN*64,0);
verify_prepare_field(result,7,"ref","",MYSQL_TYPE_VAR_STRING, verify_prepare_field(result,7,"ref","",MYSQL_TYPE_VAR_STRING,
"","","",NAME_LEN*16,0); "","","",NAME_LEN*16,0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment