1
/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
1
/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
3
3
This program is free software; you can redistribute it and/or modify
4
4
it under the terms of the GNU General Public License as published by
197
197
DBUG_ENTER("partition_default_handling");
199
if (part_info->use_default_no_partitions)
201
if (!is_create_table_ind &&
202
table->file->get_no_parts(normalized_path, &part_info->no_parts))
207
else if (part_info->is_sub_partitioned() &&
208
part_info->use_default_no_subpartitions)
211
if (!is_create_table_ind &&
212
(table->file->get_no_parts(normalized_path, &no_parts)))
216
DBUG_ASSERT(part_info->no_parts > 0);
217
part_info->no_subparts= no_parts / part_info->no_parts;
218
DBUG_ASSERT((no_parts % part_info->no_parts) == 0);
199
if (!is_create_table_ind)
201
if (part_info->use_default_no_partitions)
203
if (table->file->get_no_parts(normalized_path, &part_info->no_parts))
208
else if (part_info->is_sub_partitioned() &&
209
part_info->use_default_no_subpartitions)
212
if (table->file->get_no_parts(normalized_path, &no_parts))
216
DBUG_ASSERT(part_info->no_parts > 0);
217
DBUG_ASSERT((no_parts % part_info->no_parts) == 0);
218
part_info->no_subparts= no_parts / part_info->no_parts;
220
221
part_info->set_up_defaults_for_partitioning(table->file,
221
222
(ulonglong)0, (uint)0);
784
Check for duplicate fields in the list.
785
Assuming that there are not many fields in the partition key list.
786
If there were, it would be better to replace the for-loop
787
with a more efficient algorithm.
790
field_name_array[fields_handled] = field_name;
791
for (int i = 0; i < fields_handled; ++i)
793
if (my_strcasecmp(system_charset_info,
794
field_name_array[i], field_name) == 0)
796
my_error(ER_FIELD_NOT_FOUND_PART_ERROR, MYF(0));
779
802
if (is_list_empty)
869
892
part_info Reference to partitioning data structure
870
893
is_sub_part Is the table subpartitioned as well
871
894
is_field_to_be_setup Flag if we are to set-up field arrays
895
is_create_table_ind Indicator of whether openfrm was called as part of
896
CREATE or ALTER TABLE
874
899
TRUE An error occurred, something was wrong with the
891
916
on the field object.
894
bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
895
bool is_sub_part, bool is_field_to_be_setup)
919
static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
920
bool is_sub_part, bool is_field_to_be_setup,
921
bool is_create_table_ind)
897
923
partition_info *part_info= table->part_info;
898
924
uint dir_length, home_dir_length;
971
996
of interesting side effects, both desirable and undesirable.
974
save_use_only_table_context= thd->lex->use_only_table_context;
975
thd->lex->use_only_table_context= TRUE;
976
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
1000
const bool save_use_only_table_context= thd->lex->use_only_table_context;
1001
thd->lex->use_only_table_context= TRUE;
1002
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
1003
const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
1004
const bool save_agg_func= thd->lex->current_select->agg_func_used();
1005
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
1006
thd->lex->allow_sum_func= 0;
978
error= func_expr->fix_fields(thd, (Item**)&func_expr);
1008
error= func_expr->fix_fields(thd, (Item**)&func_expr);
980
thd->lex->use_only_table_context= save_use_only_table_context;
1011
Restore agg_field/agg_func and allow_sum_func,
1012
fix_fields should not affect mysql_select later, see Bug#46923.
1014
thd->lex->current_select->set_non_agg_field_used(save_agg_field);
1015
thd->lex->current_select->set_agg_func_used(save_agg_func);
1016
thd->lex->allow_sum_func= saved_allow_sum_func;
1017
thd->lex->use_only_table_context= save_use_only_table_context;
982
1020
context->table_list= save_table_list;
983
1021
context->first_name_resolution_table= save_first_table;
992
1030
thd->where= save_where;
993
1031
if (unlikely(func_expr->const_item()))
995
my_error(ER_CONST_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
1033
my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
996
1034
clear_field_flag(table);
1039
We don't allow creating partitions with expressions with non matching
1040
arguments as a (sub)partitioning function,
1041
but we want to allow such expressions when opening existing tables for
1042
easier maintenance. This exception should be deprecated at some point
1043
in future so that we always throw an error.
1045
if (func_expr->walk(&Item::check_valid_arguments_processor,
1048
if (is_create_table_ind)
1050
my_error(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR, MYF(0));
1054
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
1055
ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR,
1056
ER(ER_WRONG_EXPR_IN_PARTITION_FUNC_ERROR));
999
1059
if ((!is_sub_part) && (error= check_signed_flag(part_info)))
1679
1742
if (((part_info->part_type != HASH_PARTITION ||
1680
1743
part_info->list_of_part_fields == FALSE) &&
1681
1744
check_part_func_fields(part_info->part_field_array, TRUE)) ||
1682
(part_info->list_of_part_fields == FALSE &&
1745
(part_info->list_of_subpart_fields == FALSE &&
1683
1746
part_info->is_sub_partitioned() &&
1684
1747
check_part_func_fields(part_info->subpart_field_array, TRUE)))
2836
2899
*func_value= part_func_value;
2837
2900
if (unsigned_flag)
2838
2901
part_func_value-= 0x8000000000000000ULL;
2902
/* Search for the partition containing part_func_value */
2839
2903
while (max_part_id > min_part_id)
2841
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
2905
loc_part_id= (max_part_id + min_part_id) / 2;
2842
2906
if (range_array[loc_part_id] <= part_func_value)
2843
2907
min_part_id= loc_part_id + 1;
2845
max_part_id= loc_part_id - 1;
2909
max_part_id= loc_part_id;
2847
2911
loc_part_id= max_part_id;
2848
if (part_func_value >= range_array[loc_part_id])
2849
if (loc_part_id != max_partition)
2851
2912
*part_id= (uint32)loc_part_id;
2852
2913
if (loc_part_id == max_partition &&
2853
2914
part_func_value >= range_array[loc_part_id] &&
2921
2982
bool include_endpoint)
2923
2984
longlong *range_array= part_info->range_int_array;
2985
longlong part_end_val;
2924
2986
uint max_partition= part_info->no_parts - 1;
2925
2987
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
2926
2988
/* Get the partitioning function value for the endpoint */
2958
3019
if (unsigned_flag)
2959
3020
part_func_value-= 0x8000000000000000ULL;
2960
3021
if (left_endpoint && !include_endpoint)
2961
3022
part_func_value++;
3025
Search for the partition containing part_func_value
3026
(including the right endpoint).
2962
3028
while (max_part_id > min_part_id)
2964
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
2965
if (range_array[loc_part_id] <= part_func_value)
3030
loc_part_id= (max_part_id + min_part_id) / 2;
3031
if (range_array[loc_part_id] < part_func_value)
2966
3032
min_part_id= loc_part_id + 1;
2968
max_part_id= loc_part_id - 1;
3034
max_part_id= loc_part_id;
2970
3036
loc_part_id= max_part_id;
2971
if (loc_part_id < max_partition &&
2972
part_func_value >= range_array[loc_part_id+1])
3038
/* Adjust for endpoints */
3039
part_end_val= range_array[loc_part_id];
2976
3040
if (left_endpoint)
2978
longlong bound= range_array[loc_part_id];
3042
DBUG_ASSERT(part_func_value > part_end_val ?
3043
(loc_part_id == max_partition &&
3044
!part_info->defined_max_value) :
2980
3047
In case of PARTITION p VALUES LESS THAN MAXVALUE
2981
the maximum value is in the current partition.
3048
the maximum value is in the current (last) partition.
3049
If value is equal or greater than the endpoint,
3050
the range starts from the next partition.
2983
if (part_func_value > bound ||
2984
(part_func_value == bound &&
2985
(!part_info->defined_max_value || loc_part_id < max_partition)))
3052
if (part_func_value >= part_end_val &&
3053
(loc_part_id < max_partition || !part_info->defined_max_value))
2990
if (loc_part_id < max_partition)
2992
if (part_func_value == range_array[loc_part_id])
2993
loc_part_id += test(include_endpoint);
2994
else if (part_func_value > range_array[loc_part_id])
3058
/* if 'WHERE <= X' and partition is LESS THAN (X) include next partition */
3059
if (include_endpoint && loc_part_id < max_partition &&
3060
part_func_value == part_end_val)
3063
/* Right endpoint, set end after correct partition */
2999
3066
DBUG_RETURN(loc_part_id);
3834
3901
bool mysql_unpack_partition(THD *thd,
3835
const char *part_buf, uint part_info_len,
3902
char *part_buf, uint part_info_len,
3836
3903
const char *part_state, uint part_state_len,
3837
3904
TABLE* table, bool is_create_table_ind,
3838
3905
handlerton *default_db_type,
3848
3915
thd->lex= &lex;
3849
3916
thd->variables.character_set_client= system_charset_info;
3851
Parser_state parser_state(thd, part_buf, part_info_len);
3918
Parser_state parser_state;
3919
if (parser_state.init(thd, part_buf, part_info_len))
3853
3922
lex_start(thd);
3854
3923
*work_part_info_used= false;
4078
4147
if ((!is_empty) && (!written_bin_log) &&
4079
(!thd->lex->no_write_to_binlog))
4080
write_bin_log(thd, FALSE, thd->query(), thd->query_length());
4148
(!thd->lex->no_write_to_binlog) &&
4149
write_bin_log(thd, FALSE, thd->query(), thd->query_length()))
4082
4152
my_snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
4083
4153
(ulong) (copied + deleted),
4236
4306
DBUG_ENTER("prep_alter_part_table");
4308
/* Foreign keys on partitioned tables are not supported, waits for WL#148 */
4309
if (table->part_info && (alter_info->flags & ALTER_FOREIGN_KEY))
4311
my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
4239
4315
We are going to manipulate the partition info on the table object
4240
4316
so we need to ensure that the data structure of the table object
5668
5744
part_info->first_log_entry= NULL;
5669
5745
build_table_filename(path, sizeof(path) - 1, lpt->db,
5670
5746
lpt->table_name, "", 0);
5671
build_table_filename(tmp_path, sizeof(tmp_path) - 1, lpt->db,
5672
lpt->table_name, "#", 0);
5747
build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
5673
5748
pthread_mutex_lock(&LOCK_gdl);
5674
5749
if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
5726
5801
build_table_filename(path, sizeof(path) - 1, lpt->db,
5727
5802
lpt->table_name, "", 0);
5728
build_table_filename(tmp_path, sizeof(tmp_path) - 1, lpt->db,
5729
lpt->table_name, "#", 0);
5803
build_table_shadow_filename(tmp_path, sizeof(tmp_path) - 1, lpt);
5730
5804
pthread_mutex_lock(&LOCK_gdl);
5731
5805
if (write_log_dropped_partitions(lpt, &next_entry, (const char*)path,
5884
5958
if (lpt->thd->locked_tables)
5961
Close the table if open, to remove/destroy the already altered
5962
table->part_info object, so that it is not reused.
5964
if (lpt->table->db_stat)
5965
abort_and_upgrade_lock_and_close_table(lpt);
5887
5967
When we have the table locked, it is necessary to reopen the table
5888
5968
since all table objects were closed and removed as part of the
5889
5969
ALTER TABLE of partitioning structure.
5910
Unlock and close table before renaming and dropping partitions
5912
alter_close_tables()
5913
lpt Struct carrying parameters
5918
static int alter_close_tables(ALTER_PARTITION_PARAM_TYPE *lpt)
5921
const char *db= lpt->db;
5922
const char *table_name= lpt->table_name;
5923
DBUG_ENTER("alter_close_tables");
5925
We need to also unlock tables and close all handlers.
5926
We set lock to zero to ensure we don't do this twice
5927
and we set db_stat to zero to ensure we don't close twice.
5929
pthread_mutex_lock(&LOCK_open);
5930
close_data_files_and_morph_locks(thd, db, table_name);
5931
pthread_mutex_unlock(&LOCK_open);
5937
5991
Handle errors for ALTER TABLE for partitioning
5951
6005
partition_info *part_info= lpt->part_info;
5952
6006
DBUG_ENTER("handle_alter_part_error");
5954
if (!part_info->first_log_entry &&
6008
if (part_info->first_log_entry &&
5955
6009
execute_ddl_log_entry(current_thd,
5956
6010
part_info->first_log_entry->entry_pos))
6229
6283
write_log_drop_partition(lpt) ||
6230
6284
ERROR_INJECT_CRASH("crash_drop_partition_3") ||
6231
6285
(not_completed= FALSE) ||
6232
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
6233
ERROR_INJECT_CRASH("crash_drop_partition_4") ||
6234
alter_close_tables(lpt) ||
6286
abort_and_upgrade_lock_and_close_table(lpt) ||
6235
6287
ERROR_INJECT_CRASH("crash_drop_partition_5") ||
6236
6288
((!thd->lex->no_write_to_binlog) &&
6237
6289
(write_bin_log(thd, FALSE,
6296
6348
ERROR_INJECT_CRASH("crash_add_partition_2") ||
6297
6349
mysql_change_partitions(lpt) ||
6298
6350
ERROR_INJECT_CRASH("crash_add_partition_3") ||
6299
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
6300
ERROR_INJECT_CRASH("crash_add_partition_4") ||
6301
alter_close_tables(lpt) ||
6351
abort_and_upgrade_lock_and_close_table(lpt) ||
6302
6352
ERROR_INJECT_CRASH("crash_add_partition_5") ||
6303
6353
((!thd->lex->no_write_to_binlog) &&
6304
6354
(write_bin_log(thd, FALSE,
6386
6436
write_log_final_change_partition(lpt) ||
6387
6437
ERROR_INJECT_CRASH("crash_change_partition_4") ||
6388
6438
(not_completed= FALSE) ||
6389
abort_and_upgrade_lock(lpt) || /* Always returns 0 */
6390
ERROR_INJECT_CRASH("crash_change_partition_5") ||
6391
alter_close_tables(lpt) ||
6439
abort_and_upgrade_lock_and_close_table(lpt) ||
6392
6440
ERROR_INJECT_CRASH("crash_change_partition_6") ||
6393
6441
((!thd->lex->no_write_to_binlog) &&
6394
6442
(write_bin_log(thd, FALSE,
6417
6465
table, table_list, FALSE, NULL,
6418
6466
written_bin_log));
6420
close_thread_tables(thd);
6468
if (thd->locked_tables)
6471
table->part_info was altered in prep_alter_part_table and must be
6472
destroyed and recreated, since otherwise it will be reused, since
6473
we are under LOCK TABLE.
6475
alter_partition_lock_handling(lpt);
6479
/* Force the table to be closed to avoid reuse of the table->part_info */
6480
close_thread_tables(thd);
6421
6482
DBUG_RETURN(TRUE);
6511
6572
void mem_alloc_error(size_t size)
6513
my_error(ER_OUTOFMEMORY, MYF(0), size);
6574
my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(size));
6516
6577
#ifdef WITH_PARTITION_STORAGE_ENGINE
6729
6790
DBUG_ASSERT(!is_subpart);
6730
6791
Field *field= part_info->part_field_array[0];
6731
uint32 max_endpoint_val;
6732
get_endpoint_func get_endpoint;
6792
uint32 UNINIT_VAR(max_endpoint_val);
6793
get_endpoint_func UNINIT_VAR(get_endpoint);
6733
6794
bool can_match_multiple_values; /* is not '=' */
6734
6795
uint field_len= field->pack_length_in_rec();
6735
6796
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;