Merge witty.:/Users/mattiasj/clones/mysql-5.1-bug31931.2

into  witty.:/Users/mattiasj/clones/topush-51


mysql-test/r/partition.result:
  Auto merged
mysql-test/suite/ndb/r/ndb_partition_key.result:
  Auto merged
mysql-test/suite/ndb/t/ndb_partition_key.test:
  Auto merged
mysql-test/t/partition.test:
  Auto merged
sql/sql_partition.cc:
  Auto merged
sql/partition_info.cc:
  SCCS merged
This commit is contained in:
unknown 2008-02-24 16:46:35 +01:00
commit 1864caeafc
14 changed files with 551 additions and 5694 deletions

View file

@ -419,41 +419,167 @@ char *partition_info::has_unique_names()
/*
Check that all partitions use the same storage engine.
This is currently a limitation in this version.
Check that the partition/subpartition is setup to use the correct
storage engine
SYNOPSIS
check_engine_condition()
p_elem Partition element
table_engine_set Have user specified engine on table level
inout::engine_type Current engine used
inout::first Is it first partition
RETURN VALUE
TRUE Failed check
FALSE Ok
DESCRIPTION
Specified engine for table and partitions p0 and pn
Must be correct both on CREATE and ALTER commands
table p0 pn res (0 - OK, 1 - FAIL)
- - - 0
- - x 1
- x - 1
- x x 0
x - - 0
x - x 0
x x - 0
x x x 0
i.e:
- All subpartitions must use the same engine
AND it must be the same as the partition.
- All partitions must use the same engine
AND it must be the same as the table.
- if one does NOT specify an engine on the table level
then one must either NOT specify any engine on any
partition/subpartition OR for ALL partitions/subpartitions
Note:
When ALTER a table, the engines are already set for all levels
(table, all partitions and subpartitions). So if one want to
change the storage engine, one must specify it on the table level
*/
static bool check_engine_condition(partition_element *p_elem,
bool table_engine_set,
handlerton **engine_type,
bool *first)
{
DBUG_ENTER("check_engine_condition");
DBUG_PRINT("enter", ("p_eng %u t_eng %u t_eng_set %u first %u state %u",
ha_legacy_type(p_elem->engine_type),
ha_legacy_type(*engine_type),
table_engine_set, *first, p_elem->part_state));
if (*first && !table_engine_set)
{
*engine_type= p_elem->engine_type;
DBUG_PRINT("info", ("setting table_engine = %u",
ha_legacy_type(*engine_type)));
}
*first= FALSE;
if ((table_engine_set &&
(p_elem->engine_type != (*engine_type) &&
p_elem->engine_type)) ||
(!table_engine_set &&
p_elem->engine_type != (*engine_type)))
{
DBUG_RETURN(TRUE);
}
else
{
DBUG_RETURN(FALSE);
}
}
/*
Check engine mix that it is correct
Current limitation is that all partitions and subpartitions
must use the same storage engine.
SYNOPSIS
check_engine_mix()
engine_array An array of engine identifiers
no_parts Total number of partitions
inout::engine_type Current engine used
table_engine_set Have user specified engine on table level
RETURN VALUE
TRUE Error, mixed engines
FALSE Ok, no mixed engines
TRUE Error, mixed engines
FALSE Ok, no mixed engines
DESCRIPTION
Current check verifies only that all handlers are the same.
Later this check will be more sophisticated.
(specified partition handler ) specified table handler
(NDB, NDB) NDB OK
(MYISAM, MYISAM) - OK
(MYISAM, -) - NOT OK
(MYISAM, -) MYISAM OK
(- , MYISAM) - NOT OK
(- , -) MYISAM OK
(-,-) - OK
(NDB, MYISAM) * NOT OK
*/
bool partition_info::check_engine_mix(handlerton **engine_array, uint no_parts)
bool partition_info::check_engine_mix(handlerton *engine_type,
bool table_engine_set)
{
uint i= 0;
handlerton *old_engine_type= engine_type;
bool first= TRUE;
uint no_parts= partitions.elements;
DBUG_ENTER("partition_info::check_engine_mix");
do
DBUG_PRINT("info", ("in: engine_type = %u, table_engine_set = %u",
ha_legacy_type(engine_type),
table_engine_set));
if (no_parts)
{
if (engine_array[i] != engine_array[0])
List_iterator<partition_element> part_it(partitions);
uint i= 0;
do
{
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
} while (++i < no_parts);
if (engine_array[0]->flags & HTON_NO_PARTITION)
partition_element *part_elem= part_it++;
DBUG_PRINT("info", ("part = %d engine = %d table_engine_set %u",
i, ha_legacy_type(part_elem->engine_type),
table_engine_set));
if (is_sub_partitioned() &&
part_elem->subpartitions.elements)
{
uint no_subparts= part_elem->subpartitions.elements;
uint j= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions);
do
{
partition_element *sub_elem= sub_it++;
DBUG_PRINT("info", ("sub = %d engine = %u table_engie_set %u",
j, ha_legacy_type(sub_elem->engine_type),
table_engine_set));
if (check_engine_condition(sub_elem, table_engine_set,
&engine_type, &first))
goto error;
} while (++j < no_subparts);
/* ensure that the partition also has correct engine */
if (check_engine_condition(part_elem, table_engine_set,
&engine_type, &first))
goto error;
}
else if (check_engine_condition(part_elem, table_engine_set,
&engine_type, &first))
goto error;
} while (++i < no_parts);
}
DBUG_PRINT("info", ("engine_type = %u",
ha_legacy_type(engine_type)));
if (!engine_type)
engine_type= old_engine_type;
if (engine_type->flags & HTON_NO_PARTITION)
{
my_error(ER_PARTITION_MERGE_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
DBUG_PRINT("info", ("out: engine_type = %u",
ha_legacy_type(engine_type)));
DBUG_ASSERT(engine_type != partition_hton);
DBUG_RETURN(FALSE);
error:
/*
Mixed engines not yet supported but when supported it will need
the partition handler
*/
DBUG_RETURN(TRUE);
}
@ -726,12 +852,12 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
handler *file, HA_CREATE_INFO *info,
bool check_partition_function)
{
handlerton **engine_array= NULL;
uint part_count= 0;
handlerton *table_engine= default_engine_type;
uint i, tot_partitions;
bool result= TRUE;
bool result= TRUE, table_engine_set;
char *same_name;
DBUG_ENTER("partition_info::check_partition_info");
DBUG_ASSERT(default_engine_type != partition_hton);
if (check_partition_function)
{
@ -777,23 +903,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
goto end;
}
/*
if NOT specified ENGINE = <engine>:
If Create, always use create_info->db_type
else, use previous tables db_type
either ALL or NONE partition should be set to
default_engine_type when not table_engine_set
Note: after a table is created its storage engines for
the table and all partitions/subpartitions are set.
So when ALTER it is already set on table level
*/
if (thd->lex->create_info.used_fields & HA_CREATE_USED_ENGINE)
{
table_engine_set= TRUE;
table_engine= thd->lex->create_info.db_type;
}
else
{
table_engine_set= FALSE;
if (thd->lex->sql_command != SQLCOM_CREATE_TABLE)
{
table_engine_set= TRUE;
DBUG_ASSERT(table_engine && table_engine != partition_hton);
}
}
if ((same_name= has_unique_names()))
{
my_error(ER_SAME_NAME_PARTITION, MYF(0), same_name);
goto end;
}
engine_array= (handlerton**)my_malloc(tot_partitions * sizeof(handlerton *),
MYF(MY_WME));
if (unlikely(!engine_array))
goto end;
i= 0;
{
List_iterator<partition_element> part_it(partitions);
uint no_parts_not_set= 0;
uint prev_no_subparts_not_set= no_subparts + 1;
do
{
partition_element *part_elem= part_it++;
if (part_elem->engine_type == NULL)
{
no_parts_not_set++;
part_elem->engine_type= default_engine_type;
}
#ifdef HAVE_READLINK
if (!my_use_symdir || (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE))
#endif
@ -814,13 +966,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
my_error(ER_WRONG_PARTITION_NAME, MYF(0));
goto end;
}
DBUG_PRINT("info", ("engine = %d",
ha_legacy_type(part_elem->engine_type)));
engine_array[part_count++]= part_elem->engine_type;
DBUG_PRINT("info", ("part = %d engine = %d",
i, ha_legacy_type(part_elem->engine_type)));
}
else
{
uint j= 0;
uint no_subparts_not_set= 0;
List_iterator<partition_element> sub_it(part_elem->subpartitions);
do
{
@ -832,19 +984,49 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
goto end;
}
if (sub_elem->engine_type == NULL)
{
sub_elem->engine_type= default_engine_type;
DBUG_PRINT("info", ("engine = %u",
ha_legacy_type(sub_elem->engine_type)));
engine_array[part_count++]= sub_elem->engine_type;
no_subparts_not_set++;
}
DBUG_PRINT("info", ("part = %d sub = %d engine = %u",
i, j, ha_legacy_type(sub_elem->engine_type)));
} while (++j < no_subparts);
if (prev_no_subparts_not_set == (no_subparts + 1))
prev_no_subparts_not_set= no_subparts_not_set;
if (!table_engine_set &&
prev_no_subparts_not_set == no_subparts_not_set &&
no_subparts_not_set != 0 &&
no_subparts_not_set != no_subparts)
{
DBUG_PRINT("info", ("no_subparts_not_set = %u no_subparts = %u",
no_subparts_not_set, no_subparts));
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
}
} while (++i < no_parts);
if (!table_engine_set &&
no_parts_not_set != 0 &&
no_parts_not_set != no_parts)
{
DBUG_PRINT("info", ("no_parts_not_set = %u no_parts = %u",
no_parts_not_set, no_subparts));
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
}
if (unlikely(partition_info::check_engine_mix(engine_array, part_count)))
if (unlikely(check_engine_mix(table_engine, table_engine_set)))
{
my_error(ER_MIX_HANDLER_ERROR, MYF(0));
goto end;
}
if (table_engine == partition_hton)
DBUG_PRINT("info", ("Table engine set to partition_hton"));
DBUG_ASSERT(default_engine_type == table_engine);
if (eng_type)
*eng_type= (handlerton*)engine_array[0];
*eng_type= table_engine;
/*
We need to check all constant expressions that they are of the correct
@ -860,7 +1042,6 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
}
result= FALSE;
end:
my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR));
DBUG_RETURN(result);
}