Commit 098ae02a authored by unknown's avatar unknown

Merge baker@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into  zim.tangent.org:/home/brian/mysql/archive-5.1

parents dac63fb8 48b224fa
...@@ -278,3 +278,25 @@ partition p1 values in (14) ...@@ -278,3 +278,25 @@ partition p1 values in (14)
insert into t1 values (10,1); insert into t1 values (10,1);
ERROR HY000: Table has no partition for value 11 ERROR HY000: Table has no partition for value 11
drop table t1; drop table t1;
create table t1 (f1 integer,f2 integer, f3 varchar(10), primary key(f1,f2))
partition by range(f1) subpartition by hash(f2) subpartitions 2
(partition p1 values less than (0),
partition p2 values less than (2),
partition p3 values less than (2147483647));
insert into t1 values(10,10,'10');
insert into t1 values(2,2,'2');
select * from t1 where f1 = 2;
f1 f2 f3
2 2 2
drop table t1;
create table t1 (f1 integer,f2 integer, unique index(f1))
partition by range(f1 div 2)
subpartition by hash(f1) subpartitions 2
(partition partb values less than (2),
partition parte values less than (4),
partition partf values less than (10000));
insert into t1 values(10,1);
select * from t1 where f1 = 10;
f1 f2
10 1
drop table t1;
...@@ -155,11 +155,11 @@ Pos Instruction ...@@ -155,11 +155,11 @@ Pos Instruction
0 stmt 9 "drop temporary table if exists sudoku..." 0 stmt 9 "drop temporary table if exists sudoku..."
1 stmt 1 "create temporary table sudoku_work ( ..." 1 stmt 1 "create temporary table sudoku_work ( ..."
2 stmt 1 "create temporary table sudoku_schedul..." 2 stmt 1 "create temporary table sudoku_schedul..."
3 stmt 94 "call sudoku_init(" 3 stmt 95 "call sudoku_init("
4 jump_if_not 7(8) p_naive@0 4 jump_if_not 7(8) p_naive@0
5 stmt 4 "update sudoku_work set cnt = 0 where ..." 5 stmt 4 "update sudoku_work set cnt = 0 where ..."
6 jump 8 6 jump 8
7 stmt 94 "call sudoku_count(" 7 stmt 95 "call sudoku_count("
8 stmt 6 "insert into sudoku_schedule (row,col)..." 8 stmt 6 "insert into sudoku_schedule (row,col)..."
9 set v_scounter@2 0 9 set v_scounter@2 0
10 set v_i@3 1 10 set v_i@3 1
......
...@@ -33,7 +33,6 @@ rpl_until : Unstable test case, bug#15886 ...@@ -33,7 +33,6 @@ rpl_until : Unstable test case, bug#15886
sp-goto : GOTO is currently is disabled - will be fixed in the future sp-goto : GOTO is currently is disabled - will be fixed in the future
subselect : Bug#15706 (ps mode) [PATCH PENDING] subselect : Bug#15706 (ps mode) [PATCH PENDING]
rpl_ndb_log : result not deterministic rpl_ndb_log : result not deterministic
sp-code : Bug #17360
binlog_row_mix_innodb_myisam : Bug #17386 binlog_row_mix_innodb_myisam : Bug #17386
binlog_row_insert_select : Bug #17385 binlog_row_insert_select : Bug #17385
rpl_row_basic_2myisam : Bug #17385 rpl_row_basic_2myisam : Bug #17385
......
...@@ -353,3 +353,30 @@ insert into t1 values (10,1); ...@@ -353,3 +353,30 @@ insert into t1 values (10,1);
drop table t1; drop table t1;
#
# Bug#16901 Partitions: crash, SELECT, column of part.
# function=first column of primary key
#
create table t1 (f1 integer,f2 integer, f3 varchar(10), primary key(f1,f2))
partition by range(f1) subpartition by hash(f2) subpartitions 2
(partition p1 values less than (0),
partition p2 values less than (2),
partition p3 values less than (2147483647));
insert into t1 values(10,10,'10');
insert into t1 values(2,2,'2');
select * from t1 where f1 = 2;
drop table t1;
#
# Bug #16907 Partitions: crash, SELECT goes into last partition, UNIQUE INDEX
#
create table t1 (f1 integer,f2 integer, unique index(f1))
partition by range(f1 div 2)
subpartition by hash(f1) subpartitions 2
(partition partb values less than (2),
partition parte values less than (4),
partition partf values less than (10000));
insert into t1 values(10,1);
select * from t1 where f1 = 10;
drop table t1;
...@@ -2198,6 +2198,7 @@ int ha_ndbcluster::full_table_scan(byte *buf) ...@@ -2198,6 +2198,7 @@ int ha_ndbcluster::full_table_scan(byte *buf)
int res; int res;
NdbScanOperation *op; NdbScanOperation *op;
NdbTransaction *trans= m_active_trans; NdbTransaction *trans= m_active_trans;
part_id_range part_spec;
DBUG_ENTER("full_table_scan"); DBUG_ENTER("full_table_scan");
DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname)); DBUG_PRINT("enter", ("Starting new scan on %s", m_tabname));
...@@ -2209,6 +2210,35 @@ int ha_ndbcluster::full_table_scan(byte *buf) ...@@ -2209,6 +2210,35 @@ int ha_ndbcluster::full_table_scan(byte *buf)
op->readTuples(lm, 0, parallelism)) op->readTuples(lm, 0, parallelism))
ERR_RETURN(trans->getNdbError()); ERR_RETURN(trans->getNdbError());
m_active_cursor= op; m_active_cursor= op;
if (m_use_partition_function)
{
part_spec.start_part= 0;
part_spec.end_part= get_tot_partitions(m_part_info) - 1;
prune_partition_set(table, &part_spec);
DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
we can return HA_ERR_END_OF_FILE
If partition pruning has found exactly one partition in set
we can optimize scan to run towards that partition only.
*/
if (part_spec.start_part > part_spec.end_part)
{
DBUG_RETURN(HA_ERR_END_OF_FILE);
}
else if (part_spec.start_part == part_spec.end_part)
{
/*
Only one partition is required to scan, if sorted is required we
don't need it any more since output from one ordered partitioned
index is always sorted.
*/
m_active_cursor->setPartitionId(part_spec.start_part);
}
}
if (generate_scan_filter(m_cond_stack, op)) if (generate_scan_filter(m_cond_stack, op))
DBUG_RETURN(ndb_err(trans)); DBUG_RETURN(ndb_err(trans));
if ((res= define_read_attrs(buf, op))) if ((res= define_read_attrs(buf, op)))
...@@ -3012,6 +3042,14 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, ...@@ -3012,6 +3042,14 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
if (m_use_partition_function) if (m_use_partition_function)
{ {
get_partition_set(table, buf, active_index, start_key, &part_spec); get_partition_set(table, buf, active_index, start_key, &part_spec);
DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
we can return HA_ERR_END_OF_FILE
If partition pruning has found exactly one partition in set
we can optimize scan to run towards that partition only.
*/
if (part_spec.start_part > part_spec.end_part) if (part_spec.start_part > part_spec.end_part)
{ {
DBUG_RETURN(HA_ERR_END_OF_FILE); DBUG_RETURN(HA_ERR_END_OF_FILE);
...@@ -3026,6 +3064,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key, ...@@ -3026,6 +3064,7 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
sorted= FALSE; sorted= FALSE;
} }
} }
m_write_op= FALSE; m_write_op= FALSE;
switch (type){ switch (type){
case PRIMARY_KEY_ORDERED_INDEX: case PRIMARY_KEY_ORDERED_INDEX:
...@@ -7003,6 +7042,12 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p, ...@@ -7003,6 +7042,12 @@ ha_ndbcluster::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
get_partition_set(table, curr, active_index, get_partition_set(table, curr, active_index,
&multi_range_curr->start_key, &multi_range_curr->start_key,
&part_spec); &part_spec);
DBUG_PRINT("info", ("part_spec.start_part = %u, part_spec.end_part = %u",
part_spec.start_part, part_spec.end_part));
/*
If partition pruning has found no partition in set
we can skip this scan
*/
if (part_spec.start_part > part_spec.end_part) if (part_spec.start_part > part_spec.end_part)
{ {
/* /*
......
...@@ -1126,6 +1126,7 @@ char *generate_partition_syntax(partition_info *part_info, ...@@ -1126,6 +1126,7 @@ char *generate_partition_syntax(partition_info *part_info,
uint *buf_length, bool use_sql_alloc, uint *buf_length, bool use_sql_alloc,
bool write_all); bool write_all);
bool partition_key_modified(TABLE *table, List<Item> &fields); bool partition_key_modified(TABLE *table, List<Item> &fields);
void prune_partition_set(const TABLE *table, part_id_range *part_spec);
void get_partition_set(const TABLE *table, byte *buf, const uint index, void get_partition_set(const TABLE *table, byte *buf, const uint index,
const key_range *key_spec, const key_range *key_spec,
part_id_range *part_spec); part_id_range *part_spec);
......
...@@ -3606,6 +3606,51 @@ void get_full_part_id_from_key(const TABLE *table, byte *buf, ...@@ -3606,6 +3606,51 @@ void get_full_part_id_from_key(const TABLE *table, byte *buf,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Prune the set of partitions to use in query
SYNOPSIS
prune_partition_set()
table The table object
out:part_spec Contains start part, end part
DESCRIPTION
This function is called to prune the range of partitions to scan by
checking the used_partitions bitmap.
If start_part > end_part at return it means no partition needs to be
scanned. If start_part == end_part it always means a single partition
needs to be scanned.
RETURN VALUE
part_spec
*/
void prune_partition_set(const TABLE *table, part_id_range *part_spec)
{
int last_partition= -1;
uint i;
partition_info *part_info= table->part_info;
DBUG_ENTER("prune_partition_set");
for (i= part_spec->start_part; i <= part_spec->end_part; i++)
{
if (bitmap_is_set(&(part_info->used_partitions), i))
{
DBUG_PRINT("info", ("Partition %d is set", i));
if (last_partition == -1)
/* First partition found in set and pruned bitmap */
part_spec->start_part= i;
last_partition= i;
}
}
if (last_partition == -1)
/* No partition found in pruned bitmap */
part_spec->start_part= part_spec->end_part + 1;
else //if (last_partition != -1)
part_spec->end_part= last_partition;
DBUG_VOID_RETURN;
}
/* /*
Get the set of partitions to use in query. Get the set of partitions to use in query.
...@@ -3669,6 +3714,10 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index, ...@@ -3669,6 +3714,10 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
is needed. is needed.
*/ */
get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec); get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
/*
Check if range can be adjusted by looking in used_partitions
*/
prune_partition_set(table, part_spec);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
else if (is_sub_partitioned(part_info)) else if (is_sub_partitioned(part_info))
...@@ -3711,6 +3760,10 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index, ...@@ -3711,6 +3760,10 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
*/ */
get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec); get_full_part_id_from_key(table,buf,key_info,key_spec,part_spec);
clear_indicator_in_key_fields(key_info); clear_indicator_in_key_fields(key_info);
/*
Check if range can be adjusted by looking in used_partitions
*/
prune_partition_set(table, part_spec);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
else if (is_sub_partitioned(part_info)) else if (is_sub_partitioned(part_info))
...@@ -3754,7 +3807,7 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index, ...@@ -3754,7 +3807,7 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
subpartitions. This is a range without holes. subpartitions. This is a range without holes.
*/ */
DBUG_ASSERT(sub_part == no_parts); DBUG_ASSERT(sub_part == no_parts);
part_spec->start_part= part_part * part_info->no_parts; part_spec->start_part= part_part * part_info->no_subparts;
part_spec->end_part= part_spec->start_part+part_info->no_subparts - 1; part_spec->end_part= part_spec->start_part+part_info->no_subparts - 1;
} }
else else
...@@ -3770,10 +3823,13 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index, ...@@ -3770,10 +3823,13 @@ void get_partition_set(const TABLE *table, byte *buf, const uint index,
} }
if (found_part_field) if (found_part_field)
clear_indicator_in_key_fields(key_info); clear_indicator_in_key_fields(key_info);
/*
Check if range can be adjusted by looking in used_partitions
*/
prune_partition_set(table, part_spec);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/* /*
If the table is partitioned we will read the partition info into the If the table is partitioned we will read the partition info into the
.frm file here. .frm file here.
...@@ -6009,7 +6065,10 @@ static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter) ...@@ -6009,7 +6065,10 @@ static uint32 get_next_partition_via_walking(PARTITION_ITERATOR *part_iter)
field->store(part_iter->field_vals.start, FALSE); field->store(part_iter->field_vals.start, FALSE);
part_iter->field_vals.start++; part_iter->field_vals.start++;
longlong dummy; longlong dummy;
if (!part_iter->part_info->get_partition_id(part_iter->part_info, if (is_sub_partitioned(part_iter->part_info) &&
!part_iter->part_info->get_part_partition_id(part_iter->part_info,
&part_id, &dummy) ||
!part_iter->part_info->get_partition_id(part_iter->part_info,
&part_id, &dummy)) &part_id, &dummy))
return part_id; return part_id;
} }
......
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