mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
5.5 merge
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2005, 2011, Oracle and/or its affiliates.
|
||||
/* Copyright (c) 2005, 2013, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2013, Monty Program Ab.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -87,7 +87,9 @@ const LEX_STRING partition_keywords[]=
|
||||
{ C_STRING_WITH_LEN("KEY") },
|
||||
{ C_STRING_WITH_LEN("MAXVALUE") },
|
||||
{ C_STRING_WITH_LEN("LINEAR ") },
|
||||
{ C_STRING_WITH_LEN(" COLUMNS") }
|
||||
{ C_STRING_WITH_LEN(" COLUMNS") },
|
||||
{ C_STRING_WITH_LEN("ALGORITHM") }
|
||||
|
||||
};
|
||||
static const char *part_str= "PARTITION";
|
||||
static const char *sub_str= "SUB";
|
||||
@ -368,7 +370,7 @@ int get_parts_for_update(const uchar *old_data, uchar *new_data,
|
||||
longlong old_func_value;
|
||||
DBUG_ENTER("get_parts_for_update");
|
||||
|
||||
DBUG_ASSERT(new_data == rec0);
|
||||
DBUG_ASSERT(new_data == rec0); // table->record[0]
|
||||
set_field_ptr(part_field_array, old_data, rec0);
|
||||
error= part_info->get_partition_id(part_info, old_part_id,
|
||||
&old_func_value);
|
||||
@ -526,12 +528,12 @@ static bool set_up_field_array(TABLE *table,
|
||||
}
|
||||
if (num_fields > MAX_REF_PARTS)
|
||||
{
|
||||
char *ptr;
|
||||
char *err_str;
|
||||
if (is_sub_part)
|
||||
ptr= (char*)"subpartition function";
|
||||
err_str= (char*)"subpartition function";
|
||||
else
|
||||
ptr= (char*)"partition function";
|
||||
my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0), ptr);
|
||||
err_str= (char*)"partition function";
|
||||
my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0), err_str);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
if (num_fields == 0)
|
||||
@ -2339,6 +2341,58 @@ end:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Add 'KEY' word, with optional 'ALGORTIHM = N'.
|
||||
|
||||
@param fptr File to write to.
|
||||
@param part_info partition_info holding the used key_algorithm
|
||||
@param current_comment_start NULL, or comment string encapsulating the
|
||||
PARTITION BY clause.
|
||||
|
||||
@return Operation status.
|
||||
@retval 0 Success
|
||||
@retval != 0 Failure
|
||||
*/
|
||||
|
||||
static int add_key_with_algorithm(File fptr, partition_info *part_info,
|
||||
const char *current_comment_start)
|
||||
{
|
||||
int err= 0;
|
||||
err+= add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
|
||||
|
||||
/*
|
||||
current_comment_start is given when called from SHOW CREATE TABLE,
|
||||
Then only add ALGORITHM = 1, not the default 2 or non-set 0!
|
||||
For .frm current_comment_start is NULL, then add ALGORITHM if != 0.
|
||||
*/
|
||||
if (part_info->key_algorithm == partition_info::KEY_ALGORITHM_51 || // SHOW
|
||||
(!current_comment_start && // .frm
|
||||
(part_info->key_algorithm != partition_info::KEY_ALGORITHM_NONE)))
|
||||
{
|
||||
/* If we already are within a comment, end that comment first. */
|
||||
if (current_comment_start)
|
||||
err+= add_string(fptr, "*/ ");
|
||||
err+= add_string(fptr, "/*!50531 ");
|
||||
err+= add_part_key_word(fptr, partition_keywords[PKW_ALGORITHM].str);
|
||||
err+= add_equal(fptr);
|
||||
err+= add_space(fptr);
|
||||
err+= add_int(fptr, part_info->key_algorithm);
|
||||
err+= add_space(fptr);
|
||||
err+= add_string(fptr, "*/ ");
|
||||
if (current_comment_start)
|
||||
{
|
||||
/* Skip new line. */
|
||||
if (current_comment_start[0] == '\n')
|
||||
current_comment_start++;
|
||||
err+= add_string(fptr, current_comment_start);
|
||||
err+= add_space(fptr);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Generate the partition syntax from the partition data structure.
|
||||
Useful for support of generating defaults, SHOW CREATE TABLES
|
||||
@ -2383,7 +2437,8 @@ char *generate_partition_syntax(partition_info *part_info,
|
||||
bool use_sql_alloc,
|
||||
bool show_partition_options,
|
||||
HA_CREATE_INFO *create_info,
|
||||
Alter_info *alter_info)
|
||||
Alter_info *alter_info,
|
||||
const char *current_comment_start)
|
||||
{
|
||||
uint i,j, tot_num_parts, num_subparts;
|
||||
partition_element *part_elem;
|
||||
@ -2417,7 +2472,8 @@ char *generate_partition_syntax(partition_info *part_info,
|
||||
err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
|
||||
if (part_info->list_of_part_fields)
|
||||
{
|
||||
err+= add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
|
||||
err+= add_key_with_algorithm(fptr, part_info,
|
||||
current_comment_start);
|
||||
err+= add_part_field_list(fptr, part_info->part_field_list);
|
||||
}
|
||||
else
|
||||
@ -2457,8 +2513,9 @@ char *generate_partition_syntax(partition_info *part_info,
|
||||
err+= add_string(fptr, partition_keywords[PKW_LINEAR].str);
|
||||
if (part_info->list_of_subpart_fields)
|
||||
{
|
||||
add_part_key_word(fptr, partition_keywords[PKW_KEY].str);
|
||||
add_part_field_list(fptr, part_info->subpart_field_list);
|
||||
err+= add_key_with_algorithm(fptr, part_info,
|
||||
current_comment_start);
|
||||
err+= add_part_field_list(fptr, part_info->subpart_field_list);
|
||||
}
|
||||
else
|
||||
err+= add_part_key_word(fptr, partition_keywords[PKW_HASH].str);
|
||||
@ -2667,10 +2724,82 @@ static uint32 calculate_key_value(Field **field_array)
|
||||
{
|
||||
ulong nr1= 1;
|
||||
ulong nr2= 4;
|
||||
bool use_51_hash;
|
||||
use_51_hash= test((*field_array)->table->part_info->key_algorithm ==
|
||||
partition_info::KEY_ALGORITHM_51);
|
||||
|
||||
do
|
||||
{
|
||||
Field *field= *field_array;
|
||||
if (use_51_hash)
|
||||
{
|
||||
switch (field->real_type()) {
|
||||
case MYSQL_TYPE_TINY:
|
||||
case MYSQL_TYPE_SHORT:
|
||||
case MYSQL_TYPE_LONG:
|
||||
case MYSQL_TYPE_FLOAT:
|
||||
case MYSQL_TYPE_DOUBLE:
|
||||
case MYSQL_TYPE_NEWDECIMAL:
|
||||
case MYSQL_TYPE_TIMESTAMP:
|
||||
case MYSQL_TYPE_LONGLONG:
|
||||
case MYSQL_TYPE_INT24:
|
||||
case MYSQL_TYPE_TIME:
|
||||
case MYSQL_TYPE_DATETIME:
|
||||
case MYSQL_TYPE_YEAR:
|
||||
case MYSQL_TYPE_NEWDATE:
|
||||
{
|
||||
if (field->is_null())
|
||||
{
|
||||
nr1^= (nr1 << 1) | 1;
|
||||
continue;
|
||||
}
|
||||
/* Force this to my_hash_sort_bin, which was used in 5.1! */
|
||||
uint len= field->pack_length();
|
||||
my_charset_bin.coll->hash_sort(&my_charset_bin, field->ptr, len,
|
||||
&nr1, &nr2);
|
||||
/* Done with this field, continue with next one. */
|
||||
continue;
|
||||
}
|
||||
case MYSQL_TYPE_STRING:
|
||||
case MYSQL_TYPE_VARCHAR:
|
||||
case MYSQL_TYPE_BIT:
|
||||
/* Not affected, same in 5.1 and 5.5 */
|
||||
break;
|
||||
/*
|
||||
ENUM/SET uses my_hash_sort_simple in 5.1 (i.e. my_charset_latin1)
|
||||
and my_hash_sort_bin in 5.5!
|
||||
*/
|
||||
case MYSQL_TYPE_ENUM:
|
||||
case MYSQL_TYPE_SET:
|
||||
{
|
||||
if (field->is_null())
|
||||
{
|
||||
nr1^= (nr1 << 1) | 1;
|
||||
continue;
|
||||
}
|
||||
/* Force this to my_hash_sort_bin, which was used in 5.1! */
|
||||
uint len= field->pack_length();
|
||||
my_charset_latin1.coll->hash_sort(&my_charset_latin1, field->ptr,
|
||||
len, &nr1, &nr2);
|
||||
continue;
|
||||
}
|
||||
/* These types should not be allowed for partitioning! */
|
||||
case MYSQL_TYPE_NULL:
|
||||
case MYSQL_TYPE_DECIMAL:
|
||||
case MYSQL_TYPE_DATE:
|
||||
case MYSQL_TYPE_TINY_BLOB:
|
||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||
case MYSQL_TYPE_LONG_BLOB:
|
||||
case MYSQL_TYPE_BLOB:
|
||||
case MYSQL_TYPE_VAR_STRING:
|
||||
case MYSQL_TYPE_GEOMETRY:
|
||||
/* fall through. */
|
||||
default:
|
||||
DBUG_ASSERT(0); // New type?
|
||||
/* Fall through for default hashing (5.5). */
|
||||
}
|
||||
/* fall through, use collation based hashing. */
|
||||
}
|
||||
field->hash(&nr1, &nr2);
|
||||
} while (*(++field_array));
|
||||
return (uint32) nr1;
|
||||
@ -5411,14 +5540,25 @@ the generated partition syntax in a correct manner.
|
||||
Need to cater for engine types that can handle partition without
|
||||
using the partition handler.
|
||||
*/
|
||||
if (thd->work_part_info != table->part_info)
|
||||
if (part_info != table->part_info)
|
||||
{
|
||||
DBUG_PRINT("info", ("partition changed"));
|
||||
*partition_changed= TRUE;
|
||||
if (thd->work_part_info->fix_parser_data(thd))
|
||||
if (part_info->fix_parser_data(thd))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
Compare the old and new part_info. If only key_algorithm
|
||||
change is done, don't consider it as changed partitioning (to avoid
|
||||
rebuild). This is to handle KEY (numeric_cols) partitioned tables
|
||||
created in 5.1. For more info, see bug#14521864.
|
||||
*/
|
||||
if (alter_info->flags != ALTER_PARTITION ||
|
||||
!table->part_info ||
|
||||
!table->part_info->has_same_partitioning(part_info))
|
||||
{
|
||||
DBUG_PRINT("info", ("partition changed"));
|
||||
*partition_changed= true;
|
||||
}
|
||||
}
|
||||
/*
|
||||
Set up partition default_engine_type either from the create_info
|
||||
@ -6970,7 +7110,8 @@ void set_key_field_ptr(KEY *key_info, const uchar *new_buf,
|
||||
|
||||
void mem_alloc_error(size_t size)
|
||||
{
|
||||
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(size));
|
||||
my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
|
||||
static_cast<int>(size));
|
||||
}
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
@ -7057,12 +7198,12 @@ void make_used_partitions_str(partition_info *part_info, String *parts_str)
|
||||
definition)
|
||||
|
||||
IMPLEMENTATION
|
||||
There are two available interval analyzer functions:
|
||||
(1) get_part_iter_for_interval_via_mapping
|
||||
There are three available interval analyzer functions:
|
||||
(1) get_part_iter_for_interval_via_mapping
|
||||
(2) get_part_iter_for_interval_cols_via_map
|
||||
(3) get_part_iter_for_interval_via_walking
|
||||
|
||||
They both have limited applicability:
|
||||
They all have limited applicability:
|
||||
(1) is applicable for "PARTITION BY <RANGE|LIST>(func(t.field))", where
|
||||
func is a monotonic function.
|
||||
|
||||
@ -7435,6 +7576,9 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
get_endpoint_func UNINIT_VAR(get_endpoint);
|
||||
bool can_match_multiple_values; /* is not '=' */
|
||||
uint field_len= field->pack_length_in_rec();
|
||||
MYSQL_TIME start_date;
|
||||
bool check_zero_dates= false;
|
||||
bool zero_in_start_date= true;
|
||||
DBUG_ENTER("get_part_iter_for_interval_via_mapping");
|
||||
DBUG_ASSERT(!is_subpart);
|
||||
(void) store_length_array;
|
||||
@ -7491,6 +7635,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
{
|
||||
/* col is NOT NULL, but F(col) can return NULL, add NULL partition */
|
||||
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
|
||||
check_zero_dates= true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7534,6 +7679,19 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
part_iter->part_nums.cur= part_iter->part_nums.start;
|
||||
if (check_zero_dates && !part_info->part_expr->null_value)
|
||||
{
|
||||
if (!(flags & NO_MAX_RANGE) &&
|
||||
(field->type() == MYSQL_TYPE_DATE ||
|
||||
field->type() == MYSQL_TYPE_DATETIME))
|
||||
{
|
||||
/* Monotonic, but return NULL for dates with zeros in month/day. */
|
||||
zero_in_start_date= field->get_date(&start_date, 0);
|
||||
DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d",
|
||||
zero_in_start_date, start_date.year,
|
||||
start_date.month, start_date.day));
|
||||
}
|
||||
}
|
||||
if (part_iter->part_nums.start == max_endpoint_val)
|
||||
DBUG_RETURN(0); /* No partitions */
|
||||
}
|
||||
@ -7547,6 +7705,29 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
||||
store_key_image_to_rec(field, max_value, field_len);
|
||||
bool include_endp= !test(flags & NEAR_MAX);
|
||||
part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp);
|
||||
if (check_zero_dates &&
|
||||
!zero_in_start_date &&
|
||||
!part_info->part_expr->null_value)
|
||||
{
|
||||
MYSQL_TIME end_date;
|
||||
bool zero_in_end_date= field->get_date(&end_date, 0);
|
||||
/*
|
||||
This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning
|
||||
the NULL partition for ranges that cannot include a date with 0 as
|
||||
month/day.
|
||||
*/
|
||||
DBUG_PRINT("info", ("zero end %u %04d-%02d-%02d",
|
||||
zero_in_end_date,
|
||||
end_date.year, end_date.month, end_date.day));
|
||||
DBUG_ASSERT(!memcmp(((Item_func*) part_info->part_expr)->func_name(),
|
||||
"to_days", 7) ||
|
||||
!memcmp(((Item_func*) part_info->part_expr)->func_name(),
|
||||
"to_seconds", 10));
|
||||
if (!zero_in_end_date &&
|
||||
start_date.month == end_date.month &&
|
||||
start_date.year == end_date.year)
|
||||
part_iter->ret_null_part= part_iter->ret_null_part_orig= false;
|
||||
}
|
||||
if (part_iter->part_nums.start >= part_iter->part_nums.end &&
|
||||
!part_iter->ret_null_part)
|
||||
DBUG_RETURN(0); /* No partitions */
|
||||
|
Reference in New Issue
Block a user