diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2017-09-07 15:49:11 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-07 15:49:11 +0300 |
commit | 904b69cd9ed15b0d605b9923439e9a66b5057084 (patch) | |
tree | 006b4d328b739cf2d3afbfa4fe7f48496c14b191 /sql | |
parent | a734c2f0fb44b777866d8b0bc9ec46a08e4e6505 (diff) | |
download | mariadb-git-904b69cd9ed15b0d605b9923439e9a66b5057084.tar.gz |
SQL: partitioning misc fixes [closes #242]
* cleanup: *never* use assert(A && B)
* vers_setup_1() revisited
* vers_setup_2() renamed
* partition_element::type removed
* Copy ctor instead of memcpy()
* Handle return value from check_range_constants()
* Malloc error fix
* error, style, misc fixes
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_partition.cc | 7 | ||||
-rw-r--r-- | sql/ha_partition.h | 5 | ||||
-rw-r--r-- | sql/handler.h | 2 | ||||
-rw-r--r-- | sql/opt_range.cc | 7 | ||||
-rw-r--r-- | sql/partition_element.h | 37 | ||||
-rw-r--r-- | sql/partition_info.cc | 114 | ||||
-rw-r--r-- | sql/partition_info.h | 32 | ||||
-rw-r--r-- | sql/sql_partition.cc | 10 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 4 | ||||
-rw-r--r-- | sql/table.cc | 2 | ||||
-rw-r--r-- | sql/table.h | 4 |
11 files changed, 121 insertions, 103 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 747b9a8871f..68fffa24a02 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -2022,15 +2022,12 @@ int ha_partition::copy_partitions(ulonglong * const copied, else { THD *thd= ha_thd(); - handler *new_file= m_new_file[new_part]; /* Copy record to new handler */ (*copied)++; - if (new_file->ha_external_lock(thd, F_UNLCK) || new_file->ha_external_lock(thd, F_WRLCK)) - goto error; tmp_disable_binlog(thd); /* Do not replicate the low-level changes. */ - result= new_file->ha_write_row(m_rec0); + result= m_new_file[new_part]->ha_write_row(m_rec0); reenable_binlog(thd); - if (new_file->ha_external_lock(thd, F_UNLCK) || new_file->ha_external_lock(thd, F_RDLCK) || result) + if (result) goto error; } } diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 98e0c1baafe..0eb96aa2d00 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -1355,11 +1355,6 @@ public: return h; } - virtual bool versioned() const - { - return m_innodb; - } - virtual ha_rows part_records(void *_part_elem) { partition_element *part_elem= reinterpret_cast<partition_element *>(_part_elem); diff --git a/sql/handler.h b/sql/handler.h index a0c40d2765a..911eb25ba0e 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -4404,7 +4404,7 @@ public: virtual int find_unique_row(uchar *record, uint unique_ref) { return -1; /*unsupported */} - virtual bool versioned() const + bool native_versioned() const { DBUG_ASSERT(ht); return partition_ht()->flags & HTON_NATIVE_SYS_VERSIONING; } virtual ha_rows part_records(void *_part_elem) { DBUG_ASSERT(0); return false; } diff --git a/sql/opt_range.cc b/sql/opt_range.cc index fcf038a212b..53208571ee2 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3455,9 +3455,11 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond) DBUG_RETURN(FALSE); } - if (part_info->part_type == VERSIONING_PARTITION) + if (part_info->part_type == VERSIONING_PARTITION && + part_info->vers_update_range_constants(thd)) { - part_info->vers_update_range_constants(thd); + retval= TRUE; + goto end2; } dbug_tmp_use_all_columns(table, old_sets, @@ -3559,6 +3561,7 @@ all_used: mark_all_partitions_as_used(prune_param.part_info); end: dbug_tmp_restore_column_maps(table->read_set, table->write_set, old_sets); +end2: thd->no_errors=0; thd->mem_root= range_par->old_root; free_root(&alloc,MYF(0)); // Return memory & allocator diff --git a/sql/partition_element.h b/sql/partition_element.h index 723d2f21a46..b8b716e5273 100644 --- a/sql/partition_element.h +++ b/sql/partition_element.h @@ -151,6 +151,13 @@ enum stat_trx_field class partition_element :public Sql_alloc { public: + enum elem_type + { + CONVENTIONAL= 0, + AS_OF_NOW, + VERSIONING + }; + List<partition_element> subpartitions; List<part_elem_value> list_val_list; ha_rows part_max_rows; @@ -172,14 +179,18 @@ public: uint32 id; bool empty; - enum elem_type + // TODO: subclass partition_element by partitioning type to avoid such semantic + // mixup + elem_type type() { - CONVENTIONAL= 0, - AS_OF_NOW, - VERSIONING - }; + return (elem_type)(signed_flag << 1 | max_value); + } - elem_type type; + void type(elem_type val) + { + max_value= val & 1; + signed_flag= val & 2; + } partition_element() : part_max_rows(0), part_min_rows(0), range_value(0), @@ -190,8 +201,7 @@ public: nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE), signed_flag(FALSE), max_value(FALSE), id(UINT32_MAX), - empty(true), - type(CONVENTIONAL) + empty(true) {} partition_element(partition_element *part_elem) : part_max_rows(part_elem->part_max_rows), @@ -207,17 +217,16 @@ public: nodegroup_id(part_elem->nodegroup_id), has_null_value(FALSE), id(part_elem->id), - empty(part_elem->empty), - type(part_elem->type) + empty(part_elem->empty) {} ~partition_element() {} part_column_list_val& get_col_val(uint idx) { - DBUG_ASSERT(type != CONVENTIONAL); - DBUG_ASSERT(list_val_list.elements == 1); - part_elem_value *ev= static_cast<part_elem_value*>(list_val_list.first_node()->info); - DBUG_ASSERT(ev && ev->col_val_array); + DBUG_ASSERT(type() == CONVENTIONAL || list_val_list.elements == 1); + part_elem_value *ev= list_val_list.head(); + DBUG_ASSERT(ev); + DBUG_ASSERT(ev->col_val_array); return ev->col_val_array[idx]; } }; diff --git a/sql/partition_info.cc b/sql/partition_info.cc index 8bf2e2cd72d..af97791ab80 100644 --- a/sql/partition_info.cc +++ b/sql/partition_info.cc @@ -44,13 +44,12 @@ partition_info *partition_info::get_clone(THD *thd) List_iterator<partition_element> part_it(partitions); partition_element *part; - partition_info *clone= new (mem_root) partition_info(); + partition_info *clone= new (mem_root) partition_info(*this); if (!clone) { mem_alloc_error(sizeof(partition_info)); DBUG_RETURN(NULL); } - memcpy(clone, this, sizeof(partition_info)); memset(&(clone->read_partitions), 0, sizeof(clone->read_partitions)); memset(&(clone->lock_partitions), 0, sizeof(clone->lock_partitions)); clone->bitmaps_are_initialized= FALSE; @@ -913,28 +912,59 @@ partition_info::vers_part_rotate(THD * thd) return vers_info->hist_part; } -bool partition_info::vers_setup_1(THD * thd, uint32 added) +bool partition_info::vers_set_expression(THD *thd, partition_element *el, MYSQL_TIME& t) +{ + curr_part_elem= el; + init_column_part(thd); + el->list_val_list.empty(); + el->list_val_list.push_back(curr_list_val, thd->mem_root); + for (uint i= 0; i < num_columns; ++i) + { + part_column_list_val *col_val= add_column_value(thd); + if (el->type() == partition_element::AS_OF_NOW) + { + col_val->max_value= true; + col_val->item_expression= NULL; + col_val->column_value= NULL; + col_val->part_info= this; + col_val->fixed= 1; + continue; + } + Item *item_expression= new (thd->mem_root) Item_datetime_literal(thd, &t); + if (!item_expression) + return true; + /* We initialize col_val with bogus max value to make fix_partition_func() and check_range_constants() happy. + Later in vers_setup_stats() it is initialized with real stat value if there will be any. */ + /* FIXME: TIME_RESULT in col_val is expensive. It should be INT_RESULT + (got to be fixed when InnoDB is supported). */ + init_col_val(col_val, item_expression); + DBUG_ASSERT(item_expression == el->get_col_val(i).item_expression); + } // for (num_columns) + return false; +} + +bool partition_info::vers_setup_expression(THD * thd, uint32 alter_add) { DBUG_ASSERT(part_type == VERSIONING_PARTITION); if (!table->versioned()) { - my_error(ER_VERSIONING_REQUIRED, MYF(0), "`BY SYSTEM_TIME` partitioning"); + my_error(ER_VERSIONING_REQUIRED, MYF(0), table->s->table_name); return true; } - if (added) + if (alter_add) { - DBUG_ASSERT(partitions.elements > added + 1); + DBUG_ASSERT(partitions.elements > alter_add + 1); Vers_min_max_stats** old_array= table->s->stat_trx; table->s->stat_trx= static_cast<Vers_min_max_stats**>( alloc_root(&table->s->mem_root, sizeof(void *) * partitions.elements * num_columns)); - memcpy(table->s->stat_trx, old_array, sizeof(void *) * (partitions.elements - added) * num_columns); + memcpy(table->s->stat_trx, old_array, sizeof(void *) * (partitions.elements - alter_add) * num_columns); } else { + /* Prepare part_field_list */ Field *sys_trx_end= table->vers_end_field(); - part_field_list.empty(); part_field_list.push_back(const_cast<char *>(sys_trx_end->field_name), thd->mem_root); DBUG_ASSERT(part_field_list.elements == num_columns); // needed in handle_list_of_fields() @@ -949,26 +979,29 @@ bool partition_info::vers_setup_1(THD * thd, uint32 added) uint32 id= 0; while ((el= it++)) { - DBUG_ASSERT(el->type != partition_element::CONVENTIONAL); + DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); ++ts; - if (added) + if (alter_add) { - if (el->type == partition_element::VERSIONING && !el->empty) + /* Non-empty historical partitions are left as is. */ + if (el->type() == partition_element::VERSIONING && !el->empty) { ++id; continue; } - if (el->id == UINT32_MAX || el->type == partition_element::AS_OF_NOW) + /* Newly added element is inserted before AS_OF_NOW. */ + if (el->id == UINT32_MAX || el->type() == partition_element::AS_OF_NOW) { DBUG_ASSERT(table && table->s); Vers_min_max_stats *stat_trx_end= new (&table->s->mem_root) Vers_min_max_stats(table->s->vers_end_field()->field_name, table->s); table->s->stat_trx[id * num_columns + STAT_TRX_END]= stat_trx_end; el->id= id++; - if (el->type == partition_element::AS_OF_NOW) + if (el->type() == partition_element::AS_OF_NOW) break; - goto create_col_val; + goto set_expression; } + /* Existing element expression is recalculated. */ thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); for (uint i= 0; i < num_columns; ++i) { @@ -980,32 +1013,10 @@ bool partition_info::vers_setup_1(THD * thd, uint32 added) continue; } - create_col_val: - curr_part_elem= el; - init_column_part(thd); - el->list_val_list.empty(); - el->list_val_list.push_back(curr_list_val, thd->mem_root); + set_expression: thd->variables.time_zone->gmt_sec_to_TIME(&t, ts); - for (uint i= 0; i < num_columns; ++i) - { - part_column_list_val *col_val= add_column_value(thd); - if (el->type == partition_element::AS_OF_NOW) - { - col_val->max_value= true; - col_val->item_expression= NULL; - col_val->column_value= NULL; - col_val->part_info= this; - col_val->fixed= 1; - continue; - } - Item *item_expression= new (thd->mem_root) Item_datetime_literal(thd, &t); - /* We initialize col_val with bogus max value to make fix_partition_func() and check_range_constants() happy. - Later in vers_setup_2() it is initialized with real stat value if there will be any. */ - /* FIXME: TIME_RESULT in col_val is expensive. It should be INT_RESULT - (got to be fixed when InnoDB is supported). */ - init_col_val(col_val, item_expression); - DBUG_ASSERT(item_expression == el->get_col_val(i).item_expression); - } + if (vers_set_expression(thd, el, t)) + return true; } return false; } @@ -1019,7 +1030,7 @@ bool partition_info::vers_scan_min_max(THD *thd, partition_element *part) uint32 part_id= part->id * sub_factor; uint32 part_id_end= part_id + sub_factor; DBUG_ASSERT(part->empty); - DBUG_ASSERT(part->type == partition_element::VERSIONING); + DBUG_ASSERT(part->type() == partition_element::VERSIONING); DBUG_ASSERT(table->s->stat_trx); for (; part_id < part_id_end; ++part_id) { @@ -1141,8 +1152,8 @@ void partition_info::vers_update_col_vals(THD *thd, partition_element *el0, part } -// setup at open stage (TABLE_SHARE is initialized) -bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) +// setup at open() phase (TABLE_SHARE is initialized) +bool partition_info::vers_setup_stats(THD * thd, bool is_create_table_ind) { DBUG_ASSERT(part_type == VERSIONING_PARTITION); DBUG_ASSERT(vers_info && vers_info->initialized(false)); @@ -1165,6 +1176,7 @@ bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) bool dont_stat= true; bool col_val_updated= false; + // initialize stat_trx if (!table->s->stat_trx) { DBUG_ASSERT(partitions.elements > 1); @@ -1178,7 +1190,7 @@ bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) partition_element *el= NULL, *prev; while ((prev= el, el= it++)) { - if (el->type == partition_element::VERSIONING && dont_stat) + if (el->type() == partition_element::VERSIONING && dont_stat) { if (el->id == table->s->hist_part_id) { @@ -1196,7 +1208,7 @@ bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) if (!is_create_table_ind) { - if (el->type == partition_element::AS_OF_NOW) + if (el->type() == partition_element::AS_OF_NOW) { uchar buf[8]; Field_timestampf fld(buf, NULL, 0, Field::NONE, table->vers_end_field()->field_name, NULL, 6); @@ -1217,10 +1229,10 @@ bool partition_info::vers_setup_2(THD * thd, bool is_create_table_ind) } } - if (el->type == partition_element::AS_OF_NOW) + if (el->type() == partition_element::AS_OF_NOW) break; - DBUG_ASSERT(el->type == partition_element::VERSIONING); + DBUG_ASSERT(el->type() == partition_element::VERSIONING); if (vers_info->hist_part) { @@ -1435,7 +1447,7 @@ error: called for RANGE PARTITIONed tables. */ -bool partition_info::check_range_constants(THD *thd, bool init) +bool partition_info::check_range_constants(THD *thd, bool alloc) { partition_element* part_def; bool first= TRUE; @@ -1452,7 +1464,7 @@ bool partition_info::check_range_constants(THD *thd, bool init) part_column_list_val *UNINIT_VAR(current_largest_col_val); uint num_column_values= part_field_list.elements; uint size_entries= sizeof(part_column_list_val) * num_column_values; - if (init) + if (alloc) { range_col_array= (part_column_list_val*) thd->calloc(num_parts * size_entries); @@ -1493,7 +1505,7 @@ bool partition_info::check_range_constants(THD *thd, bool init) longlong part_range_value; bool signed_flag= !part_expr->unsigned_flag; - if (init) + if (alloc) { range_int_array= (longlong*) thd->alloc(num_parts * sizeof(longlong)); if (unlikely(range_int_array == NULL)) @@ -2065,13 +2077,13 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type, } if (part_type == VERSIONING_PARTITION) { - if (part_elem->type == partition_element::VERSIONING) + if (part_elem->type() == partition_element::VERSIONING) { hist_parts++; } else { - DBUG_ASSERT(part_elem->type == partition_element::AS_OF_NOW); + DBUG_ASSERT(part_elem->type() == partition_element::AS_OF_NOW); now_parts++; } } diff --git a/sql/partition_info.h b/sql/partition_info.h index d69774e0841..99772f29891 100644 --- a/sql/partition_info.h +++ b/sql/partition_info.h @@ -57,13 +57,12 @@ struct Vers_part_info : public Sql_alloc { if (now_part) { - DBUG_ASSERT( - now_part->id != UINT32_MAX && - now_part->type == partition_element::AS_OF_NOW && - (fully ? (bool) hist_part : true) && - (!hist_part || ( + DBUG_ASSERT(now_part->id != UINT32_MAX); + DBUG_ASSERT(now_part->type() == partition_element::AS_OF_NOW); + DBUG_ASSERT(!fully || (bool) hist_part); + DBUG_ASSERT(!hist_part || ( hist_part->id != UINT32_MAX && - hist_part->type == partition_element::VERSIONING))); + hist_part->type() == partition_element::VERSIONING)); return true; } return false; @@ -352,7 +351,7 @@ public: char *find_duplicate_field(); char *find_duplicate_name(); bool check_engine_mix(handlerton *engine_type, bool default_engine); - bool check_range_constants(THD *thd, bool init= true); + bool check_range_constants(THD *thd, bool alloc= true); bool check_list_constants(THD *thd); bool check_partition_info(THD *thd, handlerton **eng_type, handler *file, HA_CREATE_INFO *info, @@ -426,8 +425,9 @@ public: bool vers_set_interval(const INTERVAL &i); bool vers_set_limit(ulonglong limit); partition_element* vers_part_rotate(THD *thd); - bool vers_setup_1(THD *thd, uint32 added= 0); - bool vers_setup_2(THD *thd, bool is_create_table_ind); + bool vers_set_expression(THD *thd, partition_element *el, MYSQL_TIME &t); + bool vers_setup_expression(THD *thd, uint32 alter_add= 0); /* Stage 1. */ + bool vers_setup_stats(THD *thd, bool is_create_table_ind); /* Stage 2. */ bool vers_scan_min_max(THD *thd, partition_element *part); void vers_update_col_vals(THD *thd, partition_element *el0, partition_element *el1); @@ -443,8 +443,8 @@ public: partition_element *el; while ((el= it++)) { - DBUG_ASSERT(el->type != partition_element::CONVENTIONAL); - if (el->type == partition_element::VERSIONING && + DBUG_ASSERT(el->type() != partition_element::CONVENTIONAL); + if (el->type() == partition_element::VERSIONING && el->id == table->s->hist_part_id) { vers_info->hist_part= el; @@ -516,7 +516,7 @@ public: { DBUG_ASSERT(vers_info && vers_info->initialized()); DBUG_ASSERT(table && table->s); - DBUG_ASSERT(el && el->type == partition_element::VERSIONING); + DBUG_ASSERT(el && el->type() == partition_element::VERSIONING); bool updated; mysql_rwlock_wrlock(&table->s->LOCK_stat_serial); el->empty= false; @@ -552,7 +552,7 @@ public: if (part_id < vers_info->now_part->id) vers_update_stats(thd, get_partition(part_id)); } - void vers_update_range_constants(THD *thd) + bool vers_update_range_constants(THD *thd) { DBUG_ASSERT(vers_info && vers_info->initialized()); DBUG_ASSERT(table && table->s); @@ -561,17 +561,19 @@ public: if (vers_info->stat_serial == table->s->stat_serial) { mysql_rwlock_unlock(&table->s->LOCK_stat_serial); - return; + return false; } + bool result= false; for (uint i= 0; i < num_columns; ++i) { Field *f= part_field_array[i]; bitmap_set_bit(f->table->write_set, f->field_index); } - check_range_constants(thd, false); + result= check_range_constants(thd, false); vers_info->stat_serial= table->s->stat_serial; mysql_rwlock_unlock(&table->s->LOCK_stat_serial); + return result; } }; diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index 7278b56a017..08ba4d84d9b 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -1689,7 +1689,7 @@ bool fix_partition_func(THD *thd, TABLE *table, if (part_info->column_list) { if (part_info->part_type == VERSIONING_PARTITION && - part_info->vers_setup_1(thd)) + part_info->vers_setup_expression(thd)) goto end; List_iterator<char> it(part_info->part_field_list); if (unlikely(handle_list_of_fields(thd, it, table, part_info, FALSE))) @@ -2392,7 +2392,7 @@ static int add_partition_values(File fptr, partition_info *part_info, } else if (part_info->part_type == VERSIONING_PARTITION) { - switch (p_elem->type) + switch (p_elem->type()) { case partition_element::AS_OF_NOW: err+= add_string(fptr, " AS OF NOW"); @@ -5300,7 +5300,7 @@ that are reorganised. partition_element *el; while ((el= it++)) { - if (el->type == partition_element::AS_OF_NOW) + if (el->type() == partition_element::AS_OF_NOW) { DBUG_ASSERT(tab_part_info->vers_info && el == tab_part_info->vers_info->now_part); it.remove(); @@ -5393,7 +5393,7 @@ that are reorganised. if (is_name_in_list(part_elem->partition_name, alter_info->partition_names)) { - if (part_elem->type == partition_element::AS_OF_NOW) + if (part_elem->type() == partition_element::AS_OF_NOW) { DBUG_ASSERT(table && table->s && table->s->table_name.str); my_error(ER_VERS_WRONG_PARTS, MYF(0), table->s->table_name.str); @@ -5724,7 +5724,7 @@ the generated partition syntax in a correct manner. if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION && tab_part_info->part_type == VERSIONING_PARTITION && - tab_part_info->vers_setup_1(thd, alt_part_info->partitions.elements)) + tab_part_info->vers_setup_expression(thd, alt_part_info->partitions.elements)) goto err; if (tab_part_info->check_partition_info(thd, (handlerton**)NULL, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index ea7eb443896..1f0ce5fd6a0 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -5212,7 +5212,7 @@ opt_part_values: my_yyabort_error((ER_VERS_WRONG_PARTS, MYF(0), Lex->create_last_non_select_table->table_name)); } - elem->type= partition_element::AS_OF_NOW; + elem->type(partition_element::AS_OF_NOW); DBUG_ASSERT(part_info->vers_info); part_info->vers_info->now_part= elem; if (part_info->init_column_part(thd)) @@ -5243,7 +5243,7 @@ opt_part_values: DBUG_ASSERT(Lex->create_last_non_select_table->table_name); my_yyabort_error((ER_VERS_WRONG_PARTS, MYF(0), Lex->create_last_non_select_table->table_name)); } - elem->type= partition_element::VERSIONING; + elem->type(partition_element::VERSIONING); if (part_info->init_column_part(thd)) { MYSQL_YYABORT; diff --git a/sql/table.cc b/sql/table.cc index 902e6ea0224..07d912c4045 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3455,7 +3455,7 @@ partititon_err: thd->stmt_arena= &part_func_arena; } - bool err= outparam->part_info->vers_setup_2(thd, is_create_table); + bool err= outparam->part_info->vers_setup_stats(thd, is_create_table); if (!work_part_info_used) { diff --git a/sql/table.h b/sql/table.h index a2ede121064..d857ba4752b 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1521,13 +1521,13 @@ public: bool versioned_by_sql() const { DBUG_ASSERT(s && file); - return s->versioned && !file->versioned(); + return s->versioned && !file->native_versioned(); } bool versioned_by_engine() const { DBUG_ASSERT(s && file); - return s->versioned && file->versioned(); + return s->versioned && file->native_versioned(); } Field *vers_start_field() const |