diff options
author | Monty <monty@mariadb.org> | 2016-12-05 12:17:52 +0200 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-01-18 13:56:55 +0200 |
commit | 5ff25c31c5b57b9523e43d073b86e9ee15180932 (patch) | |
tree | bb904a78bd7414adeac5b631760096d5b89cf0c4 | |
parent | a059002ab11d3a449036860f2a8339f3267e9c2c (diff) | |
download | mariadb-git-5ff25c31c5b57b9523e43d073b86e9ee15180932.tar.gz |
MDEV 7701 Apply Spider patch 003_mariadb-10.0.15.vp.diff
- Support HA_EXTRA_ADD_CHILDREN_LIST,HA_EXTRA_ATTACH_CHILDREN,
HA_EXTRA_IS_ATTACHED_CHILDREN and HA_EXTRA_DETACH_CHILDREN
in partition handler for handlers that has HA_CAN_MULTISTEPL_MERGE flag
- Added HA_CAN_MULTISTEPL_MERGE to MERGE handler.
- Added handler::get_child_handlers()
- Change m_num_lock to contain total number of locks. This was needed as we
now adjust number of locks when extra(HA_EXTRA_ATTACH_CHILDREN) is called.
-rw-r--r-- | sql/ha_partition.cc | 76 | ||||
-rw-r--r-- | sql/ha_partition.h | 5 | ||||
-rw-r--r-- | sql/handler.h | 43 | ||||
-rw-r--r-- | sql/sql_base.cc | 28 | ||||
-rw-r--r-- | storage/myisammrg/ha_myisammrg.h | 2 |
5 files changed, 130 insertions, 24 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc index 6e7adfd8139..bedadf185af 100644 --- a/sql/ha_partition.cc +++ b/sql/ha_partition.cc @@ -3499,6 +3499,13 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked) name_buffer_ptr+= strlen(name_buffer_ptr) + 1; } while (*(++file)); } + /* + We want to know the upper bound for locks, to allocate enough memory. + There is no performance lost if we simply return in lock_count() the + maximum number locks needed, only some minor over allocation of memory + in get_lock_data(). + */ + m_num_locks*= m_tot_parts; file= m_file; ref_length= (*file)->ref_length; @@ -3940,25 +3947,14 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type) @returns Number of locks returned in call to store_lock @desc - Returns the number of store locks needed in call to store lock. - We return number of partitions we will lock multiplied with number of - locks needed by each partition. Assists the above functions in allocating - sufficient space for lock structures. + Returns the maxinum possible number of store locks needed in call to + store lock. */ uint ha_partition::lock_count() const { DBUG_ENTER("ha_partition::lock_count"); - /* - The caller want to know the upper bound, to allocate enough memory. - There is no performance lost if we simply return maximum number locks - needed, only some minor over allocation of memory in get_lock_data(). - - Also notice that this may be called for another thread != table->in_use, - when mysql_lock_abort_for_thread() is called. So this is more safe, then - using number of partitions after pruning. - */ - DBUG_RETURN(m_tot_parts * m_num_locks); + DBUG_RETURN(m_num_locks); } @@ -7215,19 +7211,36 @@ int ha_partition::extra(enum ha_extra_function operation) } /* Category 9) Operations only used by MERGE */ case HA_EXTRA_ADD_CHILDREN_LIST: + DBUG_RETURN(loop_extra(operation)); case HA_EXTRA_ATTACH_CHILDREN: - case HA_EXTRA_IS_ATTACHED_CHILDREN: - case HA_EXTRA_DETACH_CHILDREN: { - /* Special actions for MERGE tables. Ignore. */ + int result; + uint num_locks= 0; + handler **file; + if ((result = loop_extra(operation))) + DBUG_RETURN(result); + + /* Recalculate lock count as each child may have different set of locks */ + num_locks = 0; + file = m_file; + do + { + num_locks+= (*file)->lock_count(); + } while (*(++file)); + + m_num_locks= num_locks; break; } + case HA_EXTRA_IS_ATTACHED_CHILDREN: + DBUG_RETURN(loop_extra(operation)); + case HA_EXTRA_DETACH_CHILDREN: + DBUG_RETURN(loop_extra(operation)); + case HA_EXTRA_MARK_AS_LOG_TABLE: /* http://dev.mysql.com/doc/refman/5.1/en/partitioning-limitations.html says we no longer support logging to partitioned tables, so we fail here. */ - case HA_EXTRA_MARK_AS_LOG_TABLE: DBUG_RETURN(ER_UNSUPORTED_LOG_ENGINE); default: { @@ -9102,6 +9115,22 @@ const COND *ha_partition::cond_push(const COND *cond) COND *res_cond = NULL; DBUG_ENTER("ha_partition::cond_push"); + if (set_top_table_fields) + { + /* + We want to do this in a separate loop to not come into a situation + where we have only done cond_push() to some of the tables + */ + do + { + if (((*file)->set_top_table_and_fields(top_table, + top_table_field, + top_table_fields))) + DBUG_RETURN(cond); // Abort cond push, no error + } while (*(++file)); + file= m_file; + } + do { if ((*file)->pushed_cond != cond) @@ -9128,6 +9157,17 @@ void ha_partition::cond_pop() DBUG_VOID_RETURN; } +void ha_partition::clear_top_table_fields() +{ + handler **file; + if (set_top_table_fields) + { + set_top_table_fields = FALSE; + for (file= m_file; *file; file++) + (*file)->clear_top_table_fields(); + } +} + struct st_mysql_storage_engine partition_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; diff --git a/sql/ha_partition.h b/sql/ha_partition.h index 60bf69c9992..08701f3f3e6 100644 --- a/sql/ha_partition.h +++ b/sql/ha_partition.h @@ -282,6 +282,10 @@ private: MY_BITMAP m_key_not_found_partitions; bool m_key_not_found; public: + handler **get_child_handlers() + { + return m_file; + } Partition_share *get_part_share() { return part_share; } handler *clone(const char *name, MEM_ROOT *mem_root); virtual void set_part_info(partition_info *part_info) @@ -1210,6 +1214,7 @@ public: */ virtual const COND *cond_push(const COND *cond); virtual void cond_pop(); + virtual void clear_top_table_fields(); private: int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, uint flags); diff --git a/sql/handler.h b/sql/handler.h index 873c66ead90..6e8a4513aec 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -267,6 +267,9 @@ enum enum_alter_inplace_result { */ #define HA_BINLOG_FLAGS (HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE) +/* The following is for partition handler */ +#define HA_CAN_MULTISTEP_MERGE (1LL << 47) + /* bits in index_flags(index_number) for what you can do with index */ #define HA_READ_NEXT 1 /* TODO really use this flag */ #define HA_READ_PREV 2 /* supports ::index_prev */ @@ -1391,6 +1394,7 @@ handlerton *ha_default_tmp_handlerton(THD *thd); #define HTON_TEMPORARY_NOT_SUPPORTED (1 << 6) //Having temporary tables not supported #define HTON_SUPPORT_LOG_TABLES (1 << 7) //Engine supports log tables #define HTON_NO_PARTITION (1 << 8) //Not partition of these tables +#define HTON_CAN_MULTISTEP_MERGE (1 << 9) //You can merge mearged tables /* This flag should be set when deciding that the engine does not allow @@ -2725,6 +2729,11 @@ public: virtual void unbind_psi(); virtual void rebind_psi(); + bool set_top_table_fields; + struct TABLE *top_table; + Field **top_table_field; + uint top_table_fields; + private: /** The lock type set by when calling::ha_external_lock(). This is @@ -2758,7 +2767,9 @@ public: pushed_idx_cond(NULL), pushed_idx_cond_keyno(MAX_KEY), auto_inc_intervals_count(0), - m_psi(NULL), m_lock_type(F_UNLCK), ha_share(NULL) + m_psi(NULL), set_top_table_fields(FALSE), top_table(0), + top_table_field(0), top_table_fields(0), + m_lock_type(F_UNLCK), ha_share(NULL) { DBUG_PRINT("info", ("handler created F_UNLCK %d F_RDLCK %d F_WRLCK %d", @@ -3576,6 +3587,36 @@ public: virtual void cond_pop() { return; }; /** + This function is used to get correlating of a parent (table/column) + and children (table/column). When conditions are pushed down to child + table (like child of myisam_merge), child table needs to know about + which table/column is my parent for understanding conditions. + */ + virtual int set_top_table_and_fields(TABLE *top_table, + Field **top_table_field, + uint top_table_fields) + { + if (!set_top_table_fields) + { + set_top_table_fields= TRUE; + this->top_table= top_table; + this->top_table_field= top_table_field; + this->top_table_fields= top_table_fields; + } + return 0; + } + virtual void clear_top_table_fields() + { + if (set_top_table_fields) + { + set_top_table_fields= FALSE; + top_table= NULL; + top_table_field= NULL; + top_table_fields= 0; + } + } + + /** Push down an index condition to the handler. The server will use this method to push down a condition it wants diff --git a/sql/sql_base.cc b/sql/sql_base.cc index ac4b8a45107..5eade2994ee 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1079,14 +1079,32 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, table= table->find_table_for_update(); - if (table->table && table->table->file->ht->db_type == DB_TYPE_MRG_MYISAM) + if (table->table && + table->table->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) { TABLE_LIST *child; dup= NULL; /* Check duplicates of all merge children. */ - for (child= table->next_global; child && child->parent_l == table; + for (child= table->next_global; child; child= child->next_global) { + if (child->table && + child->table->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) + continue; + + /* + Ensure that the child has one parent that is the table that is + updated. + */ + TABLE_LIST *tmp_parent= child; + while ((tmp_parent= tmp_parent->parent_l)) + { + if (tmp_parent == table) + break; + } + if (!tmp_parent) + break; + if ((dup= find_dup_table(thd, child, child->next_global, check_alias))) break; } @@ -1095,6 +1113,8 @@ unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, dup= find_dup_table(thd, table, table_list, check_alias); return dup; } + + /* Issue correct error message in case we found 2 duplicate tables which prevent some update operation @@ -4039,7 +4059,7 @@ restart: continue; /* Schema tables may not have a TABLE object here. */ - if (tbl->file->ht->db_type == DB_TYPE_MRG_MYISAM) + if (tbl->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) { /* MERGE tables need to access parent and child TABLE_LISTs. */ DBUG_ASSERT(tbl->pos_in_table_list == tables); @@ -4584,7 +4604,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, */ DBUG_ASSERT(table_list->table); table= table_list->table; - if (table->file->ht->db_type == DB_TYPE_MRG_MYISAM) + if (table->file->ha_table_flags() & HA_CAN_MULTISTEP_MERGE) { /* A MERGE table must not come here. */ /* purecov: begin tested */ diff --git a/storage/myisammrg/ha_myisammrg.h b/storage/myisammrg/ha_myisammrg.h index b6db549119d..3ff10406d59 100644 --- a/storage/myisammrg/ha_myisammrg.h +++ b/storage/myisammrg/ha_myisammrg.h @@ -91,7 +91,7 @@ public: HA_ANY_INDEX_MAY_BE_UNIQUE | HA_CAN_BIT_FIELD | HA_HAS_RECORDS | HA_CAN_EXPORT | HA_NO_COPY_ON_ALTER | - HA_DUPLICATE_POS); + HA_DUPLICATE_POS | HA_CAN_MULTISTEP_MERGE); } ulong index_flags(uint inx, uint part, bool all_parts) const { |