Commit 3a272c1f authored by unknown's avatar unknown

Post-merge fixes.

Note: One sp.test still fails (prime), and rpl_server_id2.test fails (will be fixed by guilhem ASAP).


mysql-test/r/index_merge.result:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/r/index_merge_bdb.result:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/r/index_merge_innodb.result:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/r/index_merge_innodb2.result:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/r/rpl_server_id1.result:
  Update result after merge.
mysql-test/r/sp-error.result:
  Update result after merge.
mysql-test/r/variables.result:
  Update result after merge.
mysql-test/t/index_merge.test:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/t/index_merge_bdb.test:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/t/index_merge_innodb.test:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/t/index_merge_innodb2.test:
  Fixed syntax error (no ',' after last index in create table any more).
mysql-test/t/sp-error.test:
  Post-merge fix of error codes.
sql/opt_range.cc:
  Manually merged by Monty.
sql/opt_range.h:
  Manually merged by Monty.
sql/slave.cc:
  Post-merge fixes with some help from Guilhem.
sql/slave.h:
  Post-merge fixes with some help from Guilhem.
sql/sp_head.cc:
  Got rid of warning (reordering initialization).
sql/sql_parse.cc:
  Post-merge fix: Need to set/reset select_limit at SP CALL time as well.
tests/client_test.c:
  Post-merge fix: key_len length in explain has changed.
parent e9c1e75b
......@@ -2,7 +2,7 @@ drop table if exists t0, t1, t2, t3,t4;
create table t0
(
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 key3 int not null, add index i3(key3);
......@@ -217,7 +217,7 @@ key3 int not null,
index i1a (key1a, key1b),
index i1b (key1b, key1a),
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;
select * from t4 where key1a = 3 or key1b = 4;
......
......@@ -6,7 +6,7 @@ key2 int,
filler char(200),
filler2 char(200),
index(key1),
index(key2),
index(key2)
) engine=bdb;
select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
pk key1 key2 filler filler2
......
......@@ -4,7 +4,7 @@ create table t1
key1 int not null,
key2 int not null,
INDEX i1(key1),
INDEX i2(key2),
INDEX i2(key2)
) engine=innodb;
explain select * from t1 where key1 < 5 or key2 > 197;
id select_type table type possible_keys key key_len ref rows Extra
......
......@@ -6,7 +6,7 @@ key2 int,
filler char(200),
filler2 char(200),
index(key1),
index(key2),
index(key2)
) engine=innodb;
select * from t1 where (key1 >= 2 and key1 <= 10) or (pk >= 4 and pk <=8 );
pk key1 key2 filler filler2
......
......@@ -10,7 +10,7 @@ stop slave;
change master to master_port=SLAVE_PORT;
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
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;
insert into t1 values (1);
show status like "slave_running";
......
......@@ -35,7 +35,7 @@ call foo()|
ERROR 42000: PROCEDURE foo does not exist
drop procedure if exists foo|
Warnings:
Warning 1297 PROCEDURE foo does not exist
Warning 1298 PROCEDURE foo does not exist
show create procedure foo|
ERROR 42000: PROCEDURE foo does not exist
create procedure foo()
......@@ -71,7 +71,7 @@ declare y int;
set x = y;
end|
Warnings:
Warning 1303 Referring to uninitialized variable y
Warning 1304 Referring to uninitialized variable y
drop procedure foo|
create procedure foo()
return 42|
......
......@@ -364,7 +364,7 @@ set sql_log_bin=1;
set sql_log_off=1;
set sql_log_update=1;
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_max_join_size=200;
select @@sql_max_join_size,@@max_join_size;
......
......@@ -10,7 +10,7 @@ drop table if exists t0, t1, t2, t3,t4;
create table t0
(
key1 int not null,
INDEX i1(key1),
INDEX i1(key1)
);
--disable_query_log
......@@ -192,7 +192,7 @@ create table t4 (
index i1b (key1b, key1a),
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;
......
......@@ -14,7 +14,7 @@ create table t1 (
filler char(200),
filler2 char(200),
index(key1),
index(key2),
index(key2)
) engine=bdb;
......
......@@ -13,7 +13,7 @@ create table t1
key2 int not null,
INDEX i1(key1),
INDEX i2(key2),
INDEX i2(key2)
) engine=innodb;
--disable_query_log
......
......@@ -14,7 +14,7 @@ create table t1 (
filler char(200),
filler2 char(200),
index(key1),
index(key2),
index(key2)
) engine=innodb;
......
......@@ -32,18 +32,18 @@ create function func1() returns int
return 42|
# Can't create recursively
--error 1295
--error 1296
create procedure foo()
create procedure bar() set @x=3|
--error 1295
--error 1296
create procedure foo()
create function bar() returns double return 2.3|
# Already exists
--error 1296
--error 1297
create procedure proc1()
set @x = 42|
--error 1296
--error 1297
create function func1() returns int
return 42|
......@@ -51,39 +51,39 @@ drop procedure proc1|
drop function func1|
# Does not exist
--error 1297
--error 1298
alter procedure foo|
--error 1297
--error 1298
alter function foo|
--error 1297
--error 1298
drop procedure foo|
--error 1297
--error 1298
drop function foo|
--error 1297
--error 1298
call foo()|
drop procedure if exists foo|
--error 1297
--error 1298
show create procedure foo|
# LEAVE/ITERATE with no match
--error 1300
--error 1301
create procedure foo()
foo: loop
leave bar;
end loop|
--error 1300
--error 1301
create procedure foo()
foo: loop
iterate bar;
end loop|
--error 1300
--error 1301
create procedure foo()
foo: begin
iterate foo;
end|
# Redefining label
--error 1301
--error 1302
create procedure foo()
foo: loop
foo: loop
......@@ -92,7 +92,7 @@ foo: loop
end loop foo|
# End label mismatch
--error 1302
--error 1303
create procedure foo()
foo: loop
set @x=2;
......@@ -107,12 +107,12 @@ end|
drop procedure foo|
# RETURN in FUNCTION only
--error 1305
--error 1306
create procedure foo()
return 42|
# Doesn't allow queries in FUNCTIONs (for now :-( )
--error 1306
--error 1307
create function foo() returns int
begin
declare x int;
......@@ -126,19 +126,19 @@ create procedure p(x int)
create function f(x int) returns int
return x+42|
--error 1310
--error 1311
call p()|
--error 1310
--error 1311
call p(1, 2)|
--error 1310
--error 1311
select f()|
--error 1310
--error 1311
select f(1, 2)|
drop procedure p|
drop function f|
--error 1311
--error 1312
create procedure p(val int, out res int)
begin
declare x int default 0;
......@@ -152,7 +152,7 @@ begin
end if;
end|
--error 1311
--error 1312
create procedure p(val int, out res int)
begin
declare x int default 0;
......@@ -167,7 +167,7 @@ begin
end if;
end|
--error 1312
--error 1313
create function f(val int) returns int
begin
declare x int;
......@@ -185,12 +185,12 @@ begin
end if;
end|
--error 1313
--error 1314
select f(10)|
drop function f|
--error 1314
--error 1315
create procedure p()
begin
declare c cursor for insert into test.t1 values ("foo", 42);
......@@ -199,7 +199,7 @@ begin
close c;
end|
--error 1315
--error 1316
create procedure p()
begin
declare x int;
......@@ -209,7 +209,7 @@ begin
close c;
end|
--error 1316
--error 1317
create procedure p()
begin
declare c cursor for select * from test.t;
......@@ -231,7 +231,7 @@ begin
open c;
close c;
end|
--error 1317
--error 1318
call p()|
drop procedure p|
......@@ -243,11 +243,11 @@ begin
close c;
close c;
end|
--error 1318
--error 1319
call p()|
drop procedure p|
--error 1297
--error 1298
alter procedure bar3 sql security invoker|
--error 1059
alter procedure bar3 name
......@@ -261,7 +261,7 @@ drop table if exists t1|
create table t1 (val int, x float)|
insert into t1 values (42, 3.1), (19, 1.2)|
--error 1319
--error 1320
create procedure p()
begin
declare x int;
......@@ -281,7 +281,7 @@ begin
fetch c into x;
close c;
end|
--error 1320
--error 1321
call p()|
drop procedure p|
......@@ -296,34 +296,34 @@ begin
fetch c into x, y, z;
close c;
end|
--error 1320
--error 1321
call p()|
drop procedure p|
--error 1322
--error 1323
create procedure p(in x int, x char(10))
begin
end|
--error 1322
--error 1323
create function p(x int, x char(10))
begin
end|
--error 1323
--error 1324
create procedure p()
begin
declare x float;
declare x int;
end|
--error 1324
--error 1325
create procedure p()
begin
declare c condition for 1064;
declare c condition for 1065;
end|
--error 1325
--error 1326
create procedure p()
begin
declare c cursor for select * from t1;
......@@ -331,18 +331,18 @@ begin
end|
# USE is not allowed
--error 1328
--error 1329
create procedure u()
use sptmp|
# Enforced standard order of declarations
--error 1329
--error 1330
create procedure p()
begin
declare c cursor for select * from t1;
declare x int;
end|
--error 1329
--error 1330
create procedure p()
begin
declare x int;
......@@ -350,7 +350,7 @@ begin
declare foo condition for sqlstate '42S99';
end|
--error 1330
--error 1331
create procedure p()
begin
declare x int;
......@@ -375,13 +375,13 @@ drop procedure bug1965|
#
# BUG#1966
#
--error 1319
--error 1320
select 1 into a|
#
# BUG#336
#
--error 1327
--error 1328
create procedure bug336(id char(16))
begin
declare x int;
......@@ -391,7 +391,7 @@ end|
#
# BUG#1654
#
--error 1306
--error 1307
create function bug1654()
returns int
return (select sum(t.data) from test.t2 t)|
......@@ -429,7 +429,7 @@ begin
fetch c1 into v1;
end|
--error 1318
--error 1319
call bug2259()|
drop procedure bug2259|
......@@ -485,7 +485,7 @@ begin
end case;
return 2;
end|
--error 1331
--error 1332
select bug3287()|
drop function bug3287|
......@@ -496,7 +496,7 @@ when 0 then
when 1 then
insert into test.t1 values (x, 1.1);
end case|
--error 1331
--error 1332
call bug3287(2)|
drop procedure bug3287|
......
......@@ -177,11 +177,11 @@ class SEL_ARG :public Sql_alloc
if (maybe_null && *min_value)
{
**min_key=1;
bzero(*min_key+1,length);
bzero(*min_key+1,length-1);
}
else
memcpy(*min_key,min_value,length+(int) maybe_null);
(*min_key)+= length+(int) maybe_null;
memcpy(*min_key,min_value,length);
(*min_key)+= length;
}
if (!(max_flag & NO_MAX_RANGE) &&
!(max_key_flag & (NO_MAX_RANGE | NEAR_MAX)))
......@@ -189,18 +189,18 @@ class SEL_ARG :public Sql_alloc
if (maybe_null && *max_value)
{
**max_key=1;
bzero(*max_key+1,length);
bzero(*max_key+1,length-1);
}
else
memcpy(*max_key,max_value,length+(int) maybe_null);
(*max_key)+= length+(int) maybe_null;
memcpy(*max_key,max_value,length);
(*max_key)+= length;
}
}
void store_min_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{
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_flag|= key_tree->min_flag;
if (key_tree->next_key_part &&
......@@ -213,7 +213,7 @@ class SEL_ARG :public Sql_alloc
void store_max_key(KEY_PART *key,char **range_key, uint *range_key_flag)
{
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_flag)|= key_tree->max_flag;
if (key_tree->next_key_part &&
......@@ -959,6 +959,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
MEM_ROOT *old_root,alloc;
SEL_TREE *tree;
KEY_PART *key_parts;
KEY *key_info;
PARAM param;
/* 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,
old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
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))
continue;
KEY *key_info= &head->key_info[idx];
if (key_info->flags & HA_FULLTEXT)
continue; // ToDo: ft-keys in non-ft ranges, if possible SerG
param.key[param.keys]=key_parts;
for (uint part=0 ; part < key_info->key_parts ; part++,key_parts++)
{
key_parts->key=param.keys;
key_parts->part=part;
key_parts->part_length= key_info->key_part[part].length;
key_parts->field= key_info->key_part[part].field;
key_parts->null_bit= key_info->key_part[part].null_bit;
if (key_parts->field->type() == FIELD_TYPE_BLOB)
key_parts->part_length+=HA_KEY_BLOB_LENGTH;
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->part= part;
key_parts->length= key_part_info->length;
key_parts->store_length= key_part_info->store_length;
key_parts->field= key_part_info->field;
key_parts->null_bit= key_part_info->null_bit;
key_parts->image_type =
(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,
else
{
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=
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,
DBUG_RETURN(0); // Can only optimize strings
offset=maybe_null;
length=key_part->part_length;
if (field->type() == FIELD_TYPE_BLOB)
length=key_part->store_length;
if (length != key_part->length + maybe_null)
{
offset+=HA_KEY_BLOB_LENGTH;
field_length=key_part->part_length-HA_KEY_BLOB_LENGTH;
/* key packed with length prefix */
offset+= HA_KEY_BLOB_LENGTH;
field_length= length - HA_KEY_BLOB_LENGTH;
}
else
{
if (length < field_length)
length=field_length; // Only if overlapping key
if (unlikely(length < field_length))
{
/*
This can only happen in a table created with UNIREG where one key
overlaps many fields
*/
length= field_length;
}
else
field_length=length;
field_length= length;
}
length+=offset;
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,
res->ptr(), res->length(),
((Item_func_like*)(param->cond))->escape,
wild_one, wild_many,
field_length,
field_length-maybe_null,
min_str+offset, max_str+offset,
&min_length, &max_length);
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,
if (field->key_type() == HA_KEYTYPE_VARTEXT)
copies= 2;
str= str2= (char*) alloc_root(param->mem_root,
(key_part->part_length+maybe_null)*copies+1);
(key_part->store_length)*copies+1);
if (!str)
DBUG_RETURN(0);
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
field->get_key_image(str+maybe_null,key_part->part_length,
field->charset(),key_part->image_type);
field->get_key_image(str+maybe_null, key_part->length,
field->charset(), key_part->image_type);
if (copies == 2)
{
/*
......@@ -1853,16 +1864,17 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
all rows between 'X' and 'X ...'
*/
uint length= uint2korr(str+maybe_null);
str2= str+ key_part->part_length + maybe_null;
str2= str+ key_part->store_length;
/* remove end space */
while (length > 0 && str[length+HA_KEY_BLOB_LENGTH+maybe_null-1] == ' ')
length--;
int2store(str+maybe_null, length);
/* Create key that is space filled */
memcpy(str2, str, length + HA_KEY_BLOB_LENGTH + maybe_null);
bfill(str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
key_part->part_length-length - HA_KEY_BLOB_LENGTH, ' ');
int2store(str2+maybe_null, key_part->part_length - HA_KEY_BLOB_LENGTH);
my_fill_8bit(field->charset(),
str2+ length+ HA_KEY_BLOB_LENGTH +maybe_null,
key_part->length-length, ' ');
int2store(str2+maybe_null, key_part->length);
}
if (!(tree=new SEL_ARG(field,str,str2)))
DBUG_RETURN(0); // out of memory
......@@ -3055,7 +3067,7 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
uint tmp_min_flag,tmp_max_flag,keynr;
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);
uint min_key_length= (uint) (tmp_min_key- param->min_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,
{
QUICK_RANGE_SELECT *quick;
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 ||
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,
return 1;
}
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);
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)
{
for (const char *end=key+length ;
key < end;
key+= key_part++->part_length)
{
if (key_part->null_bit)
key+= key_part++->store_length)
{
if (*key++)
if (key_part->null_bit && *key)
return 1;
}
}
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,
......@@ -3370,9 +3391,8 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
{
key_part->part=part;
key_part->field= key_info->key_part[part].field;
key_part->part_length= key_info->key_part[part].length;
if (key_part->field->type() == FIELD_TYPE_BLOB)
key_part->part_length+=HA_KEY_BLOB_LENGTH;
key_part->length= key_info->key_part[part].length;
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
}
if (insert_dynamic(&quick->ranges,(gptr)&range))
......@@ -3539,117 +3559,88 @@ int QUICK_RANGE_SELECT::get_next()
for (;;)
{
int result;
key_range start_key, end_key;
if (range)
{ // Already read through key
result=((range->flag & (EQ_RANGE | GEOM_FLAG)) ?
file->index_next_same(record, (byte*) range->min_key,
range->min_length) :
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)
// Already read through key
result= file->read_range_next(test(range->flag & EQ_RANGE));
if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
}
if (!cur_range)
range= *(cur_range= (QUICK_RANGE**)ranges.buffer);
range= *(cur_range= (QUICK_RANGE**) ranges.buffer);
else
range=
(cur_range == ((QUICK_RANGE**)ranges.buffer + ranges.elements - 1))?
NULL: *(++cur_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
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
{
int local_error;
if ((local_error=file->index_first(record)))
DBUG_RETURN(local_error); // Empty table
if (cmp_next(range) == 0)
DBUG_RETURN(0);
range=0; // No matching records; go to next range
continue;
}
if ((result = file->index_read(record,
(byte*) (range->min_key +
test(range->flag & GEOM_FLAG)),
range->min_length,
(range->flag & NEAR_MIN) ?
HA_READ_AFTER_KEY:
start_key.key= (const byte*) range->min_key;
start_key.length= range->min_length;
start_key.flag= ((range->flag & NEAR_MIN) ? HA_READ_AFTER_KEY :
(range->flag & EQ_RANGE) ?
HA_READ_KEY_EXACT :
HA_READ_KEY_OR_NEXT)))
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT);
end_key.key= (const byte*) range->max_key;
end_key.length= range->max_length;
/*
We use READ_AFTER_KEY here because if we are reading on a key
prefix we want to find all keys with this prefix
*/
end_key.flag= (range->flag & NEAR_MAX ? HA_READ_BEFORE_KEY :
HA_READ_AFTER_KEY);
{
if (result != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(result);
range=0; // Not found, to next range
continue;
}
if (cmp_next(range) == 0)
{
result= file->read_range_first(range->min_length ? &start_key : 0,
range->max_length ? &end_key : 0,
sorted);
if (range->flag == (UNIQUE_RANGE | EQ_RANGE))
range=0; // Stop searching
DBUG_RETURN(0); // Found key is in range
}
range=0; // To next range
if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
range=0; // No matching rows; go to next range
}
}
/*
Compare if found key is over max-value
Returns 0 if key <= range->max_key
*/
/* Get next for geometrical indexes */
int QUICK_RANGE_SELECT::cmp_next(QUICK_RANGE *range_arg)
int QUICK_RANGE_SELECT_GEOM::get_next()
{
if (range_arg->flag & NO_MAX_RANGE)
return 0; /* key can't be to large */
DBUG_ENTER("QUICK_RANGE_SELECT_GEOM::get_next");
KEY_PART *key_part=key_parts;
for (char *key=range_arg->max_key, *end=key+range_arg->max_length;
key < end;
key+= key_part++->part_length)
{
int cmp;
if (key_part->null_bit)
for (;;)
{
if (*key++)
int result;
if (range)
{
if (!key_part->field->is_null())
return 1;
continue;
}
else if (key_part->field->is_null())
return 0;
// Already read through key
result= file->index_next_same(record, (byte*) range->min_key,
range->min_length);
if (result != HA_ERR_END_OF_FILE)
DBUG_RETURN(result);
}
if ((cmp=key_part->field->key_cmp((byte*) key, key_part->part_length)) < 0)
return 0;
if (cmp > 0)
return 1;
if (!cur_range)
range= *(cur_range= (QUICK_RANGE**) ranges.buffer);
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()
}
/*
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).
*/
......@@ -3843,15 +3875,18 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg)
return 0; /* key can't be to small */
KEY_PART *key_part = key_parts;
uint store_length;
for (char *key = range_arg->min_key, *end = key + range_arg->min_length;
key < end;
key += key_part++->part_length)
key += store_length, key_part++)
{
int cmp;
store_length= key_part->store_length;
if (key_part->null_bit)
{
// this key part allows null values; NULL is lower than everything else
if (*key++)
if (*key)
{
// the range is expecting a null value
if (!key_part->field->is_null())
......@@ -3860,9 +3895,11 @@ int QUICK_RANGE_SELECT::cmp_prev(QUICK_RANGE *range_arg)
}
else if (key_part->field->is_null())
return 1; // null -- outside the range
key++;
store_length--;
}
if ((cmp = key_part->field->key_cmp((byte*) key,
key_part->part_length)) > 0)
key_part->length)) > 0)
return 0;
if (cmp < 0)
return 1;
......@@ -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,
uint used_key_parts)
{
uint offset,end;
uint offset, end;
KEY_PART *key_part = key_parts,
*key_part_end= key_part+used_key_parts;
for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ;
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,
(char*) range_arg->max_key+offset,
key_part->part_length + null_length))
{
offset+=null_length;
key_part->store_length))
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
// Range doesn't cover NULL. This is ok if there is no more null parts
break;
......@@ -3948,33 +3982,34 @@ static void
print_key(KEY_PART *key_part,const char *key,uint used_length)
{
char buff[1024];
const char *key_end= key+used_length;
String tmp(buff,sizeof(buff),&my_charset_bin);
uint store_length;
for (uint length=0;
length < used_length ;
length+=key_part->part_length, key+=key_part->part_length, key_part++)
for (; key < key_end; key+=store_length, key_part++)
{
Field *field=key_part->field;
if (length != 0)
fputc('/',DBUG_FILE);
Field *field= key_part->field;
store_length= key_part->store_length;
if (field->real_maybe_null())
{
length++; // null byte is not in part_length
if (*key++)
if (*key)
{
fwrite("NULL",sizeof(char),4,DBUG_FILE);
continue;
}
key++; // Skip null byte
store_length--;
}
field->set_key_image((char*) key,key_part->part_length -
((field->type() == FIELD_TYPE_BLOB) ?
HA_KEY_BLOB_LENGTH : 0),
field->charset());
field->val_str(&tmp,&tmp);
field->set_key_image((char*) key, key_part->length, field->charset());
field->val_str(&tmp);
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,
const key_map *needed_reg)
{
......@@ -3994,6 +4029,7 @@ static void print_quick_sel_imerge(QUICK_INDEX_MERGE_SELECT *quick,
DBUG_VOID_RETURN;
}
void print_quick_sel_range(QUICK_RANGE_SELECT *quick,
const key_map *needed_reg)
{
......
......@@ -35,7 +35,7 @@
typedef struct st_key_part {
uint16 key,part,part_length;
uint16 key,part, store_length, length;
uint8 null_bit;
Field *field;
Field::imagetype image_type;
......@@ -74,6 +74,7 @@ class QUICK_RANGE :public Sql_alloc {
class QUICK_SELECT_I
{
public:
bool sorted;
ha_rows records; /* estimate of # of records to be retrieved */
double read_time; /* time to perform this retrieval */
TABLE *head;
......@@ -170,6 +171,17 @@ class QUICK_RANGE_SELECT : public QUICK_SELECT_I
};
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.
......
......@@ -464,13 +464,12 @@ void init_slave_skip_errors(const char* arg)
}
void st_relay_log_info::inc_group_relay_log_pos(ulonglong val,
ulonglong log_pos,
bool skip_lock)
void st_relay_log_info::inc_group_relay_log_pos(ulonglong log_pos,
bool skip_lock=0)
{
if (!skip_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;
strmake(group_relay_log_name,event_relay_log_name,
sizeof(group_relay_log_name)-1);
......@@ -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
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 MYSQL_VERSION_ID < 50000
......@@ -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;
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);
#else
group_master_log_pos= log_pos+ val;
group_master_log_pos= log_pos;
#endif /* MYSQL_VERSION_ID < 5000 */
}
pthread_cond_broadcast(&data_cond);
......@@ -2540,13 +2561,13 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
goto err;
}
int cmp_result;
/* The "compare and wait" main loop */
while (!thd->killed &&
init_abort_pos_wait == abort_pos_wait &&
slave_running)
{
bool pos_reached;
int cmp_result= 0;
/*
group_master_log_name can be "", if we are just after a fresh
......
......@@ -283,12 +283,14 @@ typedef struct st_relay_log_info
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,
longlong timeout);
void close_temporary_tables();
......
......@@ -206,8 +206,8 @@ sp_head::operator delete(void *ptr, size_t size)
}
sp_head::sp_head()
: Sql_alloc(), m_has_return(FALSE), m_simple_case(FALSE),
m_multi_results(FALSE), m_free_list(NULL), m_returns_cs(NULL)
: Sql_alloc(), m_returns_cs(NULL), m_has_return(FALSE), m_simple_case(FALSE),
m_multi_results(FALSE), m_free_list(NULL)
{
DBUG_ENTER("sp_head::sp_head");
......
......@@ -3434,6 +3434,7 @@ mysql_execute_command(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
st_sp_security_context save_ctx;
#endif
ha_rows select_limit;
uint smrx;
LINT_INIT(smrx);
......@@ -3468,9 +3469,12 @@ mysql_execute_command(THD *thd)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_change_security_context(thd, sp, &save_ctx);
#endif
select_limit= thd->variables.select_limit;
thd->variables.select_limit= HA_POS_ERROR;
res= sp->execute_procedure(thd, &lex->value_list);
thd->variables.select_limit= select_limit;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_restore_security_context(thd, sp, &save_ctx);
#endif
......
......@@ -6976,7 +6976,7 @@ static void test_explain_bug()
"","","",NAME_LEN,0);
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,
"","","",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