From 23cd6c5feb410d29c577d2070755c4fa180d189c Mon Sep 17 00:00:00 2001 From: PeterWeiWang <715533650@qq.com> Date: Tue, 22 Feb 2022 19:42:52 +0800 Subject: [PATCH] support for parallel queries - add ParallelScanIterator. - add PQblockScanIterator. --- sql/basic_row_iterators.h | 76 ++++++++ sql/composite_iterators.cc | 15 +- sql/composite_iterators.h | 20 +++ sql/exchange_sort.h | 6 +- sql/filesort.cc | 120 ++++++++++++- sql/filesort.h | 7 +- sql/handler.cc | 71 ++++++++ sql/handler.h | 60 ++++++- sql/item.cc | 144 ++++++++------- sql/item.h | 171 ++++++++++++++++-- sql/item_cmpfunc.cc | 2 + sql/item_cmpfunc.h | 66 +++++++ sql/item_func.cc | 34 +++- sql/item_func.h | 103 ++++++++++- sql/item_geofunc.h | 24 +++ sql/item_inetfunc.h | 9 + sql/item_json_func.h | 8 + sql/item_pfs_func.h | 4 + sql/item_regexp_func.h | 5 + sql/item_row.h | 3 + sql/item_strfunc.h | 71 +++++++- sql/item_subselect.cc | 3 +- sql/item_sum.cc | 184 +++++++++++++++---- sql/item_sum.h | 88 +++++++-- sql/item_timefunc.h | 61 +++++++ sql/item_xmlfunc.h | 2 + sql/records.cc | 353 ++++++++++++++++++++++++++++++++++++- sql/row_iterator.h | 9 + sql/sorting_iterator.h | 3 + 29 files changed, 1574 insertions(+), 148 deletions(-) diff --git a/sql/basic_row_iterators.h b/sql/basic_row_iterators.h index bba4d07a2f99..cd9479cbd50a 100644 --- a/sql/basic_row_iterators.h +++ b/sql/basic_row_iterators.h @@ -2,6 +2,7 @@ #define SQL_BASIC_ROW_ITERATORS_H_ /* Copyright (c) 2018, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -41,6 +42,7 @@ #include "sql/mem_root_array.h" #include "sql/row_iterator.h" #include "sql/sql_list.h" +#include "filesort.h" class Filesort_info; class Item; @@ -50,6 +52,80 @@ class THD; class handler; struct IO_CACHE; struct TABLE; +class Gather_operator; +class ORDER; +class MQ_record_gather; +class QEP_TAB; + +/** + * Parallel scan iterator, which is used in parallel leader + */ +class ParallelScanIterator final : public TableRowIterator { + public: + ParallelScanIterator(THD *thd, QEP_TAB *tab, TABLE *table, + ha_rows *examined_rows, JOIN *join, + Gather_operator *gather, bool stab_output = false, + uint ref_length = 0); + + ~ParallelScanIterator() override; + + bool Init() override; + int Read() override; + int End() override; + void UnlockRow() override {} + void SetNullRowFlag(bool) override {} + void StartPSIBatchMode() override {} + void EndPSIBatchModeIfStarted() override {} + + private: + uchar *const m_record; + ha_rows *const m_examined_rows; + uint m_dop; + JOIN *m_join; + Gather_operator *m_gather; + MQ_record_gather *m_record_gather; + ORDER *m_order; /** use for records merge sort */ + QEP_TAB *m_tab; + bool m_stable_sort; /** determine whether using stable sort */ + uint m_ref_length; + + /** construct filesort on leader when needing stab_output or merge_sort */ + bool pq_make_filesort(Filesort **sort); + /** init m_record_gather */ + bool pq_init_record_gather(); + /** launch worker threads to execute parallel query */ + bool pq_launch_worker(); + /** wait all workers finished */ + void pq_wait_workers_finished(); + /** outoput parallel query error code */ + int pq_error_code(); +}; + +class PQ_worker_manager; + +/** + * block scan iterator, which is used is in parallel worker. + * a whole talbe is cut into many blocks for parallel scan + */ +class PQblockScanIterator final : public TableRowIterator { + public: + PQblockScanIterator(THD *thd, TABLE *table, uchar *record, + ha_rows *examined_rows, Gather_operator *gather, + bool need_rowid = false); + ~PQblockScanIterator() override; + + bool Init() override; + int Read() override; + int End() override; + + private: + uchar *const m_record; + ha_rows *const m_examined_rows; + void *m_pq_ctx; // parallel query context + uint keyno; + Gather_operator *m_gather; + bool m_need_rowid; +}; /** Scan a table from beginning to end. diff --git a/sql/composite_iterators.cc b/sql/composite_iterators.cc index dff62b694f82..0d69b992d29c 100644 --- a/sql/composite_iterators.cc +++ b/sql/composite_iterators.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2018, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -179,6 +180,10 @@ int LimitOffsetIterator::Read() { return result; } +int LimitOffsetIterator::End() { + return m_source->End(); +} + AggregateIterator::AggregateIterator( THD *thd, unique_ptr_destroy_only source, JOIN *join, TableCollection tables, bool rollup) @@ -193,7 +198,7 @@ AggregateIterator::AggregateIterator( } bool AggregateIterator::Init() { - assert(!m_join->tmp_table_param.precomputed_group_by); + assert(!m_join->tmp_table_param->precomputed_group_by); // Disable any leftover rollup items used in children. m_current_rollup_position = -1; @@ -214,6 +219,10 @@ bool AggregateIterator::Init() { return false; } +int AggregateIterator::End() { + return m_source->End(); +} + int AggregateIterator::Read() { switch (m_state) { case READING_FIRST_ROW: { @@ -1187,6 +1196,10 @@ int TemptableAggregateIterator::Read() { return m_table_iterator->Read(); } +int TemptableAggregateIterator::End() { + return m_subquery_iterator->End(); +} + MaterializedTableFunctionIterator::MaterializedTableFunctionIterator( THD *thd, Table_function *table_function, TABLE *table, unique_ptr_destroy_only table_iterator) diff --git a/sql/composite_iterators.h b/sql/composite_iterators.h index 7e1b31fc9dda..9bff5e443415 100644 --- a/sql/composite_iterators.h +++ b/sql/composite_iterators.h @@ -2,6 +2,7 @@ #define SQL_COMPOSITE_ITERATORS_INCLUDED /* Copyright (c) 2018, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -81,6 +82,8 @@ class FilterIterator final : public RowIterator { int Read() override; + int End() override { return m_source->End(); } + void SetNullRowFlag(bool is_null_row) override { m_source->SetNullRowFlag(is_null_row); } @@ -135,6 +138,8 @@ class LimitOffsetIterator final : public RowIterator { int Read() override; + int End() override; + void SetNullRowFlag(bool is_null_row) override { m_source->SetNullRowFlag(is_null_row); } @@ -205,6 +210,8 @@ class AggregateIterator final : public RowIterator { bool Init() override; int Read() override; + int End() override; + void SetNullRowFlag(bool is_null_row) override { m_source->SetNullRowFlag(is_null_row); } @@ -535,6 +542,13 @@ class MaterializeIterator final : public TableRowIterator { bool Init() override; int Read() override; + int End() override { + for (auto &qb : m_query_blocks_to_materialize) { + qb.subquery_iterator->End(); + } + return thd()->is_worker() ? -1 : 1; + } + void SetNullRowFlag(bool is_null_row) override { m_table_iterator->SetNullRowFlag(is_null_row); } @@ -654,6 +668,10 @@ class StreamingIterator final : public TableRowIterator { int Read() override; + int End() override { + return m_subquery_iterator->End(); + } + void StartPSIBatchMode() override { m_subquery_iterator->StartPSIBatchMode(); } @@ -691,6 +709,8 @@ class TemptableAggregateIterator final : public TableRowIterator { bool Init() override; int Read() override; + int End() override; + void SetNullRowFlag(bool is_null_row) override { m_table_iterator->SetNullRowFlag(is_null_row); } diff --git a/sql/exchange_sort.h b/sql/exchange_sort.h index 608fb5380512..704709183d34 100644 --- a/sql/exchange_sort.h +++ b/sql/exchange_sort.h @@ -110,7 +110,7 @@ class Exchange_sort : public Exchange { /** get the k-th record in m_min_records */ mq_record_st *get_record(int k) { - DBUG_ASSERT(0 <= k && k < lanuch_workers()); + assert(0 <= k && k < lanuch_workers()); mq_record_st *record = m_min_records[k]; return record; } @@ -120,12 +120,12 @@ class Exchange_sort : public Exchange { inline const Filesort *get_filesort() { return m_sort; } inline uchar *get_row_id(int i) { - DBUG_ASSERT(0 <= i && i < 2); + assert(0 <= i && i < 2); return row_id[i]; } inline uchar *get_key(int i) { - DBUG_ASSERT(0 <= i && i < 2); + assert(0 <= i && i < 2); return keys[i]; } diff --git a/sql/filesort.cc b/sql/filesort.cc index 725ee0fedf75..0c136c5e40b8 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -77,6 +78,7 @@ #include "sql/debug_sync.h" #include "sql/derror.h" #include "sql/error_handler.h" +#include "sql/exchange_sort.h" #include "sql/field.h" #include "sql/filesort_utils.h" #include "sql/handler.h" @@ -601,8 +603,7 @@ bool filesort(THD *thd, Filesort *filesort, RowIterator *source_iterator, else sort_mode.append("fixed_sort_key"); sort_mode.append(", "); - sort_mode.append(param->using_packed_addons() - ? "packed_additional_fields" + sort_mode.append(param->using_packed_addons() ? "packed_additional_fields" : param->using_addon_fields() ? "additional_fields" : "rowid"); sort_mode.append(">"); @@ -683,6 +684,7 @@ Filesort::Filesort(THD *thd, Mem_root_array tables_arg, bool sort_positions, bool unwrap_rollup) : m_thd(thd), tables(std::move(tables_arg)), + m_order(order), keep_buffers(keep_buffers_arg), limit(limit_arg), sortorder(nullptr), @@ -691,7 +693,11 @@ Filesort::Filesort(THD *thd, Mem_root_array
tables_arg, force_stable_sort), // keep relative order of equiv. elts m_remove_duplicates(remove_duplicates), m_force_sort_positions(sort_positions), - m_sort_order_length(make_sortorder(order, unwrap_rollup)) {} + m_sort_order_length(0) { + if (order) { + m_sort_order_length = make_sortorder(order, unwrap_rollup); + } + } uint Filesort::make_sortorder(ORDER *order, bool unwrap_rollup) { uint count; @@ -2314,3 +2320,111 @@ void change_double_for_sort(double nr, uchar *to) { swap(to[3], to[4]); #endif } + +/** + * compare table->record[0] of two workers in PQ_merge_sort + * @a: the ID of first worker + * @b: the ID of second worker + * @arg: PQ_merge sort + * @return + * true if a's record is less than b's record; + * false otherwise. + */ +bool heap_compare_records(int a, int b, void *arg) { + assert(arg); + bool convert_res; + + Exchange_sort *merge_sort = static_cast(arg); + const Filesort *filesort = merge_sort->get_filesort(); + THD *thd = merge_sort->get_thd(); + assert(filesort && current_thd == thd); + + uchar *row_id_0 = merge_sort->get_row_id(0); + uchar *row_id_1 = merge_sort->get_row_id(1); + uchar *key_0 = merge_sort->get_key(0); + uchar *key_1 = merge_sort->get_key(1); + + /** using previous old table when comparing row_id (or PK) */ + handler *file = merge_sort->get_file(); + assert(file->ht->db_type == DB_TYPE_INNODB); +#if !defined(NDEBUG) + uint ref_len = merge_sort->ref_length(); + assert(ref_len == file->ref_length); +#endif + bool force_stable_sort = merge_sort->is_stable(); + + Sort_param *sort_param = merge_sort->get_sort_param(); + int key_len = 0, compare_len = 0; + + if (sort_param) { + key_len = sort_param->max_record_length() + 1; + compare_len = sort_param->max_compare_length(); + } + + /** + * the compare process contains the following three steps: + * 1. copy to table->record[0] + * 2. add row_id info. + * 3. generate sort key + */ + mq_record_st *compare_a = merge_sort->get_record(a); + convert_res = merge_sort->convert_mq_data_to_record( + compare_a->m_data, compare_a->m_length, row_id_0); + + // there is an error during execution + if (!convert_res || DBUG_EVALUATE_IF("pq_msort_error6", true, false)) { + thd->pq_error = true; + return true; + } + + /* + * using row_id to achieve stable sort, i.e., + * record1 < record2 <=> key1 < key2 or (key1 = key2 && row_id1 < row_id2) + */ + if (sort_param) { + sort_param->make_sortkey(key_0, key_len, filesort->tables); + } + + mq_record_st *compare_b = merge_sort->get_record(b); + convert_res = merge_sort->convert_mq_data_to_record( + compare_b->m_data, compare_b->m_length, row_id_1); + + // there is an error during execution + if (!convert_res || DBUG_EVALUATE_IF("pq_msort_error7", true, false)) { + thd->pq_error = true; + return true; + } + + if (sort_param) { + sort_param->make_sortkey(key_1, key_len, filesort->tables); + } + + // c1: table scan (or index scan with optimized order = nullptr) + if (!filesort->sortorder) { + assert(sort_param == nullptr && force_stable_sort); + assert(row_id_0 && row_id_1); + return file->cmp_ref(row_id_0, row_id_1) < 0; + } else { + int cmp_key_result; + // c2: with order + if (sort_param != nullptr && sort_param->using_varlen_keys()) { + cmp_varlen_keys(sort_param->local_sortorder, sort_param->use_hash, key_0, + key_1, &cmp_key_result); + if (!force_stable_sort) { + return cmp_key_result < 0; + } else { + assert(row_id_0 && row_id_1); + return (cmp_key_result < 0 || + (cmp_key_result == 0 && file->cmp_ref(row_id_0, row_id_1) < 0)); + } + } else { + int cmp = memcmp(key_0, key_1, compare_len); + if (!force_stable_sort) { + return cmp < 0; + } else { + assert(row_id_0 && row_id_1); + return (cmp < 0 || (cmp == 0 && file->cmp_ref(row_id_0, row_id_1) < 0)); + } + } + } +} diff --git a/sql/filesort.h b/sql/filesort.h index 7197ee875e38..6c7ce384aa47 100644 --- a/sql/filesort.h +++ b/sql/filesort.h @@ -1,4 +1,5 @@ /* Copyright (c) 2006, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -53,6 +54,8 @@ class Filesort { THD *m_thd; /// The tables we are sorting. Mem_root_array
tables; + /// list of expressions to order the table by + ORDER *m_order; /// If true, do not free the filesort buffers (use if you expect to sort many /// times, like in an uncacheable subquery). const bool keep_buffers; @@ -96,10 +99,10 @@ class Filesort { /// circumstances (see NewWeedoutAccessPathForTables()). void clear_addon_fields(); - private: /* Prepare ORDER BY list for sorting. */ uint make_sortorder(ORDER *order, bool unwrap_rollup); - + + private: uint m_sort_order_length; }; diff --git a/sql/handler.cc b/sql/handler.cc index 9219a8729679..6d4a8873e8a8 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -2942,6 +2943,30 @@ int handler::ha_rnd_init(bool scan) { return result; } +int handler::ha_pq_init(uint &dop, uint keyno) { + DBUG_EXECUTE_IF("ha_pq_init_fail", return HA_ERR_TABLE_DEF_CHANGED;); + int result; + DBUG_ENTER("handler::ha_pq_init"); + assert(table_share->tmp_table != NO_TMP_TABLE || m_lock_type != F_UNLCK); + assert(inited == NONE || inited == INDEX || (inited == PQ_LEADER)); + THD *cur_thd = table->in_use; + inited = (result = pq_leader_scan_init(keyno, cur_thd->pq_ctx, dop)) + ? NONE + : PQ_LEADER; + end_range = NULL; + pq_ref = false; + pq_reverse_scan = false; + DBUG_RETURN(result); +} + +int handler::ha_pq_signal_all() { + DBUG_ENTER("handler::ha_pq_signal_all"); + int result; + THD *cur_thd = table->in_use; + result = pq_leader_signal_all(cur_thd->pq_ctx); + DBUG_RETURN(result); +} + /** End use of random access. @@ -2959,9 +2984,25 @@ int handler::ha_rnd_end() { inited = NONE; end_range = nullptr; m_record_buffer = nullptr; + pq_range_type = PQ_QUICK_SELECT_NONE; return rnd_end(); } +int handler::ha_pq_end() { + DBUG_ENTER("handler::ha_pq_end"); + + if(pq_table_scan){ + inited = RND; + ha_rnd_end(); + } else { + inited = INDEX; + ha_index_end(); + } + + THD *thd = current_thd; + DBUG_RETURN(pq_leader_scan_end(thd->pq_ctx)); +} + /** Read next row via random scan. @@ -2992,6 +3033,28 @@ int handler::ha_rnd_next(uchar *buf) { return result; } +int handler::ha_pq_next(uchar *buf, void *scan_ctx) { + int result; + DBUG_EXECUTE_IF("ha_pq_next_deadlock", return HA_ERR_LOCK_DEADLOCK;); + DBUG_ENTER("handler::ha_pq_next"); + assert(table_share->tmp_table != NO_TMP_TABLE || m_lock_type != F_UNLCK); + + // Set status for the need to update generated fields + m_update_generated_read_fields = table->has_gcol(); + + MYSQL_TABLE_IO_WAIT(PSI_TABLE_FETCH_ROW, + pq_table_scan ? MAX_KEY : active_index, result, + { result = pq_worker_scan_next(scan_ctx, buf); }) + if (!result && m_update_generated_read_fields) { + result = update_generated_read_fields( + buf, table, pq_table_scan ? MAX_KEY : active_index); + m_update_generated_read_fields = false; + } + + table->set_row_status_from_handler(result); + DBUG_RETURN(result); +} + /** Read row via random scan from position. @@ -6456,6 +6519,14 @@ int DsMrr_impl::dsmrr_init(RANGE_SEQ_IF *seq_funcs, void *seq_init_param, return retval; } + if (!thd->in_sp_trigger && thd->parallel_exec && + table->file->pq_range_type != PQ_QUICK_SELECT_NONE) { + use_default_impl = true; + retval = h->handler::multi_range_read_init(seq_funcs, seq_init_param, + n_ranges, mode, buf); + return retval; + } + /* This assert will hit if we have pushed an index condition to the primary key index and then "change our mind" and use a different diff --git a/sql/handler.h b/sql/handler.h index 76e55abc9ab3..81d90037867d 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -3,6 +3,7 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -69,6 +70,7 @@ #include "sql/sql_plugin_ref.h" // plugin_ref #include "thr_lock.h" // thr_lock_type #include "typelib.h" +#include "pq_range.h" class Alter_info; class Create_field; @@ -4134,6 +4136,12 @@ class handler { ha_rows estimation_rows_to_insert; public: + uint pq_range_type{0}; + key_range pq_ref_key; + bool pq_ref{false}; + bool pq_table_scan{false}; + bool pq_reverse_scan{false}; + handlerton *ht; /* storage engine of this handler */ /** Pointer to current row */ uchar *ref; @@ -4206,7 +4214,7 @@ class handler { /** Length of ref (1-8 or the clustered key length) */ uint ref_length; FT_INFO *ft_handler; - enum { NONE = 0, INDEX, RND, SAMPLING } inited; + enum { NONE = 0, INDEX, RND, SAMPLING, PQ_LEADER, PQ_WORKER } inited; bool implicit_emptied; /* Can be !=0 only if HEAP */ const Item *pushed_cond; @@ -4442,8 +4450,12 @@ class handler { int ha_index_init(uint idx, bool sorted); int ha_index_end(); int ha_rnd_init(bool scan); + int ha_pq_init(uint &dop, uint keyno); int ha_rnd_end(); + int ha_pq_end(); + int ha_pq_signal_all(); int ha_rnd_next(uchar *buf); + int ha_pq_next(uchar *buf, void *scan_ctx); // See the comment on m_update_generated_read_fields. int ha_rnd_pos(uchar *buf, uchar *pos); int ha_index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map, @@ -4461,7 +4473,23 @@ class handler { int ha_reset(); /* this is necessary in many places, e.g. in HANDLER command */ int ha_index_or_rnd_end() { - return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0; + switch (inited) + { + case INDEX: + return ha_index_end(); + break; + case RND: + return ha_rnd_end(); + break; + case PQ_LEADER: + return ha_pq_end(); + break; + case PQ_WORKER: + return pq_worker_scan_end(nullptr); + break; + default: + return 0; + } } /** The cached_table_flags is set at ha_open and ha_external_lock @@ -4515,6 +4543,10 @@ class handler { int ha_unload_table(const char *db_name, const char *table_name, bool error_if_not_loaded); + virtual int pq_leader_signal_all(void *scan_ctx MY_ATTRIBUTE((unused))) { + return (0); + } + /** Initializes a parallel scan. It creates a parallel_scan_ctx that has to be used across all parallel_scan methods. Also, gets the number of @@ -4535,6 +4567,17 @@ class handler { return 0; } + virtual int pq_leader_scan_init(uint keyno MY_ATTRIBUTE((unused)), + void *&scan_ctx MY_ATTRIBUTE((unused)), + uint &n_threads MY_ATTRIBUTE((unused))) { + return (0); + } + + virtual int pq_worker_scan_init(uint keyno MY_ATTRIBUTE((unused)), + void *scan_ctx MY_ATTRIBUTE((unused))) { + return (0); + } + /** This callback is called by each parallel load thread at the beginning of the parallel load for the adapter scan. @@ -4601,6 +4644,11 @@ class handler { return 0; } + virtual int pq_worker_scan_next(void *scan_ctx MY_ATTRIBUTE((unused)), + uchar* buf MY_ATTRIBUTE((unused))) { + return (0); + } + /** End of the parallel scan. @param[in] scan_ctx A scan context created by parallel_scan_init. @@ -4609,6 +4657,14 @@ class handler { return; } + virtual int pq_leader_scan_end(void *parallel_scan_ctx MY_ATTRIBUTE((unused))) { + return (0); + } + + virtual int pq_worker_scan_end(void *parallel_scan_ctx MY_ATTRIBUTE((unused))) { + return (0); + } + /** Submit a dd::Table object representing a core DD table having hardcoded data to be filled in by the DDSE. This function can be diff --git a/sql/item.cc b/sql/item.cc index cad56f47d940..cd9f2d7cd56e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,5 +1,6 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -174,7 +175,11 @@ Item::Item(THD *thd, const Item *item) derived_used(item->derived_used), m_accum_properties(item->m_accum_properties) { #ifndef NDEBUG - assert(item->contextualized); + /* + PQ will build a tmp table to store result, so the origin item of tmp item + which is created by resolvation could be uncontextualized. + */ + assert(thd->parallel_exec || item->contextualized); contextualized = true; #endif // NDEBUG @@ -1964,45 +1969,12 @@ void Item_name_const::print(const THD *thd, String *str, str->append(')'); } -/* - need a special class to adjust printing : references to aggregate functions - must not be printed as refs because the aggregate functions that are added to - the front of select list are not printed as well. -*/ -class Item_aggregate_ref : public Item_ref { - public: - Item_aggregate_ref(Name_resolution_context *context_arg, Item **item, - const char *db_name_arg, const char *table_name_arg, - const char *field_name_arg, Query_block *depended_from_arg) - : Item_ref(context_arg, item, db_name_arg, table_name_arg, - field_name_arg) { - depended_from = depended_from_arg; - } - - void print(const THD *thd, String *str, - enum_query_type query_type) const override { - if (ref) - (*ref)->print(thd, str, query_type); - else - Item_ident::print(thd, str, query_type); - } - Ref_Type ref_type() const override { return AGGREGATE_REF; } - - /** - Walker processor used by Query_block::transform_grouped_to_derived to - replace an aggregate's reference to one in the new derived table's (hidden) - select list. - - @param arg An info object of type Item::Aggregate_ref_update - @returns false - */ - bool update_aggr_refs(uchar *arg) override { - auto *info = pointer_cast(arg); - if (*ref != info->m_target) return false; - ref = info->m_owner->add_hidden_item(info->m_target); - return false; - } -}; +bool Item_aggregate_ref::update_aggr_refs(uchar *arg) { + auto *info = pointer_cast(arg); + if (*ref != info->m_target) return false; + ref = info->m_owner->add_hidden_item(info->m_target); + return false; +} /** 1. Move SUM items out from item tree and replace with reference. @@ -2948,6 +2920,16 @@ my_decimal *Item_field::val_decimal(my_decimal *decimal_value) { return field->val_decimal(decimal_value); } +const uchar *Item_field::val_extra(uint32 *len) { + assert(len != nullptr); + *len = field->extra_length; + if (*len == 0) { + return nullptr; + } + + return (field->ptr + field->pack_length() - *len); +} + bool Item_field::get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) { if ((null_value = field->is_null()) || field->get_date(ltime, fuzzydate)) { memset(ltime, 0, sizeof(*ltime)); @@ -4696,7 +4678,7 @@ static Item **find_field_in_group_list(Item *find_item, ORDER *group_list) { - resolved item - if the item was resolved */ -static Item **resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, +Item **resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, Query_block *select) { DBUG_TRACE; Item **select_ref = nullptr; @@ -5880,27 +5862,29 @@ bool Item::eq_by_collation(Item *item, bool binary_cmp, @param table Table for which the field is created */ -Field *Item::make_string_field(TABLE *table) const { +Field *Item::make_string_field(TABLE *table, MEM_ROOT *root) const { Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; + assert(collation.collation); if (data_type() == MYSQL_TYPE_JSON) field = - new (*THR_MALLOC) Field_json(max_length, m_nullable, item_name.ptr()); + new (pq_check_root) Field_json(max_length, m_nullable, item_name.ptr()); else if (data_type() == MYSQL_TYPE_GEOMETRY) { - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_geom(max_length, m_nullable, item_name.ptr(), Field::GEOM_GEOMETRY, Nullable()); } else if (max_length / collation.collation->mbmaxlen > CONVERT_IF_BIGGER_TO_BLOB) - field = new (*THR_MALLOC) Field_blob( + field = new (pq_check_root) Field_blob( max_length, m_nullable, item_name.ptr(), collation.collation, true); /* Item_type_holder holds the exact type, do not change it */ else if (max_length > 0 && (type() != Item::TYPE_HOLDER || data_type() != MYSQL_TYPE_STRING)) - field = new (*THR_MALLOC) Field_varstring( + field = new (pq_check_root) Field_varstring( max_length, m_nullable, item_name.ptr(), table->s, collation.collation); else - field = new (*THR_MALLOC) Field_string( + field = new (pq_check_root) Field_string( max_length, m_nullable, item_name.ptr(), collation.collation); if (field) field->init(table); return field; @@ -5917,67 +5901,69 @@ Field *Item::make_string_field(TABLE *table) const { */ Field *Item::tmp_table_field_from_field_type(TABLE *table, - bool fixed_length) const { + bool fixed_length, + MEM_ROOT *root) const { /* The field functions defines a field to be not null if null_ptr is not 0 */ Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; switch (data_type()) { case MYSQL_TYPE_DECIMAL: case MYSQL_TYPE_NEWDECIMAL: - field = Field_new_decimal::create_from_item(this); + field = Field_new_decimal::create_from_item(this, root); break; case MYSQL_TYPE_TINY: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_tiny(max_length, m_nullable, item_name.ptr(), unsigned_flag); break; case MYSQL_TYPE_SHORT: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_short(max_length, m_nullable, item_name.ptr(), unsigned_flag); break; case MYSQL_TYPE_LONG: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_long(max_length, m_nullable, item_name.ptr(), unsigned_flag); break; case MYSQL_TYPE_LONGLONG: - field = new (*THR_MALLOC) Field_longlong(max_length, m_nullable, + field = new (pq_check_root) Field_longlong(max_length, m_nullable, item_name.ptr(), unsigned_flag); break; case MYSQL_TYPE_FLOAT: - field = new (*THR_MALLOC) Field_float( + field = new (pq_check_root) Field_float( max_length, m_nullable, item_name.ptr(), decimals, unsigned_flag); break; case MYSQL_TYPE_DOUBLE: - field = new (*THR_MALLOC) Field_double( + field = new (pq_check_root) Field_double( max_length, m_nullable, item_name.ptr(), decimals, unsigned_flag); break; case MYSQL_TYPE_INT24: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_medium(max_length, m_nullable, item_name.ptr(), unsigned_flag); break; case MYSQL_TYPE_DATE: case MYSQL_TYPE_NEWDATE: - field = new (*THR_MALLOC) Field_newdate(m_nullable, item_name.ptr()); + field = new (pq_check_root) Field_newdate(m_nullable, item_name.ptr()); break; case MYSQL_TYPE_TIME: field = - new (*THR_MALLOC) Field_timef(m_nullable, item_name.ptr(), decimals); + new (pq_check_root) Field_timef(m_nullable, item_name.ptr(), decimals); break; case MYSQL_TYPE_TIMESTAMP: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_timestampf(m_nullable, item_name.ptr(), decimals); break; case MYSQL_TYPE_DATETIME: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_datetimef(m_nullable, item_name.ptr(), decimals); break; case MYSQL_TYPE_YEAR: assert(max_length == 4); // Field_year is only for length 4. - field = new (*THR_MALLOC) Field_year(m_nullable, item_name.ptr()); + field = new (pq_check_root) Field_year(m_nullable, item_name.ptr()); break; case MYSQL_TYPE_BIT: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_bit_as_char(max_length, m_nullable, item_name.ptr()); break; case MYSQL_TYPE_INVALID: @@ -5990,7 +5976,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, case MYSQL_TYPE_STRING: case MYSQL_TYPE_NULL: if (fixed_length && max_length <= CONVERT_IF_BIGGER_TO_BLOB) { - field = new (*THR_MALLOC) Field_string( + field = new (pq_check_root) Field_string( max_length, m_nullable, item_name.ptr(), collation.collation); break; } @@ -5999,26 +5985,26 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table, case MYSQL_TYPE_SET: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VARCHAR: - return make_string_field(table); + return make_string_field(table, root); case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_BLOB: if (this->type() == Item::TYPE_HOLDER) - field = new (*THR_MALLOC) Field_blob( + field = new (pq_check_root) Field_blob( max_length, m_nullable, item_name.ptr(), collation.collation, true); else - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_blob(max_length, m_nullable, item_name.ptr(), collation.collation, false); break; // Blob handled outside of case case MYSQL_TYPE_GEOMETRY: - field = new (*THR_MALLOC) Field_geom( + field = new (pq_check_root) Field_geom( max_length, m_nullable, item_name.ptr(), get_geometry_type(), {}); break; case MYSQL_TYPE_JSON: field = - new (*THR_MALLOC) Field_json(max_length, m_nullable, item_name.ptr()); + new (pq_check_root) Field_json(max_length, m_nullable, item_name.ptr()); } if (field) field->init(table); return field; @@ -6037,6 +6023,10 @@ void Item_field::make_field(Send_field *tmp_field) { tmp_field->org_col_name = m_orig_field_name != nullptr ? m_orig_field_name : ""; tmp_field->field = true; + if (ref) { + tmp_field->org_col_name = ref_col_name; + tmp_field->org_table_name = orig_table_name(); + } } /** @@ -6138,6 +6128,10 @@ type_conversion_status Item::save_in_field(Field *field, bool no_conversions) { type_conversion_status Item::save_in_field_inner(Field *field, bool no_conversions) { + uint32 extra_len; + const uchar *extra = val_extra(&extra_len); + field->store_extra(extra, extra_len); + // Storing of arrays should be handled by specialized subclasses. assert(!returns_array()); @@ -7427,7 +7421,8 @@ Item_ref::Item_ref(Name_resolution_context *context_arg, Item **item, const char *db_name_arg, const char *table_name_arg, const char *field_name_arg, bool alias_of_expr_arg) : Item_ident(context_arg, db_name_arg, table_name_arg, field_name_arg), - ref(item) { + ref(item), + copy_type(WITH_CONTEXT_REF) { m_alias_of_expr = alias_of_expr_arg; /* This constructor used to create some internals references over fixed items @@ -9824,16 +9819,17 @@ uint32 Item_aggregate_type::display_length(Item *item) { created field */ -Field *Item_aggregate_type::make_field_by_type(TABLE *table, bool strict) { +Field *Item_aggregate_type::make_field_by_type(TABLE *table, bool strict, MEM_ROOT *root) { /* The field functions defines a field to be not null if null_ptr is not 0 */ Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; switch (data_type()) { case MYSQL_TYPE_ENUM: assert(m_typelib != nullptr); - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_enum(max_length, is_nullable(), item_name.ptr(), get_enum_pack_length(m_typelib->count), m_typelib, collation.collation); @@ -9841,17 +9837,17 @@ Field *Item_aggregate_type::make_field_by_type(TABLE *table, bool strict) { break; case MYSQL_TYPE_SET: assert(m_typelib != nullptr); - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_set(max_length, is_nullable(), item_name.ptr(), get_set_pack_length(m_typelib->count), m_typelib, collation.collation); if (field) field->init(table); break; case MYSQL_TYPE_NULL: - field = make_string_field(table); + field = make_string_field(table, root); break; default: - field = tmp_table_field_from_field_type(table, false); + field = tmp_table_field_from_field_type(table, false, root); break; } if (field == nullptr) return nullptr; diff --git a/sql/item.h b/sql/item.h index 62abaddc46c6..a54c7955439e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,6 +2,7 @@ #define ITEM_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -69,6 +70,7 @@ #include "sql/trigger_def.h" // enum_trigger_variable_type #include "sql_string.h" #include "template_utils.h" +#include "sql_class.h" class Item; class Item_field; @@ -86,6 +88,9 @@ typedef Bounds_checked_array Ref_item_array; void item_init(void); /* Init item functions */ +/** this item needs extra bytes for storing count info. */ +extern bool need_extra(Item_sum *ref_item); + /** Default condition filtering (selectivity) values used by get_filtering_effect() and friends when better estimates @@ -779,6 +784,26 @@ class Item : public Parse_tree_node { friend class udf_handler; virtual bool is_expensive_processor(uchar *) { return false; } + public: + /** + During resolve/optimize phase, a item maybe subsituted by a new one, for example + convert_constant_item()/resolve_const_item(), this point to old item for new item. + */ + Item *origin_item{nullptr}; + + /** + During create_tmp_table, const_item can be skipped when hidden_field_count <= 0; + and thus, these skipped items will not create result_field in tmp table. Here, we + should mark it when sending data to MQ. + */ + bool skip_create_tmp_table{false}; + + /** + During itemize (or new item()), some item are added to THD::m_item_list for ease of + releasing the space allocated at runtime. + */ + bool pq_alloc_item{false}; + protected: /** Sets the result value of the function an empty string, using the current @@ -1007,6 +1032,18 @@ class Item : public Parse_tree_node { */ Item(THD *thd, const Item *item); + virtual Item *pq_clone(THD *thd, Query_block *select); + + virtual bool pq_copy_from(THD *thd, Query_block *select, Item *item); + + virtual size_t pq_extra_len(bool) { return 0; } + + virtual const uchar *val_extra(uint32 *len) { + assert(len != nullptr); + *len = 0; + return nullptr; + } + /** Parse-time context-independent constructor. @@ -1098,7 +1135,7 @@ class Item : public Parse_tree_node { */ virtual void notify_removal() {} virtual void make_field(Send_field *field); - virtual Field *make_string_field(TABLE *table) const; + virtual Field *make_string_field(TABLE *table, MEM_ROOT *root = nullptr) const; virtual bool fix_fields(THD *, Item **); /** Fix after tables have been moved from one query_block level to the parent @@ -2845,7 +2882,7 @@ class Item : public Parse_tree_node { // used in row subselects to get value of elements virtual void bring_value() {} - Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length) const; + Field *tmp_table_field_from_field_type(TABLE *table, bool fixed_length, MEM_ROOT *root = nullptr) const; virtual Item_field *field_for_view_update() { return nullptr; } /** Informs an item that it is wrapped in a truth test, in case it wants to @@ -3419,6 +3456,8 @@ class Item_basic_constant : public Item { } bool basic_const_item() const override { return true; } void set_str_value(String *str) { str_value = *str; } + + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; }; /***************************************************************************** @@ -3632,6 +3671,9 @@ class Item_name_const final : public Item { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; + protected: type_conversion_status save_in_field_inner(Field *field, bool no_conversions) override { @@ -3696,6 +3738,8 @@ class Item_ident : public Item { the source base table. */ const char *m_orig_db_name; + + public: /** Names the original table that is the source of the field. If field is from - a non-aliased base table, the same as table_name. @@ -3706,6 +3750,8 @@ class Item_ident : public Item { - a temporary table (in optimization stage), the name of the source base tbl */ const char *m_orig_table_name; + + protected: /** Names the field in the source base table. If field is from - an expression, a NULL pointer. @@ -3762,6 +3808,7 @@ class Item_ident : public Item { cached_table should be replaced by table_ref ASAP. */ TABLE_LIST *cached_table; + uint m_tableno{0}; Query_block *depended_from; Item_ident(Name_resolution_context *context_arg, const char *db_name_arg, @@ -3906,6 +3953,8 @@ class Item_ident : public Item { bool any_privileges); bool is_strong_side_column_not_in_fd(uchar *arg) override; bool is_column_not_in_fd(uchar *arg) override; + + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; }; class Item_ident_for_show final : public Item { @@ -3969,8 +4018,9 @@ class Item_field : public Item_ident { TABLE_LIST *table_ref; /// Source field Field *field; + const char *ref_col_name{nullptr}; + bool ref{false}; - private: /// Result field Field *result_field{nullptr}; @@ -4043,6 +4093,8 @@ class Item_field : public Item_ident { bool itemize(Parse_context *pc, Item **res) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; enum Type type() const override { return FIELD_ITEM; } bool eq(const Item *item, bool binary_cmp) const override; double val_real() override; @@ -4052,6 +4104,7 @@ class Item_field : public Item_ident { longlong val_time_temporal_at_utc() override; longlong val_date_temporal_at_utc() override; my_decimal *val_decimal(my_decimal *) override; + const uchar *val_extra(uint32 *len) override; String *val_str(String *) override; bool val_json(Json_wrapper *result) override; bool send(Protocol *protocol, String *str_arg) override; @@ -4214,6 +4267,11 @@ class Item_field : public Item_ident { bool replace_field_processor(uchar *arg) override; bool strip_db_table_name_processor(uchar *) override; + size_t pq_extra_len(bool) override { + return field->item_sum_ref && need_extra(field->item_sum_ref) + ? sizeof(longlong) : 0; + } + /** Checks if the current object represents an asterisk select list item @@ -4327,6 +4385,7 @@ class Item_null : public Item_basic_constant { Item *safe_charset_converter(THD *thd, const CHARSET_INFO *tocs) override; bool check_partition_func_processor(uchar *) override { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /// Dynamic parameters used as placeholders ('?') inside prepared statements @@ -4704,6 +4763,9 @@ class Item_int : public Item_num { bool no_conversions) override; public: + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; + enum Type type() const override { return INT_ITEM; } Item_result result_type() const override { return INT_RESULT; } longlong val_int() override { @@ -4742,6 +4804,8 @@ class Item_int_0 final : public Item_int { public: Item_int_0() : Item_int(NAME_STRING("0"), 0, 1) {} explicit Item_int_0(const POS &pos) : Item_int(pos, NAME_STRING("0"), 0, 1) {} + + Item *pq_clone(THD *, Query_block *) override { return this; } }; /* @@ -4822,6 +4886,7 @@ class Item_uint : public Item_int { enum_query_type query_type) const override; Item_num *neg() override; uint decimal_precision() const override { return max_length; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /* decimal (fixed point) constant */ @@ -4869,6 +4934,7 @@ class Item_decimal : public Item_num { bool eq(const Item *, bool binary_cmp) const override; void set_decimal_value(const my_decimal *value_par); bool check_partition_func_processor(uchar *) override { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_float : public Item_num { @@ -4952,6 +5018,7 @@ class Item_float : public Item_num { void print(const THD *thd, String *str, enum_query_type query_type) const override; bool eq(const Item *, bool binary_cmp) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_pi : public Item_float { @@ -5074,6 +5141,8 @@ class Item_string : public Item_basic_constant { fixed = true; } + Item *pq_clone(THD *thd, Query_block *select) override; + /* This is used in stored procedures to avoid memory leaks and does a deep copy of its argument. @@ -5168,7 +5237,7 @@ double double_from_string_with_check(const CHARSET_INFO *cs, const char *cptr, const char *end); class Item_static_string_func : public Item_string { - const Name_string func_name; + Name_string func_name; public: Item_static_string_func(const Name_string &name_par, const char *str, @@ -5196,6 +5265,8 @@ class Item_static_string_func : public Item_string { func_arg->banned_function_name = func_name.ptr(); return true; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /* for show tables */ @@ -5300,6 +5371,7 @@ class Item_hex_string : public Item_basic_constant { bool check_partition_func_processor(uchar *) override { return false; } static LEX_CSTRING make_hex_str(const char *str, size_t str_length); uint decimal_precision() const override; + Item *pq_clone(THD *thd, Query_block *select) override; private: void hex_string_init(const char *str, uint str_length); @@ -5318,6 +5390,8 @@ class Item_bin_string final : public Item_hex_string { static LEX_CSTRING make_bin_str(const char *str, size_t str_length); + Item *pq_clone(THD *thd, Query_block *select) override; + private: void bin_string_init(const char *str, size_t str_length); }; @@ -5340,9 +5414,8 @@ class Item_bin_string final : public Item_hex_string { available. */ class Item_result_field : public Item { - protected: - Field *result_field{nullptr}; /* Save result here */ public: + Field *result_field{nullptr}; /* Save result here */ Item_result_field() = default; explicit Item_result_field(const POS &pos) : Item(pos) {} @@ -5433,15 +5506,26 @@ class Item_ref : public Item_ident { public: Item **ref; + enum PQ_copy_type { + WITH_CONTEXT = 0, + WITHOUT_CONTEXT, + WITH_CONTEXT_REF, + WITH_REF_ONLY + }; + + PQ_copy_type copy_type; + public: Item_ref(Name_resolution_context *context_arg, const char *db_name_arg, const char *table_name_arg, const char *field_name_arg) : Item_ident(context_arg, db_name_arg, table_name_arg, field_name_arg), - ref(nullptr) {} + ref(nullptr), + copy_type(WITH_CONTEXT) {} Item_ref(const POS &pos, const char *db_name_arg, const char *table_name_arg, const char *field_name_arg) : Item_ident(pos, db_name_arg, table_name_arg, field_name_arg), - ref(nullptr) {} + ref(nullptr), + copy_type(WITHOUT_CONTEXT) {} /* This constructor is used in two scenarios: @@ -5467,7 +5551,8 @@ class Item_ref : public Item_ident { Item_ref(THD *thd, Item_ref *item) : Item_ident(thd, item), result_field(item->result_field), - ref(item->ref) {} + ref(item->ref), + copy_type(WITH_REF_ONLY) {} enum Type type() const override { return REF_ITEM; } bool eq(const Item *item, bool binary_cmp) const override { const Item *it = const_cast(item)->real_item(); @@ -5617,6 +5702,8 @@ class Item_ref : public Item_ident { return (*ref)->check_column_in_group_by(arg); } bool collect_item_field_or_ref_processor(uchar *arg) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -5658,6 +5745,8 @@ class Item_view_ref final : public Item_ref { bool fix_fields(THD *, Item **) override; + Item *pq_clone(THD *thd, Query_block *select) override; + /** Takes into account whether an Item in a derived table / view is part of an inner table of an outer join. @@ -5866,6 +5955,8 @@ class Item_int_with_ref : public Item_int { } Item *clone_item() const override; Item *real_item() override { return ref; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /* @@ -5915,6 +6006,8 @@ class Item_datetime_with_ref final : public Item_temporal_with_ref { assert(0); return val_int(); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /* @@ -5940,6 +6033,8 @@ class Item_time_with_ref final : public Item_temporal_with_ref { assert(0); return val_int(); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -6125,6 +6220,7 @@ class Item_default_value final : public Item_field { } Item *transform(Item_transformer transformer, uchar *args) override; + Item *pq_clone(THD *thd, Query_block *select) override; private: /// The argument for this function @@ -6320,8 +6416,9 @@ class Item_trigger_field final : public Item_field, }; class Item_cache : public Item_basic_constant { - protected: + public: Item *example{nullptr}; + protected: table_map used_table_map{0}; /** Field that this object will get value from. This is used by @@ -6449,6 +6546,9 @@ class Item_cache : public Item_basic_constant { if (!example) return INT_RESULT; return Field::result_merge_type(example->data_type()); } + + Item *get_example() { return example;} + bool pq_copy_from(THD *thd, Query_block *select, Item* item) override; }; class Item_cache_int final : public Item_cache { @@ -6477,6 +6577,7 @@ class Item_cache_int final : public Item_cache { bool get_time(MYSQL_TIME *ltime) override { return get_time_from_int(ltime); } Item_result result_type() const override { return INT_RESULT; } bool cache_value() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_cache_real final : public Item_cache { @@ -6498,6 +6599,8 @@ class Item_cache_real final : public Item_cache { Item_result result_type() const override { return REAL_RESULT; } bool cache_value() override; void store_value(Item *expr, double value); + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_cache_decimal final : public Item_cache { @@ -6520,6 +6623,8 @@ class Item_cache_decimal final : public Item_cache { Item_result result_type() const override { return DECIMAL_RESULT; } bool cache_value() override; void store_value(Item *expr, my_decimal *d); + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_cache_str final : public Item_cache { @@ -6554,6 +6659,8 @@ class Item_cache_str final : public Item_cache { const CHARSET_INFO *charset() const { return value->charset(); } bool cache_value() override; void store_value(Item *expr, String &s); + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_cache_row final : public Item_cache { @@ -6610,6 +6717,8 @@ class Item_cache_row final : public Item_cache { void bring_value() override; void cleanup() override { Item_cache::cleanup(); } bool cache_value() override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_cache_datetime : public Item_cache { @@ -6649,6 +6758,8 @@ class Item_cache_datetime : public Item_cache { Item_cache::clear(); str_value_cached = false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /// An item cache for values of type JSON. @@ -6706,7 +6817,7 @@ class Item_aggregate_type : public Item { Item_result result_type() const override; bool join_types(THD *, Item *); - Field *make_field_by_type(TABLE *table, bool strict); + Field *make_field_by_type(TABLE *table, bool strict, MEM_ROOT *root = nullptr); static uint32 display_length(Item *item); Field::geometry_type get_geometry_type() const override { return geometry_type; @@ -6852,4 +6963,42 @@ inline Item *GetNthVisibleField(const mem_root_deque &fields, return nullptr; } +/* + need a special class to adjust printing : references to aggregate functions + must not be printed as refs because the aggregate functions that are added to + the front of select list are not printed as well. +*/ +class Item_aggregate_ref : public Item_ref { + public: + Item_aggregate_ref(Name_resolution_context *context_arg, Item **item, + const char *db_name_arg, const char *table_name_arg, const char *field_name_arg, + Query_block *depended_from_arg) + : Item_ref(context_arg, item, db_name_arg, table_name_arg, field_name_arg) { + depended_from = depended_from_arg; + } + + void print(const THD *thd, String *str, + enum_query_type query_type) const override { + if (ref != nullptr && (*ref) != nullptr) { + (*ref)->print(thd, str, query_type); + } else { + Item_ident::print(thd, str, query_type); + } + } + + Ref_Type ref_type() const override { return AGGREGATE_REF; } + + /** + Walker processor used by Query_block::transform_grouped_to_derived to replace + an aggregate's reference to one in the new derived table's (hidden) select + list. + + @param arg An info object of type Item::Aggregate_ref_update + @returns false + */ + bool update_aggr_refs(uchar *arg) override; + + Item *pq_clone(class THD *thd, class Query_block *select) override; +}; + #endif /* ITEM_INCLUDED */ diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 443940f640d0..a37212938a23 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -6884,6 +6885,7 @@ bool Item_equal::fix_fields(THD *thd, Item **) { not_null_tables_cache = used_tables_cache = 0; bool nullable = false; while ((item = li++)) { + if (!item->fixed && item->fix_fields(thd, &item)) return true; used_tables_cache |= item->used_tables(); not_null_tables_cache |= item->not_null_tables(); nullable |= item->is_nullable(); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b77a6570c0f5..4044ce367423 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -2,6 +2,7 @@ #define ITEM_CMPFUNC_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -370,6 +371,7 @@ class Item_func_true : public Item_func_bool_const { str->append("true"); } enum Functype functype() const override { return TRUE_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /// A predicate that is "always false". @@ -384,6 +386,7 @@ class Item_func_false : public Item_func_bool_const { void print(const THD *, String *str, enum_query_type) const override { str->append("false"); } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -448,6 +451,8 @@ class Item_func_truth final : public Item_bool_func { } } + Item *pq_clone(THD *thd, Query_block *select) override; + protected: Bool_test truth_test; ///< The value we're testing for. }; @@ -717,6 +722,8 @@ class Item_func_xor final : public Item_bool_func2 { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_not : public Item_bool_func { @@ -735,6 +742,8 @@ class Item_func_not : public Item_bool_func { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -892,6 +901,7 @@ class Item_func_trig_cond final : public Item_bool_func { plan_idx idx() const { return m_idx; } bool contains_only_equi_join_condition() const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_not_all : public Item_func_not { @@ -1046,6 +1056,8 @@ class Item_func_eq : public Item_func_comparison { /// we save a list of all of the fields that were considered equal. void ensure_multi_equality_fields_are_available(table_map left_side_tables, table_map right_side_tables); + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1078,6 +1090,8 @@ class Item_func_equal final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1098,6 +1112,8 @@ class Item_func_ge final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1118,6 +1134,8 @@ class Item_func_gt final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1138,6 +1156,8 @@ class Item_func_le final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1180,6 +1200,8 @@ class Item_func_lt final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1200,6 +1222,8 @@ class Item_func_ne final : public Item_func_comparison { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /* @@ -1236,6 +1260,7 @@ class Item_func_opt_neg : public Item_int_func { } bool eq(const Item *item, bool binary_cmp) const override; bool subst_argument_checker(uchar **) override { return true; } + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_between final : public Item_func_opt_neg { @@ -1288,6 +1313,8 @@ class Item_func_between final : public Item_func_opt_neg { args[0]->not_null_tables() | (args[1]->not_null_tables() & args[2]->not_null_tables()); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_strcmp final : public Item_bool_func2 { @@ -1308,6 +1335,8 @@ class Item_func_strcmp final : public Item_bool_func2 { fix_char_length(2); // returns "1" or "0" or "-1" return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; struct interval_range { @@ -1332,15 +1361,27 @@ class Item_func_interval final : public Item_int_func { allowed_arg_cols = 0; // Fetch this value from first argument } + Item_func_interval(const POS &pos, Item_row *tmprow) + : super(pos, tmprow), + row(tmprow), + use_decimal_comparison(false), + intervals(0) { + allowed_arg_cols = 0; + } + bool itemize(Parse_context *pc, Item **res) override; longlong val_int() override; bool resolve_type(THD *) override; + enum Functype functype() const override { return INTERVAL_FUNC; } const char *func_name() const override { return "interval"; } uint decimal_precision() const override { return 2; } void print(const THD *thd, String *str, enum_query_type query_type) const override; void update_used_tables() override; + Item* pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; + private: // Runs in CTOR init list, cannot access *this as Item_func_interval static Item_row *alloc_row(const POS &pos, MEM_ROOT *mem_root, Item *expr1, @@ -1387,6 +1428,7 @@ class Item_func_coalesce : public Item_func_numhybrid { enum Item_result result_type() const override { return hybrid_type; } const char *func_name() const override { return "coalesce"; } enum Functype functype() const override { return COALESCE_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_ifnull final : public Item_func_coalesce { @@ -1406,6 +1448,7 @@ class Item_func_ifnull final : public Item_func_coalesce { const char *func_name() const override { return "ifnull"; } Field *tmp_table_field(TABLE *table) override; uint decimal_precision() const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1420,6 +1463,7 @@ class Item_func_any_value final : public Item_func_coalesce { const char *func_name() const override { return "any_value"; } bool aggregate_check_group(uchar *arg) override; bool aggregate_check_distinct(uchar *arg) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_if final : public Item_func { @@ -1462,6 +1506,8 @@ class Item_func_if final : public Item_func { not_null_tables_cache = (args[1]->not_null_tables() & args[2]->not_null_tables()); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_nullif final : public Item_bool_func2 { @@ -1500,6 +1546,8 @@ class Item_func_nullif final : public Item_bool_func2 { inherit from Item_func instead of Item_bool_func2 */ bool is_bool_func() const override { return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /* Functions to handle the optimized IN */ @@ -1554,6 +1602,8 @@ class in_vector { virtual bool is_row_result() const { return false; } + virtual in_vector* pq_clone(THD *thd MY_ATTRIBUTE((unused))) { return nullptr; } + /** Fill the vector by evaluating the items passed as arguments. Note that null values are skipped so the vector may end up containing @@ -1627,6 +1677,7 @@ class in_longlong : public in_vector { } bool find_item(Item *item) override; bool compare_elems(uint pos1, uint pos2) const override; + void resize_and_sort_ll() {resize_and_sort();} private: void set(uint pos, Item *item) override { val_item(item, &base[pos]); } @@ -1971,6 +2022,8 @@ class Item_func_case final : public Item_func { return cmp_collation.collation; } enum Functype functype() const override { return CASE_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /** @@ -2068,6 +2121,8 @@ class Item_func_in final : public Item_func_opt_neg { not_null_tables_cache |= args[0]->not_null_tables(); } + Item *pq_clone(THD *thd, Query_block *select) override; + private: /** Usable if @ is made only of constants. Returns true if one @@ -2192,6 +2247,8 @@ class Item_func_isnull : public Item_bool_func { return args[0]->collation.collation; } bool fix_fields(THD *thd, Item **ref) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /* Functions used by HAVING for rewriting IN subquery */ @@ -2254,6 +2311,7 @@ class Item_func_isnotnull final : public Item_bool_func { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_like final : public Item_bool_func2 { @@ -2315,6 +2373,7 @@ class Item_func_like final : public Item_bool_func2 { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + Item *pq_clone(THD *thd, Query_block *select) override; private: /** @@ -2393,6 +2452,7 @@ class Item_cond : public Item_bool_func { /// Treat UNKNOWN result like FALSE because callers see no difference bool ignore_unknown() const { return abort_on_null; } bool equality_substitution_analyzer(uchar **) override { return true; } + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /* @@ -2487,6 +2547,7 @@ class Item_equal final : public Item_bool_func { Item_equal(Item *c, Item_field *f); Item_equal(Item_equal *item_equal); + inline List get_fields() {return fields;} inline Item *get_const() { return const_item; } void set_const(Item *c) { const_item = c; } bool compare_const(THD *thd, Item *c); @@ -2555,6 +2616,8 @@ class Item_equal final : public Item_bool_func { const MY_BITMAP *fields_to_ignore, double rows_in_table) override; Item *m_const_folding[2]; ///< temporary area used for constant folding + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; private: void check_covering_prefix_keys(); @@ -2609,6 +2672,8 @@ class Item_cond_and final : public Item_cond { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; bool contains_only_equi_join_condition() const override; }; @@ -2638,6 +2703,7 @@ class Item_cond_or final : public Item_cond { table_map read_tables, const MY_BITMAP *fields_to_ignore, double rows_in_table) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /// Builds condition: (a AND b) IS TRUE diff --git a/sql/item_func.cc b/sql/item_func.cc index 77e847f66a2c..04215acfad21 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -6555,10 +6556,13 @@ static int get_var_with_binlog(THD *thd, enum_sql_command sql_command, Binlog_user_var_event *user_var_event; user_var_entry *var_entry; + /* obtain user variables from leader thread */ + THD *entry_thd = thd->is_worker() ? thd->pq_leader : thd; + /* Protects thd->user_vars. */ - mysql_mutex_lock(&thd->LOCK_thd_data); - var_entry = get_variable(thd, name, nullptr); - mysql_mutex_unlock(&thd->LOCK_thd_data); + mysql_mutex_lock(&entry_thd->LOCK_thd_data); + var_entry = get_variable(entry_thd, name, nullptr); + mysql_mutex_unlock(&entry_thd->LOCK_thd_data); *out_entry = var_entry; @@ -6845,6 +6849,30 @@ bool Item_func_get_user_var::set_value(THD *thd, sp_rcontext * /*ctx*/, suv->update()); } +bool Item_func_get_user_var::pq_copy_from(THD *thd, Query_block *select, + Item *item) { + if (Item_var_func::pq_copy_from(thd, select, this)) { + return true; + } + Item_func_get_user_var *orig_item = + dynamic_cast(item); + assert(orig_item); + + // obtain var_entry from leader +#ifndef NDEBUG + THD *entry_thd = thd->pq_leader; + assert(entry_thd); + mysql_mutex_lock(&entry_thd->LOCK_thd_data); + var_entry = get_variable(entry_thd, name, NULL); + mysql_mutex_unlock(&entry_thd->LOCK_thd_data); + assert(var_entry && orig_item->var_entry); +#endif + if (orig_item != nullptr) { + m_cached_result_type = orig_item->m_cached_result_type; + } + return false; +} + bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref) { assert(fixed == 0); diff --git a/sql/item_func.h b/sql/item_func.h index 3dbb10a8f4be..ed3296059ae9 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -2,6 +2,7 @@ #define ITEM_FUNC_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -285,7 +286,9 @@ class Item_func : public Item_result_field { JSON_UNQUOTE_FUNC, MEMBER_OF_FUNC, STRCMP_FUNC, - TRUE_FUNC + TRUE_FUNC, + JSON_FUNC, + XML_FUNC }; enum optimize_type { OPTIMIZE_NONE, @@ -698,6 +701,7 @@ class Item_func : public Item_result_field { bool check_column_in_group_by(uchar *arg) override; longlong val_int_from_real(); + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_real_func : public Item_func { @@ -972,6 +976,9 @@ class Item_func_connection_id final : public Item_int_func { return ((func_arg->source == VGS_GENERATED_COLUMN) || (func_arg->source == VGS_CHECK_CONSTRAINT)); } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_typecast_signed final : public Item_int_func { @@ -985,6 +992,7 @@ class Item_typecast_signed final : public Item_int_func { void print(const THD *thd, String *str, enum_query_type query_type) const override; enum Functype functype() const override { return TYPECAST_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_typecast_unsigned final : public Item_int_func { @@ -998,14 +1006,16 @@ class Item_typecast_unsigned final : public Item_int_func { void print(const THD *thd, String *str, enum_query_type query_type) const override; enum Functype functype() const override { return TYPECAST_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_typecast_decimal final : public Item_func { public: Item_typecast_decimal(const POS &pos, Item *a, int len, int dec) - : Item_func(pos, a) { + : Item_func(pos, a), pq_precision(len) { set_data_type_decimal(len, dec); } + int pq_precision; String *val_str(String *str) override; double val_real() override; longlong val_int() override; @@ -1026,6 +1036,7 @@ class Item_typecast_decimal final : public Item_func { enum Functype functype() const override { return TYPECAST_FUNC; } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1055,6 +1066,7 @@ class Item_typecast_real final : public Item_func { enum Functype functype() const override { return TYPECAST_FUNC; } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_additive_op : public Item_num_op { @@ -1082,6 +1094,7 @@ class Item_func_plus final : public Item_func_additive_op { double real_op() override; my_decimal *decimal_op(my_decimal *) override; enum Functype functype() const override { return PLUS_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_minus final : public Item_func_additive_op { @@ -1099,6 +1112,7 @@ class Item_func_minus final : public Item_func_additive_op { my_decimal *decimal_op(my_decimal *) override; bool resolve_type(THD *thd) override; enum Functype functype() const override { return MINUS_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mul final : public Item_num_op { @@ -1114,6 +1128,7 @@ class Item_func_mul final : public Item_num_op { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } enum Functype functype() const override { return MUL_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_div final : public Item_num_op { @@ -1130,6 +1145,7 @@ class Item_func_div final : public Item_num_op { bool resolve_type(THD *thd) override; void result_precision() override; enum Functype functype() const override { return DIV_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_int_div final : public Item_int_func { @@ -1148,6 +1164,7 @@ class Item_func_int_div final : public Item_int_func { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mod final : public Item_num_op { @@ -1164,6 +1181,7 @@ class Item_func_mod final : public Item_num_op { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } enum Functype functype() const override { return MOD_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_neg final : public Item_func_num1 { @@ -1183,6 +1201,7 @@ class Item_func_neg final : public Item_func_num1 { } bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_abs final : public Item_func_num1 { @@ -1196,6 +1215,7 @@ class Item_func_abs final : public Item_func_num1 { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } enum Functype functype() const override { return ABS_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; // A class to handle logarithmic and trigonometric functions @@ -1215,6 +1235,7 @@ class Item_func_exp final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "exp"; } enum Functype functype() const override { return EXP_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_ln final : public Item_dec_func { @@ -1223,6 +1244,7 @@ class Item_func_ln final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "ln"; } enum Functype functype() const override { return LN_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_log final : public Item_dec_func { @@ -1232,6 +1254,7 @@ class Item_func_log final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "log"; } enum Functype functype() const override { return LOG_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_log2 final : public Item_dec_func { @@ -1239,6 +1262,7 @@ class Item_func_log2 final : public Item_dec_func { Item_func_log2(const POS &pos, Item *a) : Item_dec_func(pos, a) {} double val_real() override; const char *func_name() const override { return "log2"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_log10 final : public Item_dec_func { @@ -1247,6 +1271,7 @@ class Item_func_log10 final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "log10"; } enum Functype functype() const override { return LOG10_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sqrt final : public Item_dec_func { @@ -1255,6 +1280,7 @@ class Item_func_sqrt final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "sqrt"; } enum Functype functype() const override { return SQRT_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_pow final : public Item_dec_func { @@ -1262,6 +1288,7 @@ class Item_func_pow final : public Item_dec_func { Item_func_pow(const POS &pos, Item *a, Item *b) : Item_dec_func(pos, a, b) {} double val_real() override; const char *func_name() const override { return "pow"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_acos final : public Item_dec_func { @@ -1270,6 +1297,7 @@ class Item_func_acos final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "acos"; } enum Functype functype() const override { return ACOS_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_asin final : public Item_dec_func { @@ -1278,6 +1306,7 @@ class Item_func_asin final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "asin"; } enum Functype functype() const override { return ASIN_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_atan final : public Item_dec_func { @@ -1287,6 +1316,7 @@ class Item_func_atan final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "atan"; } enum Functype functype() const override { return ATAN_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_cos final : public Item_dec_func { @@ -1295,6 +1325,7 @@ class Item_func_cos final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "cos"; } enum Functype functype() const override { return COS_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sin final : public Item_dec_func { @@ -1303,6 +1334,7 @@ class Item_func_sin final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "sin"; } enum Functype functype() const override { return SIN_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_tan final : public Item_dec_func { @@ -1311,6 +1343,7 @@ class Item_func_tan final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "tan"; } enum Functype functype() const override { return TAN_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_cot final : public Item_dec_func { @@ -1319,6 +1352,7 @@ class Item_func_cot final : public Item_dec_func { double val_real() override; const char *func_name() const override { return "cot"; } enum Functype functype() const override { return COT_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_int_val : public Item_func_num1 { @@ -1339,6 +1373,7 @@ class Item_func_ceiling final : public Item_func_int_val { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } enum Functype functype() const override { return CEILING_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_floor final : public Item_func_int_val { @@ -1352,6 +1387,7 @@ class Item_func_floor final : public Item_func_int_val { bool check_partition_func_processor(uchar *) override { return false; } bool check_function_as_value_generator(uchar *) override { return false; } enum Functype functype() const override { return FLOOR_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /* This handles round and truncate */ @@ -1375,6 +1411,7 @@ class Item_func_round final : public Item_func_num1 { enum Functype functype() const override { return truncate ? TRUNCATE_FUNC : ROUND_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_rand final : public Item_real_func { @@ -1413,6 +1450,8 @@ class Item_func_rand final : public Item_real_func { (func_arg->source == VGS_CHECK_CONSTRAINT)); } + Item *pq_clone(THD *thd, Query_block *select) override; + private: void seed_random(Item *val); }; @@ -1533,6 +1572,7 @@ class Item_func_min final : public Item_func_min_max { : Item_func_min_max(pos, opt_list, true) {} const char *func_name() const override { return "least"; } enum Functype functype() const override { return LEAST_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_max final : public Item_func_min_max { @@ -1541,6 +1581,7 @@ class Item_func_max final : public Item_func_min_max { : Item_func_min_max(pos, opt_list, false) {} const char *func_name() const override { return "greatest"; } enum Functype functype() const override { return GREATEST_FUNC; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1639,6 +1680,7 @@ class Item_func_length : public Item_int_func { max_length = 10; return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_bit_length final : public Item_func_length { @@ -1649,6 +1691,7 @@ class Item_func_bit_length final : public Item_func_length { return Item_func_length::val_int() * 8; } const char *func_name() const override { return "bit_length"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_char_length final : public Item_int_func { @@ -1663,6 +1706,9 @@ class Item_func_char_length final : public Item_int_func { max_length = 10; return Item_int_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_coercibility final : public Item_int_func { @@ -1677,6 +1723,8 @@ class Item_func_coercibility final : public Item_int_func { set_nullable(false); return Item_int_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_locate : public Item_int_func { @@ -1695,6 +1743,8 @@ class Item_func_locate : public Item_int_func { bool resolve_type(THD *thd) override; void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_instr final : public Item_func_locate { @@ -1703,6 +1753,7 @@ class Item_func_instr final : public Item_func_locate { : Item_func_locate(pos, a, b) {} const char *func_name() const override { return "instr"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_validate_password_strength final : public Item_int_func { @@ -1731,6 +1782,7 @@ class Item_func_field final : public Item_int_func { longlong val_int() override; const char *func_name() const override { return "field"; } bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_ascii final : public Item_int_func { @@ -1744,6 +1796,7 @@ class Item_func_ascii final : public Item_int_func { max_length = 3; return Item_int_func::resolve_type(thd); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_ord final : public Item_int_func { @@ -1753,6 +1806,7 @@ class Item_func_ord final : public Item_int_func { Item_func_ord(const POS &pos, Item *a) : Item_int_func(pos, a) {} longlong val_int() override; const char *func_name() const override { return "ord"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_find_in_set final : public Item_int_func { @@ -1770,6 +1824,7 @@ class Item_func_find_in_set final : public Item_int_func { const CHARSET_INFO *compare_collation() const override { return cmp_collation.collation; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /* Base class for all bit functions: '~', '|', '^', '&', '>>', '<<' */ @@ -1815,6 +1870,8 @@ class Item_func_bit : public Item_func { return get_time_from_string(ltime); } + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; + private: /** @brief Performs the operation on integers to produce a result of type @@ -1856,6 +1913,7 @@ class Item_func_bit_or final : public Item_func_bit_two_param { Item_func_bit_or(const POS &pos, Item *a, Item *b) : Item_func_bit_two_param(pos, a, b) {} const char *func_name() const override { return "|"; } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override { return eval_int_op(std::bit_or()); } @@ -1869,6 +1927,7 @@ class Item_func_bit_and final : public Item_func_bit_two_param { Item_func_bit_and(const POS &pos, Item *a, Item *b) : Item_func_bit_two_param(pos, a, b) {} const char *func_name() const override { return "&"; } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override { return eval_int_op(std::bit_and()); } @@ -1882,6 +1941,7 @@ class Item_func_bit_xor final : public Item_func_bit_two_param { Item_func_bit_xor(const POS &pos, Item *a, Item *b) : Item_func_bit_two_param(pos, a, b) {} const char *func_name() const override { return "^"; } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override { return eval_int_op(std::bit_xor()); } @@ -1904,6 +1964,7 @@ class Item_func_bit_count final : public Item_int_func { max_length = MAX_BIGINT_WIDTH + 1; return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_shift : public Item_func_bit { @@ -1926,6 +1987,7 @@ class Item_func_shift_left final : public Item_func_shift { Item_func_shift_left(const POS &pos, Item *a, Item *b) : Item_func_shift(pos, a, b) {} const char *func_name() const override { return "<<"; } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override { return eval_int_op(); } @@ -1937,6 +1999,7 @@ class Item_func_shift_right final : public Item_func_shift { Item_func_shift_right(const POS &pos, Item *a, Item *b) : Item_func_shift(pos, a, b) {} const char *func_name() const override { return ">>"; } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override { return eval_int_op(); } @@ -1956,6 +2019,7 @@ class Item_func_bit_neg final : public Item_func_bit { enum_query_type query_type) const override { Item_func::print(thd, str, query_type); } + Item *pq_clone(THD *thd, Query_block *select) override; private: longlong int_op() override; @@ -1986,6 +2050,8 @@ class Item_func_last_insert_id final : public Item_int_func { func_arg->banned_function_name = func_name(); return true; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_benchmark final : public Item_int_func { @@ -2019,6 +2085,8 @@ class Item_func_benchmark final : public Item_int_func { func_arg->banned_function_name = func_name(); return true; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; void item_func_sleep_init(); @@ -2053,6 +2121,7 @@ class Item_func_sleep final : public Item_int_func { return Item_int_func::resolve_type(thd); } longlong val_int() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_udf_func : public Item_func { @@ -2277,6 +2346,7 @@ class Item_func_get_lock final : public Item_int_func { return true; } uint decimal_precision() const override { return max_length; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_release_lock final : public Item_int_func { @@ -2461,6 +2531,7 @@ class Item_func_can_access_table : public Item_int_func { set_nullable(true); return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_can_access_user : public Item_int_func { @@ -2562,6 +2633,8 @@ class Item_func_is_visible_dd_object : public Item_int_func { set_nullable(true); return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_table_rows : public Item_int_func { @@ -2577,6 +2650,8 @@ class Item_func_internal_table_rows : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_avg_row_length : public Item_int_func { @@ -2592,6 +2667,8 @@ class Item_func_internal_avg_row_length : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_data_length : public Item_int_func { @@ -2607,6 +2684,8 @@ class Item_func_internal_data_length : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_max_data_length : public Item_int_func { @@ -2622,6 +2701,8 @@ class Item_func_internal_max_data_length : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_index_length : public Item_int_func { @@ -2637,6 +2718,8 @@ class Item_func_internal_index_length : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_data_free : public Item_int_func { @@ -2652,6 +2735,8 @@ class Item_func_internal_data_free : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_auto_increment : public Item_int_func { @@ -2667,6 +2752,8 @@ class Item_func_internal_auto_increment : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_checksum : public Item_int_func { @@ -2681,6 +2768,8 @@ class Item_func_internal_checksum : public Item_int_func { null_on_null = false; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_keys_disabled : public Item_int_func { @@ -3301,6 +3390,9 @@ class Item_func_get_user_var : public Item_var_func, Settable_routine_parameter *get_settable_routine_parameter() override { return this; } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /* @@ -3425,6 +3517,9 @@ class Item_func_get_system_var final : public Item_var_func { void cleanup() override; bool bind(THD *thd); + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class JOIN; @@ -3914,6 +4009,8 @@ class Item_func_found_rows final : public Item_int_func { func_arg->banned_function_name = func_name(); return true; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; void uuid_short_init(); @@ -3949,6 +4046,8 @@ class Item_func_version final : public Item_static_string_func { explicit Item_func_version(const POS &pos); bool itemize(Parse_context *pc, Item **res) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 84267e177b5e..178240eca9a6 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -2,6 +2,7 @@ #define ITEM_GEOFUNC_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -690,6 +691,8 @@ class Item_func_latfromgeohash : public Item_func_latlongfromgeohash { false) {} const char *func_name() const override { return "ST_LATFROMGEOHASH"; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -703,6 +706,8 @@ class Item_func_longfromgeohash : public Item_func_latlongfromgeohash { } const char *func_name() const override { return "ST_LONGFROMGEOHASH"; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_centroid : public Item_geometry_func { @@ -1085,6 +1090,7 @@ class Item_func_st_contains final : public Item_func_spatial_relation { const char *func_name() const override { return "st_contains"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_crosses final : public Item_func_spatial_relation { @@ -1096,6 +1102,7 @@ class Item_func_st_crosses final : public Item_func_spatial_relation { const char *func_name() const override { return "st_crosses"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_disjoint final : public Item_func_spatial_relation { @@ -1107,6 +1114,7 @@ class Item_func_st_disjoint final : public Item_func_spatial_relation { const char *func_name() const override { return "st_disjoint"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_equals final : public Item_func_spatial_relation { @@ -1118,6 +1126,7 @@ class Item_func_st_equals final : public Item_func_spatial_relation { const char *func_name() const override { return "st_equals"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_intersects final : public Item_func_spatial_relation { @@ -1129,6 +1138,7 @@ class Item_func_st_intersects final : public Item_func_spatial_relation { const char *func_name() const override { return "st_intersects"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrcontains final : public Item_func_spatial_relation { @@ -1140,6 +1150,7 @@ class Item_func_mbrcontains final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrcontains"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrcoveredby final : public Item_func_spatial_relation { @@ -1151,6 +1162,7 @@ class Item_func_mbrcoveredby final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrcoveredby"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrcovers final : public Item_func_spatial_relation { @@ -1162,6 +1174,7 @@ class Item_func_mbrcovers final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrcovers"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrdisjoint final : public Item_func_spatial_relation { @@ -1173,6 +1186,7 @@ class Item_func_mbrdisjoint final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrdisjoint"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrequals final : public Item_func_spatial_relation { @@ -1184,6 +1198,7 @@ class Item_func_mbrequals final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrequals"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrintersects final : public Item_func_spatial_relation { @@ -1195,6 +1210,7 @@ class Item_func_mbrintersects final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrintersects"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbroverlaps final : public Item_func_spatial_relation { @@ -1206,6 +1222,7 @@ class Item_func_mbroverlaps final : public Item_func_spatial_relation { const char *func_name() const override { return "mbroverlaps"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrtouches final : public Item_func_spatial_relation { @@ -1217,6 +1234,7 @@ class Item_func_mbrtouches final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrtouches"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_mbrwithin final : public Item_func_spatial_relation { @@ -1228,6 +1246,7 @@ class Item_func_mbrwithin final : public Item_func_spatial_relation { const char *func_name() const override { return "mbrwithin"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_overlaps final : public Item_func_spatial_relation { @@ -1239,6 +1258,7 @@ class Item_func_st_overlaps final : public Item_func_spatial_relation { const char *func_name() const override { return "st_overlaps"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_touches final : public Item_func_spatial_relation { @@ -1250,6 +1270,7 @@ class Item_func_st_touches final : public Item_func_spatial_relation { const char *func_name() const override { return "st_touches"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_st_within final : public Item_func_spatial_relation { @@ -1261,6 +1282,7 @@ class Item_func_st_within final : public Item_func_spatial_relation { const char *func_name() const override { return "st_within"; } bool eval(const dd::Spatial_reference_system *srs, const gis::Geometry *g1, const gis::Geometry *g2, bool *result, bool *null) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1787,6 +1809,8 @@ class Item_func_st_srid_mutator : public Item_geometry_func { if (param_type_is_default(thd, 1, 2, MYSQL_TYPE_LONGLONG)) return true; return Item_geometry_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /// This class implements the one-parameter ST_SRID function which diff --git a/sql/item_inetfunc.h b/sql/item_inetfunc.h index bc559061f67d..5caad1d69012 100644 --- a/sql/item_inetfunc.h +++ b/sql/item_inetfunc.h @@ -2,6 +2,7 @@ #define ITEM_INETFUNC_INCLUDED /* Copyright (c) 2011, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -54,6 +55,8 @@ class Item_func_inet_aton : public Item_int_func { unsigned_flag = true; return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /************************************************************************* @@ -76,6 +79,8 @@ class Item_func_inet_ntoa : public Item_str_func { set_nullable(true); return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /************************************************************************* @@ -133,6 +138,8 @@ class Item_func_inet6_aton : public Item_func_inet_str_base { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; + protected: bool calc_value(String *arg, String *buffer) override; }; @@ -160,6 +167,8 @@ class Item_func_inet6_ntoa : public Item_func_inet_str_base { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; + protected: bool calc_value(String *arg, String *buffer) override; }; diff --git a/sql/item_json_func.h b/sql/item_json_func.h index 3701eb4f7ca7..dd772b643c7e 100644 --- a/sql/item_json_func.h +++ b/sql/item_json_func.h @@ -2,6 +2,7 @@ #define ITEM_JSON_FUNC_INCLUDED /* Copyright (c) 2015, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -192,6 +193,7 @@ class Item_json_func : public Item_func { double val_real() override; my_decimal *val_decimal(my_decimal *decimal_value) override; + enum Functype functype() const override { return JSON_FUNC; } void cleanup() override; Item_result cast_to_int_type() const override { return INT_RESULT; } @@ -343,6 +345,8 @@ class Item_func_json_schema_valid final : public Item_bool_func { void cleanup() override; + Item *pq_clone(THD *thd, Query_block *select) override; + private: // Wrap the object in a unique_ptr so that the relevant rapidjson destructors // are called. @@ -416,6 +420,8 @@ class Item_func_json_contains final : public Item_int_func { enum_const_item_cache can_cache_json_arg(Item *arg) override { return (arg == args[0] || arg == args[1]) ? CACHE_JSON_VALUE : CACHE_NONE; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -541,6 +547,7 @@ class Item_func_json_depth final : public Item_int_func { } longlong val_int() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -894,6 +901,7 @@ class Item_func_json_quote : public Item_str_func { } String *val_str(String *tmpspace) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** diff --git a/sql/item_pfs_func.h b/sql/item_pfs_func.h index 42b7734f8630..af701cba34c0 100644 --- a/sql/item_pfs_func.h +++ b/sql/item_pfs_func.h @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -78,6 +79,8 @@ class Item_func_pfs_format_bytes final : public Item_str_func { const char *func_name() const override { return "format_bytes"; } bool resolve_type(THD *) override; String *val_str(String *str) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /** format_pico_time() */ @@ -93,6 +96,7 @@ class Item_func_pfs_format_pico_time final : public Item_str_func { const char *func_name() const override { return "format_pico_time"; } bool resolve_type(THD *) override; String *val_str(String *str) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; #endif /* ITEM_PFS_FUNC_INCLUDED */ diff --git a/sql/item_regexp_func.h b/sql/item_regexp_func.h index 4c84589cf4f8..06e69af61d70 100644 --- a/sql/item_regexp_func.h +++ b/sql/item_regexp_func.h @@ -2,6 +2,7 @@ #define SQL_ITEM_REGEXP_FUNC_H_ /* Copyright (c) 2017, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -263,6 +264,8 @@ class Item_func_regexp_instr : public Item_func_regexp { bool get_time(MYSQL_TIME *t) override { return get_time_from_int(t); } /// @} + Item *pq_clone(THD *thd, Query_block *select) override; + protected: int pos_arg_pos() const override { return 2; } int occ_arg_pos() const override { return 3; } @@ -307,6 +310,8 @@ class Item_func_regexp_like : public Item_func_regexp { bool get_time(MYSQL_TIME *t) override { return get_time_from_int(t); } /// @} + Item *pq_clone(THD *thd, Query_block *select) override; + protected: int pos_arg_pos() const override { return -1; } int occ_arg_pos() const override { return -1; } diff --git a/sql/item_row.h b/sql/item_row.h index 6cdeed0b2d56..59231ebd5e46 100644 --- a/sql/item_row.h +++ b/sql/item_row.h @@ -2,6 +2,7 @@ #define ITEM_ROW_INCLUDED /* Copyright (c) 2002, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -152,6 +153,8 @@ class Item_row : public Item { bool null_inside() override { return with_null; } void bring_value() override; bool check_function_as_value_generator(uchar *) override { return false; } + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; #endif /* ITEM_ROW_INCLUDED */ diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index c1a0b07fdfaf..f2f9a03ca3f0 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -185,6 +186,7 @@ class Item_func_md5 final : public Item_str_ascii_func { String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "md5"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sha : public Item_str_ascii_func { @@ -193,6 +195,7 @@ class Item_func_sha : public Item_str_ascii_func { String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "sha"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sha2 : public Item_str_ascii_func { @@ -202,6 +205,7 @@ class Item_func_sha2 : public Item_str_ascii_func { String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "sha2"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_to_base64 final : public Item_str_ascii_func { @@ -212,6 +216,7 @@ class Item_func_to_base64 final : public Item_str_ascii_func { String *val_str_ascii(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "to_base64"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_statement_digest final : public Item_str_ascii_func { @@ -270,6 +275,7 @@ class Item_func_from_base64 final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "from_base64"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_aes_encrypt final : public Item_str_func { @@ -286,6 +292,7 @@ class Item_func_aes_encrypt final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "aes_encrypt"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_aes_decrypt : public Item_str_func { @@ -301,6 +308,7 @@ class Item_func_aes_decrypt : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "aes_decrypt"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_random_bytes : public Item_str_func { @@ -317,6 +325,7 @@ class Item_func_random_bytes : public Item_str_func { String *val_str(String *a) override; const char *func_name() const override { return "random_bytes"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_concat : public Item_str_func { @@ -331,6 +340,7 @@ class Item_func_concat : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "concat"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_concat_ws : public Item_str_func { @@ -347,6 +357,7 @@ class Item_func_concat_ws : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "concat_ws"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_reverse : public Item_str_func { @@ -359,6 +370,7 @@ class Item_func_reverse : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "reverse"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_replace : public Item_str_func { @@ -372,6 +384,7 @@ class Item_func_replace : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "replace"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_insert : public Item_str_func { @@ -386,6 +399,7 @@ class Item_func_insert : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "insert"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_str_conv : public Item_str_func { @@ -397,6 +411,7 @@ class Item_str_conv : public Item_str_func { public: Item_str_conv(const POS &pos, Item *item) : Item_str_func(pos, item) {} String *val_str(String *) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_lower : public Item_str_conv { @@ -404,6 +419,7 @@ class Item_func_lower : public Item_str_conv { Item_func_lower(const POS &pos, Item *item) : Item_str_conv(pos, item) {} const char *func_name() const override { return "lower"; } bool resolve_type(THD *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_upper : public Item_str_conv { @@ -411,6 +427,7 @@ class Item_func_upper : public Item_str_conv { Item_func_upper(const POS &pos, Item *item) : Item_str_conv(pos, item) {} const char *func_name() const override { return "upper"; } bool resolve_type(THD *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_left : public Item_str_func { @@ -421,6 +438,7 @@ class Item_func_left : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "left"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_right : public Item_str_func { @@ -432,6 +450,7 @@ class Item_func_right : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "right"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_substr : public Item_str_func { @@ -450,6 +469,7 @@ class Item_func_substr : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "substr"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_substr_index final : public Item_str_func { @@ -461,6 +481,7 @@ class Item_func_substr_index final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "substring_index"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_trim : public Item_str_func { @@ -542,18 +563,23 @@ class Item_func_trim : public Item_str_func { } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_ltrim final : public Item_func_trim { public: Item_func_ltrim(const POS &pos, Item *a) : Item_func_trim(pos, a, TRIM_LTRIM) {} + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_rtrim final : public Item_func_trim { public: Item_func_rtrim(const POS &pos, Item *a) : Item_func_trim(pos, a, TRIM_RTRIM) {} + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sysconst : public Item_str_func { @@ -602,6 +628,8 @@ class Item_func_database : public Item_func_sysconst { const Name_string fully_qualified_func_name() const override { return NAME_STRING("database()"); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_user : public Item_func_sysconst { @@ -649,6 +677,7 @@ class Item_func_user : public Item_func_sysconst { } String *val_str(String *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_current_user : public Item_func_user { @@ -669,6 +698,7 @@ class Item_func_current_user : public Item_func_user { } String *val_str(String *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_soundex : public Item_str_func { @@ -680,6 +710,7 @@ class Item_func_soundex : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "soundex"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_elt final : public Item_str_func { @@ -691,15 +722,16 @@ class Item_func_elt final : public Item_str_func { String *val_str(String *str) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "elt"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_make_set final : public Item_str_func { typedef Item_str_func super; + public: Item *item; String tmp_str; - public: Item_func_make_set(const POS &pos, Item *a, PT_item_list *opt_list) : Item_str_func(pos, opt_list), item(a) {} @@ -730,6 +762,8 @@ class Item_func_make_set final : public Item_str_func { Item *transform(Item_transformer transformer, uchar *arg) override; void print(const THD *thd, String *str, enum_query_type query_type) const override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_format final : public Item_str_ascii_func { @@ -748,6 +782,8 @@ class Item_func_format final : public Item_str_ascii_func { const char *func_name() const override { return "format"; } void print(const THD *thd, String *str, enum_query_type query_type) const override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_char final : public Item_str_func { @@ -767,6 +803,7 @@ class Item_func_char final : public Item_str_func { return false; } const char *func_name() const override { return "char"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_repeat final : public Item_str_func { @@ -778,6 +815,7 @@ class Item_func_repeat final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "repeat"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_space final : public Item_str_func { @@ -786,6 +824,7 @@ class Item_func_space final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "space"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_rpad final : public Item_str_func { @@ -797,6 +836,8 @@ class Item_func_rpad final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "rpad"; } + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_lpad final : public Item_str_func { @@ -808,6 +849,8 @@ class Item_func_lpad final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "lpad"; } + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_uuid_to_bin final : public Item_str_func { @@ -822,6 +865,7 @@ class Item_func_uuid_to_bin final : public Item_str_func { String *val_str(String *) override; bool resolve_type(THD *) override; const char *func_name() const override { return "uuid_to_bin"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_bin_to_uuid final : public Item_str_ascii_func { @@ -836,6 +880,7 @@ class Item_func_bin_to_uuid final : public Item_str_ascii_func { String *val_str_ascii(String *) override; bool resolve_type(THD *thd) override; const char *func_name() const override { return "bin_to_uuid"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_is_uuid final : public Item_bool_func { @@ -861,6 +906,7 @@ class Item_func_conv final : public Item_str_func { const char *func_name() const override { return "conv"; } String *val_str(String *) override; bool resolve_type(THD *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_hex : public Item_str_ascii_func { @@ -875,6 +921,7 @@ class Item_func_hex : public Item_str_ascii_func { set_data_type_string(args[0]->max_length * 2U, default_charset()); return false; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_unhex final : public Item_str_func { @@ -888,6 +935,7 @@ class Item_func_unhex final : public Item_str_func { const char *func_name() const override { return "unhex"; } String *val_str(String *) override; bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; #ifndef NDEBUG @@ -945,6 +993,7 @@ class Item_typecast_char final : public Item_str_func { bool resolve_type(THD *) override; void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_load_file final : public Item_str_func { @@ -989,6 +1038,7 @@ class Item_func_export_set final : public Item_str_func { String *val_str(String *str) override; bool resolve_type(THD *) override; const char *func_name() const override { return "export_set"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_quote : public Item_str_func { @@ -999,6 +1049,7 @@ class Item_func_quote : public Item_str_func { const char *func_name() const override { return "quote"; } String *val_str(String *) override; bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_conv_charset final : public Item_str_func { @@ -1050,6 +1101,7 @@ class Item_func_conv_charset final : public Item_str_func { const char *func_name() const override { return "convert"; } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_set_collation final : public Item_str_func { @@ -1074,6 +1126,9 @@ class Item_func_set_collation final : public Item_str_func { /* this function is transparent for view updating */ return args[0]->field_for_view_update(); } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_charset final : public Item_str_func { @@ -1088,6 +1143,8 @@ class Item_func_charset final : public Item_str_func { set_nullable(false); return Item_str_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_collation : public Item_str_func { @@ -1103,6 +1160,8 @@ class Item_func_collation : public Item_str_func { set_nullable(false); return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_weight_string final : public Item_str_func { @@ -1134,6 +1193,7 @@ class Item_func_weight_string final : public Item_str_func { bool resolve_type(THD *) override; void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_crc32 final : public Item_int_func { @@ -1150,6 +1210,7 @@ class Item_func_crc32 final : public Item_int_func { return false; } longlong val_int() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_uncompressed_length final : public Item_int_func { @@ -1165,6 +1226,7 @@ class Item_func_uncompressed_length final : public Item_int_func { return false; } longlong val_int() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_compress final : public Item_str_func { @@ -1179,6 +1241,7 @@ class Item_func_compress final : public Item_str_func { } const char *func_name() const override { return "compress"; } String *val_str(String *str) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_uncompress final : public Item_str_func { @@ -1194,6 +1257,7 @@ class Item_func_uncompress final : public Item_str_func { } const char *func_name() const override { return "uncompress"; } String *val_str(String *str) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_uuid final : public Item_str_func { @@ -1218,6 +1282,8 @@ class Item_func_uuid final : public Item_str_func { return ((func_arg->source == VGS_GENERATED_COLUMN) || (func_arg->source == VGS_CHECK_CONSTRAINT)); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_gtid_subtract final : public Item_str_ascii_func { @@ -1342,6 +1408,8 @@ class Item_func_get_dd_create_options final : public Item_str_func { const char *func_name() const override { return "get_dd_create_options"; } String *val_str(String *) override; + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_get_dd_schema_options final : public Item_str_func { @@ -1389,6 +1457,7 @@ class Item_func_internal_get_comment_or_error final : public Item_str_func { } String *val_str(String *) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_get_dd_tablespace_private_data final : public Item_str_func { diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f3d5d862e671..0d965d964288 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2002, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -3453,7 +3454,7 @@ bool subselect_hash_sj_engine::exec(THD *thd) { } /* Set tmp_param only if its usable, i.e. there are Copy_field's. */ - tmp_param = &(item->unit->outer_query_block()->join->tmp_table_param); + tmp_param = (item->unit->outer_query_block()->join->tmp_table_param); if (tmp_param && tmp_param->copy_fields.empty()) tmp_param = nullptr; } // if (!is_materialized) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 4882708fbf1f..67ebbdb96d9d 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -631,22 +632,24 @@ bool Item_sum::has_aggregate_ref_in_group_by(uchar *) { return aggr_query_block != nullptr && aggr_query_block->group_fix_field; } -Field *Item_sum::create_tmp_field(bool, TABLE *table) { +Field *Item_sum::create_tmp_field(bool, TABLE *table, MEM_ROOT *root) { DBUG_TRACE; Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; + switch (result_type()) { case REAL_RESULT: - field = new (*THR_MALLOC) Field_double( + field = new (pq_check_root) Field_double( max_length, is_nullable(), item_name.ptr(), decimals, false, true); break; case INT_RESULT: - field = new (*THR_MALLOC) Field_longlong(max_length, is_nullable(), + field = new (pq_check_root) Field_longlong(max_length, is_nullable(), item_name.ptr(), unsigned_flag); break; case STRING_RESULT: return make_string_field(table); case DECIMAL_RESULT: - field = Field_new_decimal::create_from_item(this); + field = Field_new_decimal::create_from_item(this, root); break; case ROW_RESULT: default: @@ -1732,9 +1735,11 @@ bool Item_sum_hybrid::setup_hybrid(Item *item, Item *value_arg) { return false; } -Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) { +Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table, MEM_ROOT *root) { DBUG_TRACE; Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; + if (args[0]->type() == Item::FIELD_ITEM) { field = down_cast(args[0])->field; @@ -1753,22 +1758,22 @@ Field *Item_sum_hybrid::create_tmp_field(bool group, TABLE *table) { */ switch (args[0]->data_type()) { case MYSQL_TYPE_DATE: - field = new (*THR_MALLOC) Field_newdate(is_nullable(), item_name.ptr()); + field = new (pq_check_root) Field_newdate(is_nullable(), item_name.ptr()); break; case MYSQL_TYPE_TIME: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_timef(is_nullable(), item_name.ptr(), decimals); break; case MYSQL_TYPE_TIMESTAMP: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_timestampf(is_nullable(), item_name.ptr(), decimals); break; case MYSQL_TYPE_DATETIME: - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_datetimef(is_nullable(), item_name.ptr(), decimals); break; default: - return Item_sum::create_tmp_field(group, table); + return Item_sum::create_tmp_field(group, table, root); } if (field) field->init(table); return field; @@ -2073,6 +2078,10 @@ double Aggregator_simple::arg_val_real() { return item_sum->args[0]->val_real(); } +longlong Aggregator_simple::arg_val_int() { + return item_sum->args[0]->val_int(); +} + bool Aggregator_simple::arg_is_null(bool use_null_value) { Item **item = item_sum->args; const uint item_count = item_sum->arg_count; @@ -2098,6 +2107,11 @@ double Aggregator_distinct::arg_val_real() { : item_sum->args[0]->val_real(); } +longlong Aggregator_distinct::arg_val_int() { + return use_distinct_values ? table->field[0]->val_int() + : item_sum->args[0]->val_int(); +} + bool Aggregator_distinct::arg_is_null(bool use_null_value) { if (use_distinct_values) { const bool rc = table->field[0]->is_null(); @@ -2124,7 +2138,7 @@ bool Item_sum_count::add() { if (aggr->arg_is_null(false)) { return current_thd->is_error(); } - count++; + count += is_fake ? args[0]->val_int() : 1; return current_thd->is_error(); } @@ -2169,6 +2183,27 @@ void Item_sum_count::cleanup() { bool Item_sum_avg::resolve_type(THD *thd) { if (Item_sum_sum::resolve_type(thd)) return true; + /** + * for the rewritten Item_sum_avg, we should keep the same precision as that + * of Item_sum_sum. For the case of "3.1415926", we obtain + * precision = len(31415926) = 8; + * decimals = len(1315926) = 7; + * max_length = len(3.1415926 + signed_flag) = 9; + * if scale == 2: scale(3.1415926) = 3.14 + */ + if (pq_avg_type == PQ_WORKER || pq_avg_type == PQ_LEADER) { + prec_increment = 0; + if (hybrid_type == DECIMAL_RESULT) { + f_precision = args[0]->decimal_precision() + DECIMAL_LONGLONG_DIGITS; + decimals = args[0]->decimals; + max_length = my_decimal_precision_to_length_no_truncation( + f_precision, decimals, unsigned_flag); + f_scale = args[0]->decimals; + dec_bin_size = my_decimal_get_binary_size(f_precision, f_scale); + } + return false; + } + set_nullable(true); null_value = true; prec_increment = thd->variables.div_precincrement; @@ -2194,28 +2229,32 @@ bool Item_sum_avg::resolve_type(THD *thd) { Item *Item_sum_avg::copy_or_same(THD *thd) { DBUG_TRACE; - Item *result = + Item_sum_avg *result = m_is_window_function ? this : new (thd->mem_root) Item_sum_avg(thd, this); + if (!result) return result; + result->pq_avg_type = pq_avg_type; return result; } -Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table) { +Field *Item_sum_avg::create_tmp_field(bool group, TABLE *table, MEM_ROOT *root) { DBUG_TRACE; Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; + if (group) { /* We must store both value and counter in the temporary table in one field. The easiest way is to do this is to store both value in a string and unpack on access. */ - field = new (*THR_MALLOC) Field_string( + field = new (pq_check_root) Field_string( ((hybrid_type == DECIMAL_RESULT) ? dec_bin_size : sizeof(double)) + sizeof(longlong), false, item_name.ptr(), &my_charset_bin); } else if (hybrid_type == DECIMAL_RESULT) field = Field_new_decimal::create_from_item(this); else - field = new (*THR_MALLOC) Field_double( + field = new (pq_check_root) Field_double( max_length, is_nullable(), item_name.ptr(), decimals, false, true); if (field) field->init(table); return field; @@ -2226,7 +2265,17 @@ void Item_sum_avg::clear() { Item_sum_sum::clear(); } bool Item_sum_avg::add() { assert(!m_is_window_function); if (Item_sum_sum::add()) return true; - if (!aggr->arg_is_null(true)) m_count++; + if (!aggr->arg_is_null(true)) { + if (pq_avg_type == PQ_REBUILD) { + uint32 extra_len; + auto val = args[0]->val_extra((uint32 *)&extra_len); + if (val != nullptr) { + m_count += uint8korr(val); + } + } else { + m_count++; + } + } return false; } @@ -2251,6 +2300,10 @@ double Item_sum_avg::val_real() { null_value = true; return 0.0; } + if (pq_avg_type == PQ_WORKER) { + return Item_sum_sum::val_real(); + } + return Item_sum_sum::val_real() / ulonglong2double(m_count); } } @@ -2333,6 +2386,10 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val) { return result; } + if (pq_avg_type == PQ_WORKER) { + return (dec_buffs + curr_dec_buff); + } + sum_dec = dec_buffs + curr_dec_buff; int2my_decimal(E_DEC_FATAL_ERROR, m_count, false, &cnt); my_decimal_div(E_DEC_FATAL_ERROR, val, sum_dec, &cnt, prec_increment); @@ -2340,6 +2397,11 @@ my_decimal *Item_sum_avg::val_decimal(my_decimal *val) { } } +const uchar *Item_sum_avg::val_extra(uint32 *len) { + *len = pq_extra_len(false); + return (const uchar*)(&m_count); +} + String *Item_sum_avg::val_str(String *str) { if (aggr) aggr->endup(); if (hybrid_type == DECIMAL_RESULT) return val_string_from_decimal(str); @@ -2571,9 +2633,11 @@ Item *Item_sum_variance::copy_or_same(THD *thd) { If we're grouping, then we need some space to serialize variables into, to pass around. */ -Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table) { +Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table, MEM_ROOT *root) { DBUG_TRACE; Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; + if (group) { /* We must store both value and counter in the temporary table in one field. @@ -2581,10 +2645,10 @@ Field *Item_sum_variance::create_tmp_field(bool group, TABLE *table) { and unpack on access. */ field = - new (*THR_MALLOC) Field_string(sizeof(double) * 2 + sizeof(longlong), + new (pq_check_root) Field_string(sizeof(double) * 2 + sizeof(longlong), false, item_name.ptr(), &my_charset_bin); } else - field = new (*THR_MALLOC) Field_double( + field = new (pq_check_root) Field_double( max_length, is_nullable(), item_name.ptr(), decimals, false, true); if (field != nullptr) field->init(table); @@ -3305,7 +3369,9 @@ void Item_sum_count::reset_field() { longlong nr = 0; assert(aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); - if (!args[0]->is_nullable() || !args[0]->is_null()) nr = 1; + if (!args[0]->is_nullable() || !args[0]->is_null()) { + nr = is_fake ? args[0]->val_int() : 1; + } int8store(result_field->field_ptr(), nr); } @@ -3318,8 +3384,14 @@ void Item_sum_avg::reset_field() { if (args[0]->null_value) { arg_dec = &decimal_zero; tmp = 0; - } else - tmp = 1; + } else { + uint32 extra_len; + if (pq_avg_type == PQ_REBUILD && args[0]->val_extra(&extra_len) != nullptr) { + tmp = sint8korr(args[0]->val_extra(&extra_len)); + } else { + tmp = 1; + } + } my_decimal2binary(E_DEC_FATAL_ERROR, arg_dec, res, f_precision, f_scale); res += dec_bin_size; int8store(res, tmp); @@ -3329,7 +3401,13 @@ void Item_sum_avg::reset_field() { if (args[0]->null_value) memset(res, 0, sizeof(double) + sizeof(longlong)); else { - longlong tmp = 1; + longlong tmp; + uint32 extra_len; + if (pq_avg_type == PQ_REBUILD && args[0]->val_extra(&extra_len) != nullptr) { + tmp = sint8korr(args[0]->val_extra(&extra_len)); + } else { + tmp = 1; + } float8store(res, nr); res += sizeof(double); int8store(res, tmp); @@ -3405,13 +3483,15 @@ void Item_sum_count::update_field() { uchar *res = result_field->field_ptr(); nr = sint8korr(res); - if (!args[0]->is_nullable() || !args[0]->is_null()) nr++; + if (!args[0]->is_nullable() || !args[0]->is_null()) { + nr += is_fake ? args[0]->val_int() : 1; + } int8store(res, nr); } void Item_sum_avg::update_field() { DBUG_TRACE; - longlong field_count; + ulonglong field_count; uchar *res = result_field->field_ptr(); assert(aggr->Aggrtype() != Aggregator::DISTINCT_AGGREGATOR); @@ -3421,12 +3501,19 @@ void Item_sum_avg::update_field() { if (!args[0]->null_value) { binary2my_decimal(E_DEC_FATAL_ERROR, res, dec_buffs + 1, f_precision, f_scale); - field_count = sint8korr(res + dec_bin_size); + field_count = uint8korr(res + dec_bin_size); my_decimal_add(E_DEC_FATAL_ERROR, dec_buffs, arg_val, dec_buffs + 1); my_decimal2binary(E_DEC_FATAL_ERROR, dec_buffs, res, f_precision, f_scale); res += dec_bin_size; - field_count++; + if (pq_avg_type == PQ_REBUILD) { + uint32 extra_len; + if (args[0]->val_extra(&extra_len) != nullptr) { + field_count += uint8korr(args[0]->val_extra(&extra_len)); + } + } else { + field_count++; + } int8store(res, field_count); } } else { @@ -3439,7 +3526,14 @@ void Item_sum_avg::update_field() { old_nr += nr; float8store(res, old_nr); res += sizeof(double); - field_count++; + if (pq_avg_type == PQ_REBUILD) { + uint32 extra_len; + if (args[0]->val_extra(&extra_len) != nullptr) { + field_count += sint8korr(args[0]->val_extra(&extra_len)); + } + } else { + field_count++; + } int8store(res, field_count); } } @@ -3574,6 +3668,8 @@ Item_avg_field::Item_avg_field(Item_result res_type, Item_sum_avg *item) { field = item->get_result_field(); set_nullable(true); hybrid_type = res_type; + avg_item = item; + pq_avg_type = item->pq_avg_type; set_data_type(hybrid_type == DECIMAL_RESULT ? MYSQL_TYPE_NEWDECIMAL : MYSQL_TYPE_DOUBLE); prec_increment = item->prec_increment; @@ -3595,6 +3691,10 @@ double Item_avg_field::val_real() { res = (field->field_ptr() + sizeof(double)); count = sint8korr(res); + if (pq_avg_type == PQ_WORKER) { + return nr; + } + if ((null_value = !count)) return 0.0; return nr / (double)count; } @@ -3606,6 +3706,13 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf) { if ((null_value = !count)) return nullptr; my_decimal dec_count, dec_field; + + if (pq_avg_type == PQ_WORKER) { + binary2my_decimal(E_DEC_FATAL_ERROR, field->ptr, dec_buf, f_precision, + f_scale); + return dec_buf; + } + binary2my_decimal(E_DEC_FATAL_ERROR, field->field_ptr(), &dec_field, f_precision, f_scale); int2my_decimal(E_DEC_FATAL_ERROR, count, false, &dec_count); @@ -3614,6 +3721,11 @@ my_decimal *Item_avg_field::val_decimal(my_decimal *dec_buf) { return dec_buf; } +const uchar *Item_avg_field::val_extra(uint32 *len) { + *len = pq_extra_len(false); + return (field->ptr + field->pack_length() - *len); +} + String *Item_avg_field::val_str(String *str) { // fix_fields() never calls for this Item if (hybrid_type == DECIMAL_RESULT) return val_string_from_decimal(str); @@ -4218,8 +4330,9 @@ void Item_func_group_concat::cleanup() { row_count = 0; } -Field *Item_func_group_concat::make_string_field(TABLE *table_arg) const { +Field *Item_func_group_concat::make_string_field(TABLE *table_arg, MEM_ROOT *root) const { Field *field; + MEM_ROOT *pq_check_root = root ? root : *THR_MALLOC; assert(collation.collation); /* Use mbminlen to determine maximum number of characters. @@ -4233,11 +4346,11 @@ Field *Item_func_group_concat::make_string_field(TABLE *table_arg) const { const uint32 max_characters = group_concat_max_len / collation.collation->mbminlen; if (max_characters > CONVERT_IF_BIGGER_TO_BLOB) - field = new (*THR_MALLOC) + field = new (pq_check_root) Field_blob(max_characters * collation.collation->mbmaxlen, is_nullable(), item_name.ptr(), collation.collation, true); else - field = new (*THR_MALLOC) Field_varstring( + field = new (pq_check_root) Field_varstring( max_characters * collation.collation->mbmaxlen, is_nullable(), item_name.ptr(), table_arg->s, collation.collation); @@ -6196,8 +6309,8 @@ void Item_rollup_sum_switcher::print(const THD *thd, String *str, } } -Field *Item_rollup_sum_switcher::create_tmp_field(bool group, TABLE *table) { - return master()->create_tmp_field(group, table); +Field *Item_rollup_sum_switcher::create_tmp_field(bool group, TABLE *table, MEM_ROOT *root) { + return master()->create_tmp_field(group, table, root); } void Item_rollup_sum_switcher::clear() { @@ -6483,3 +6596,8 @@ void Item_sum_collect::reset_field() { add(); store_result_field(); } + +bool need_extra(Item_sum *ref_item) +{ + return ref_item->sum_func() == Item_sum::AVG_FUNC; +} diff --git a/sql/item_sum.h b/sql/item_sum.h index 53c77703864d..89ddfab9b714 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -2,6 +2,7 @@ #define ITEM_SUM_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -148,6 +149,8 @@ class Aggregator { virtual my_decimal *arg_val_decimal(my_decimal *value) = 0; /** Floating point value of being-aggregated argument */ virtual double arg_val_real() = 0; + /** Longlong point value of being-aggregated argument */ + virtual longlong arg_val_int() = 0; /** NULLness of being-aggregated argument. @@ -497,6 +500,7 @@ class Item_sum : public Item_func { WF allowance status afterwards. */ nesting_map save_deny_window_func; + Item_sum *orig_func {nullptr}; protected: /** @@ -606,7 +610,8 @@ class Item_sum : public Item_func { aggregator_clear(); } virtual void make_unique() { force_copy_fields = true; } - virtual Field *create_tmp_field(bool group, TABLE *table); + virtual Field *create_tmp_field(bool group, TABLE *table, + MEM_ROOT *root = nullptr); /// argument used by walk method collect_grouped_aggregates ("cga") struct Collect_grouped_aggregate_info { @@ -752,6 +757,10 @@ class Item_sum : public Item_func { */ bool wf_common_init(); + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; + virtual Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item); + virtual uint32 pq_extra_size() { return 0; } + protected: /* Raise an error (ER_NOT_SUPPORTED_YET) with the detail that this @@ -877,6 +886,7 @@ class Aggregator_distinct : public Aggregator { void endup() override; my_decimal *arg_val_decimal(my_decimal *value) override; double arg_val_real() override; + longlong arg_val_int() override; bool arg_is_null(bool use_null_value) override; bool unique_walk_function(void *element); @@ -899,6 +909,7 @@ class Aggregator_simple : public Aggregator { void endup() override {} my_decimal *arg_val_decimal(my_decimal *value) override; double arg_val_real() override; + longlong arg_val_int() override; bool arg_is_null(bool use_null_value) override; }; @@ -943,6 +954,7 @@ class Item_sum_num : public Item_sum { return get_time_from_numeric(ltime); /* Decimal or real */ } void reset_field() override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_sum_int : public Item_sum_num { @@ -979,10 +991,12 @@ class Item_sum_int : public Item_sum_num { }; class Item_sum_sum : public Item_sum_num { + public: + my_decimal dec_buffs[2]; + protected: Item_result hybrid_type; double sum; - my_decimal dec_buffs[2]; uint curr_dec_buff; bool resolve_type(THD *thd) override; /** @@ -1025,6 +1039,8 @@ class Item_sum_sum : public Item_sum_num { void update_field() override; const char *func_name() const override { return "sum"; } Item *copy_or_same(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; }; class Item_sum_count : public Item_sum_int { @@ -1037,8 +1053,15 @@ class Item_sum_count : public Item_sum_int { void cleanup() override; public: - Item_sum_count(const POS &pos, Item *item_par, PT_window *w) - : Item_sum_int(pos, item_par, w), count(0) {} + /* + * mark faked item_sum_count. when we have read one more + * records from table, the faked-item_sum_sum have the same result with the original + * Item_sum_count, then is_fake = false; + */ + bool is_fake{false}; //mark Item_sum_count + + Item_sum_count(const POS &pos, Item *item_par, PT_window *w, bool fake = false) + : Item_sum_int(pos, item_par, w), count(0), is_fake(fake) {} Item_sum_count(Item_int *number) : Item_sum_int(number), count(0) {} /** Constructs an instance for COUNT(DISTINCT) @@ -1051,11 +1074,11 @@ class Item_sum_count : public Item_sum_int { */ Item_sum_count(const POS &pos, PT_item_list *list, PT_window *w) - : Item_sum_int(pos, list, w), count(0) { + : Item_sum_int(pos, list, w), count(0), is_fake(false) { set_distinct(true); } Item_sum_count(THD *thd, Item_sum_count *item) - : Item_sum_int(thd, item), count(item->count) {} + : Item_sum_int(thd, item), count(item->count), is_fake(false) {} enum Sumfunctype sum_func() const override { return has_with_distinct() ? COUNT_DISTINCT_FUNC : COUNT_FUNC; } @@ -1075,6 +1098,9 @@ class Item_sum_count : public Item_sum_int { void update_field() override; const char *func_name() const override { return "count"; } Item *copy_or_same(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, + Item *item) override; }; /* Item to get the value of a stored sum function */ @@ -1134,14 +1160,28 @@ class Item_sum_num_field : public Item_sum_hybrid_field { bool is_null() override { return update_null_value() || null_value; } }; +enum PqAvgType{ + PQ_LEADER, + PQ_WORKER, + PQ_REBUILD, + PQ_INVALID +}; + class Item_avg_field : public Item_sum_num_field { public: uint f_precision, f_scale, dec_bin_size; uint prec_increment; + Item_sum_avg *avg_item; + PqAvgType pq_avg_type; Item_avg_field(Item_result res_type, Item_sum_avg *item); enum Type type() const override { return FIELD_AVG_ITEM; } double val_real() override; my_decimal *val_decimal(my_decimal *) override; + size_t pq_extra_len(bool) override { + return ((pq_avg_type == PQ_WORKER || pq_avg_type == PQ_LEADER) + ? sizeof(longlong) : 0); + }; + const uchar *val_extra(uint32 *len) override; String *val_str(String *) override; bool resolve_type(THD *) override { return false; } const char *func_name() const override { @@ -1280,6 +1320,7 @@ class Item_sum_avg final : public Item_sum_sum { typedef Item_sum_sum super; my_decimal m_avg_dec; double m_avg; + PqAvgType pq_avg_type {PQ_INVALID}; Item_sum_avg(const POS &pos, Item *item_par, bool distinct, PT_window *w) : Item_sum_sum(pos, item_par, distinct, w) {} @@ -1305,12 +1346,21 @@ class Item_sum_avg final : public Item_sum_sum { } const char *func_name() const override { return "avg"; } Item *copy_or_same(THD *thd) override; - Field *create_tmp_field(bool group, TABLE *table) override; + Field *create_tmp_field(bool group, TABLE *table, MEM_ROOT *root) override; void cleanup() override { m_count = 0; m_frame_null_count = 0; Item_sum_sum::cleanup(); } + + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, + Query_block *select, Item *item) override; + size_t pq_extra_len(bool group) override { + return ((!group && (pq_avg_type == PQ_WORKER || pq_avg_type == PQ_LEADER)) + ? sizeof(longlong) : 0); + } + const uchar *val_extra(uint32* len) override; }; class Item_sum_variance; @@ -1439,7 +1489,8 @@ class Item_sum_variance : public Item_sum_num { return sample ? "var_samp" : "variance"; } Item *copy_or_same(THD *thd) override; - Field *create_tmp_field(bool group, TABLE *table) override; + Field *create_tmp_field(bool group, TABLE *table, + MEM_ROOT *root = nullptr) override; enum Item_result result_type() const override { return REAL_RESULT; } void cleanup() override { count = 0; @@ -1475,6 +1526,8 @@ class Item_std_field final : public Item_variance_field { */ class Item_sum_std : public Item_sum_variance { + typedef Item_sum_variance Item_supper; + public: Item_sum_std(const POS &pos, Item *item_par, uint sample_arg, PT_window *w) : Item_sum_variance(pos, item_par, sample_arg, w) {} @@ -1645,12 +1698,13 @@ class Item_sum_hybrid : public Item_sum { void cleanup() override; bool any_value() { return was_values; } void no_rows_in_result() override; - Field *create_tmp_field(bool group, TABLE *table) override; + Field *create_tmp_field(bool group, TABLE *table, MEM_ROOT *root = nullptr) override; bool uses_only_one_row() const override { return m_optimize; } bool add() override; Item *copy_or_same(THD *thd) override; bool check_wf_semantics1(THD *thd, Query_block *select, Window_evaluation_requirements *r) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; private: /* @@ -1675,6 +1729,8 @@ class Item_sum_min final : public Item_sum_hybrid { : Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func() const override { return MIN_FUNC; } const char *func_name() const override { return "min"; } + Item* pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; private: Item_sum_min *clone_hybrid(THD *thd) const override; @@ -1689,6 +1745,8 @@ class Item_sum_max final : public Item_sum_hybrid { : Item_sum_hybrid(thd, item) {} enum Sumfunctype sum_func() const override { return MAX_FUNC; } const char *func_name() const override { return "max"; } + Item* pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; private: Item_sum_max *clone_hybrid(THD *thd) const override; @@ -1822,6 +1880,7 @@ class Item_sum_bit : public Item_sum { bool add() override; /// @returns true iff this is BIT_AND. inline bool is_and() const { return reset_bits != 0; } + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; private: /** @@ -1866,6 +1925,8 @@ class Item_sum_or final : public Item_sum_bit { Item_sum_or(THD *thd, Item_sum_or *item) : Item_sum_bit(thd, item) {} const char *func_name() const override { return "bit_or"; } Item *copy_or_same(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; }; class Item_sum_and final : public Item_sum_bit { @@ -1876,6 +1937,8 @@ class Item_sum_and final : public Item_sum_bit { Item_sum_and(THD *thd, Item_sum_and *item) : Item_sum_bit(thd, item) {} const char *func_name() const override { return "bit_and"; } Item *copy_or_same(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; }; class Item_sum_xor final : public Item_sum_bit { @@ -1888,6 +1951,8 @@ class Item_sum_xor final : public Item_sum_bit { Item_sum_xor(THD *thd, Item_sum_xor *item) : Item_sum_bit(thd, item) {} const char *func_name() const override { return "bit_xor"; } Item *copy_or_same(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; + Item_sum *pq_rebuild_sum_func(THD *thd, Query_block *select, Item *item) override; }; /* @@ -2133,7 +2198,8 @@ class Item_func_group_concat final : public Item_sum { enum Sumfunctype sum_func() const override { return GROUP_CONCAT_FUNC; } const char *func_name() const override { return "group_concat"; } Item_result result_type() const override { return STRING_RESULT; } - Field *make_string_field(TABLE *table_arg) const override; + Field *make_string_field(TABLE *table_arg, + MEM_ROOT *root = nullptr) const override; void clear() override; bool add() override; void reset_field() override { assert(0); } // not used @@ -2697,7 +2763,7 @@ class Item_rollup_sum_switcher final : public Item_sum { } void print(const THD *thd, String *str, enum_query_type query_type) const override; - Field *create_tmp_field(bool group, TABLE *table) override; + Field *create_tmp_field(bool group, TABLE *table, MEM_ROOT *root = nullptr) override; enum Sumfunctype sum_func() const override { return master()->sum_func(); } enum Sumfunctype real_sum_func() const override { diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 21bf2eae14fc..f5a3bab18600 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -2,6 +2,7 @@ #define ITEM_TIMEFUNC_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -69,6 +70,7 @@ class Item_func_period_add final : public Item_int_func { longlong val_int() override; const char *func_name() const override { return "period_add"; } bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_period_diff final : public Item_int_func { @@ -78,6 +80,7 @@ class Item_func_period_diff final : public Item_int_func { longlong val_int() override; const char *func_name() const override { return "period_diff"; } bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_to_days final : public Item_int_func { @@ -93,6 +96,7 @@ class Item_func_to_days final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_to_seconds final : public Item_int_func { @@ -118,6 +122,7 @@ class Item_func_to_seconds final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_dayofmonth final : public Item_int_func { @@ -132,6 +137,7 @@ class Item_func_dayofmonth final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -166,6 +172,7 @@ class Item_func_month final : public Item_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_monthname final : public Item_str_func { @@ -181,6 +188,7 @@ class Item_func_monthname final : public Item_str_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_dayofyear final : public Item_int_func { @@ -194,6 +202,7 @@ class Item_func_dayofyear final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_hour final : public Item_int_func { @@ -207,6 +216,7 @@ class Item_func_hour final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_time_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_minute final : public Item_int_func { @@ -220,6 +230,7 @@ class Item_func_minute final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_time_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_quarter final : public Item_int_func { @@ -233,6 +244,7 @@ class Item_func_quarter final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_second final : public Item_int_func { @@ -246,6 +258,7 @@ class Item_func_second final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_time_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_week final : public Item_int_func { @@ -261,6 +274,7 @@ class Item_func_week final : public Item_int_func { const char *func_name() const override { return "week"; } enum Functype functype() const override { return WEEK_FUNC; } bool resolve_type(THD *thd) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_yearweek final : public Item_int_func { @@ -274,6 +288,7 @@ class Item_func_yearweek final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_year final : public Item_int_func { @@ -289,6 +304,7 @@ class Item_func_year final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_typecast_year final : public Item_int_func { @@ -338,6 +354,7 @@ class Item_func_weekday : public Item_func { bool check_valid_arguments_processor(uchar *) override { return !has_date_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -363,6 +380,7 @@ class Item_func_dayname final : public Item_func_weekday { enum Item_result result_type() const override { return STRING_RESULT; } bool resolve_type(THD *thd) override; bool check_partition_func_processor(uchar *) override { return true; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /* @@ -446,6 +464,8 @@ class Item_func_unix_timestamp final : public Item_timeval_func { return ((func_arg->source == VGS_GENERATED_COLUMN) || (func_arg->source == VGS_CHECK_CONSTRAINT)); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_time_to_sec final : public Item_int_func { @@ -460,6 +480,7 @@ class Item_func_time_to_sec final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_time_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -561,6 +582,7 @@ class Item_temporal_hybrid_func : public Item_str_func { } bool get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzydate) override; bool get_time(MYSQL_TIME *ltime) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; /* @@ -859,6 +881,7 @@ class Item_date_literal final : public Item_date_func { table_map not_null_tables() const override { return used_tables(); } void cleanup() override { assert(marker == MARKER_NONE); } bool eq(const Item *item, bool binary_cmp) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -866,6 +889,7 @@ class Item_date_literal final : public Item_date_func { */ class Item_time_literal final : public Item_time_func { MYSQL_TIME_cache cached_time; + uint pq_dec_arg; public: /** @@ -874,6 +898,7 @@ class Item_time_literal final : public Item_time_func { @param dec_arg number of fractional digits in ltime. */ Item_time_literal(MYSQL_TIME *ltime, uint dec_arg) { + pq_dec_arg = dec_arg; set_data_type_time(std::min(dec_arg, uint(DATETIME_MAX_DECIMALS))); cached_time.set_time(ltime, decimals); fixed = true; @@ -900,6 +925,7 @@ class Item_time_literal final : public Item_time_func { table_map not_null_tables() const override { return used_tables(); } void cleanup() override { assert(marker == MARKER_NONE); } bool eq(const Item *item, bool binary_cmp) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -944,6 +970,7 @@ class Item_datetime_literal final : public Item_datetime_func { table_map not_null_tables() const override { return used_tables(); } void cleanup() override { assert(marker == MARKER_NONE); } bool eq(const Item *item, bool binary_cmp) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1045,6 +1072,7 @@ class Item_func_curtime_local final : public Item_func_curtime { Item_func_curtime_local(const POS &pos, uint8 dec_arg) : Item_func_curtime(pos, dec_arg) {} const char *func_name() const override { return "curtime"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_curtime_utc final : public Item_func_curtime { @@ -1099,6 +1127,7 @@ class Item_func_curdate_local final : public Item_func_curdate { public: explicit Item_func_curdate_local(const POS &pos) : Item_func_curdate(pos) {} const char *func_name() const override { return "curdate"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_curdate_utc final : public Item_func_curdate { @@ -1108,6 +1137,7 @@ class Item_func_curdate_utc final : public Item_func_curdate { public: Item_func_curdate_utc(const POS &pos) : Item_func_curdate(pos) {} const char *func_name() const override { return "utc_date"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; /** @@ -1207,6 +1237,8 @@ class Item_func_sysdate_local final : public Item_datetime_func { table_map get_initial_pseudo_tables() const override { return RAND_TABLE_BIT; } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_from_days final : public Item_date_func { @@ -1222,6 +1254,8 @@ class Item_func_from_days final : public Item_date_func { if (param_type_is_default(thd, 0, 1, MYSQL_TYPE_LONGLONG)) return true; return Item_date_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_date_format final : public Item_str_func { @@ -1240,6 +1274,8 @@ class Item_func_date_format final : public Item_str_func { bool resolve_type(THD *thd) override; uint format_length(const String *format); bool eq(const Item *item, bool binary_cmp) const override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_from_unixtime final : public Item_datetime_func { @@ -1250,6 +1286,7 @@ class Item_func_from_unixtime final : public Item_datetime_func { enum Functype functype() const override { return FROM_UNIXTIME_FUNC; } bool resolve_type(THD *thd) override; bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /* @@ -1280,6 +1317,7 @@ class Item_func_convert_tz final : public Item_datetime_func { bool resolve_type(THD *) override; bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; void cleanup() override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_sec_to_time final : public Item_time_func { @@ -1295,6 +1333,7 @@ class Item_func_sec_to_time final : public Item_time_func { } const char *func_name() const override { return "sec_to_time"; } bool get_time(MYSQL_TIME *ltime) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; extern const char *interval_names[]; @@ -1329,6 +1368,7 @@ class Item_date_add_interval final : public Item_temporal_hybrid_func { bool eq(const Item *item, bool binary_cmp) const override; void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_extract final : public Item_int_func { @@ -1381,6 +1421,9 @@ class Item_extract final : public Item_int_func { } return true; } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_typecast_date final : public Item_date_func { @@ -1406,6 +1449,7 @@ class Item_typecast_date final : public Item_date_func { bool is_explicit_cast() const { return m_explicit_cast; } bool get_date(MYSQL_TIME *ltime, my_time_flags_t fuzzy_date) override; const char *cast_type() const { return "date"; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_typecast_time final : public Item_time_func { @@ -1443,6 +1487,9 @@ class Item_typecast_time final : public Item_time_func { set_nullable(true); return false; } + + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_typecast_datetime final : public Item_datetime_func { @@ -1481,6 +1528,8 @@ class Item_typecast_datetime final : public Item_datetime_func { return false; } bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_makedate final : public Item_date_func { @@ -1495,6 +1544,8 @@ class Item_func_makedate final : public Item_date_func { if (param_type_is_default(thd, 0, -1, MYSQL_TYPE_LONGLONG)) return true; return Item_date_func::resolve_type(thd); } + + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_add_time final : public Item_temporal_hybrid_func { @@ -1522,6 +1573,7 @@ class Item_func_add_time final : public Item_temporal_hybrid_func { const char *func_name() const override { return "add_time"; } enum Functype functype() const override { return ADDTIME_FUNC; } int get_sign() const { return sign; } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_timediff final : public Item_time_func { @@ -1544,6 +1596,7 @@ class Item_func_timediff final : public Item_time_func { return false; } bool get_time(MYSQL_TIME *ltime) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_maketime final : public Item_time_func { @@ -1561,6 +1614,7 @@ class Item_func_maketime final : public Item_time_func { } const char *func_name() const override { return "maketime"; } bool get_time(MYSQL_TIME *ltime) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_microsecond final : public Item_int_func { @@ -1574,6 +1628,7 @@ class Item_func_microsecond final : public Item_int_func { bool check_valid_arguments_processor(uchar *) override { return !has_time_args(); } + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_timestamp_diff final : public Item_int_func { @@ -1594,6 +1649,7 @@ class Item_func_timestamp_diff final : public Item_int_func { } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; enum date_time_format { @@ -1619,6 +1675,7 @@ class Item_func_get_format final : public Item_str_ascii_func { } void print(const THD *thd, String *str, enum_query_type query_type) const override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_str_to_date final : public Item_temporal_hybrid_func { @@ -1633,6 +1690,8 @@ class Item_func_str_to_date final : public Item_temporal_hybrid_func { : Item_temporal_hybrid_func(pos, a, b) {} const char *func_name() const override { return "str_to_date"; } bool resolve_type(THD *) override; + Item *pq_clone(THD *thd, Query_block *select) override; + bool pq_copy_from(THD *thd, Query_block *select, Item *item) override; }; class Item_func_last_day final : public Item_date_func { @@ -1656,6 +1715,7 @@ class Item_func_internal_update_time final : public Item_datetime_func { const char *func_name() const override { return "internal_update_time"; } bool resolve_type(THD *thd) override; bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; class Item_func_internal_check_time final : public Item_datetime_func { @@ -1666,6 +1726,7 @@ class Item_func_internal_check_time final : public Item_datetime_func { const char *func_name() const override { return "internal_check_time"; } bool resolve_type(THD *thd) override; bool get_date(MYSQL_TIME *res, my_time_flags_t fuzzy_date) override; + Item *pq_clone(THD *thd, Query_block *select) override; }; /* Function prototypes */ diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index ba0ba0e0cbd0..5b2957d40614 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -2,6 +2,7 @@ #define ITEM_XMLFUNC_INCLUDED /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -74,6 +75,7 @@ class Item_xml_str_func : public Item_str_func { if (!nodeset_func_permanent) nodeset_func = nullptr; } bool check_function_as_value_generator(uchar *) override { return false; } + enum Functype functype() const override { return XML_FUNC; } protected: /** diff --git a/sql/records.cc b/sql/records.cc index 48b49d471246..a91977f81ea8 100644 --- a/sql/records.cc +++ b/sql/records.cc @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -53,6 +54,11 @@ #include "sql/sql_tmp_table.h" #include "sql/table.h" #include "sql/timing_iterator.h" +#include "sql/sql_parallel.h" +#include "sql/exchange_sort.h" +#include "sql/sql_parse.h" +#include "sql/mysqld.h" +#include "sql/exchange.h" using std::string; using std::vector; @@ -152,7 +158,7 @@ template class IndexScanIterator; See AccessPath::count_examined_rows. */ AccessPath *create_table_access_path(THD *thd, TABLE *table, QEP_TAB *qep_tab, - bool count_examined_rows) { + bool count_examined_rows, bool *pq_replace_path) { // If only 'table' is given, assume no quick, no condition. if (table != nullptr && qep_tab != nullptr) { assert(table == qep_tab->table()); @@ -160,16 +166,23 @@ AccessPath *create_table_access_path(THD *thd, TABLE *table, QEP_TAB *qep_tab, table = qep_tab->table(); } + bool could_replace_path = false; + AccessPath *path; if (qep_tab != nullptr && qep_tab->quick() != nullptr) { path = NewIndexRangeScanAccessPath(thd, table, qep_tab->quick(), count_examined_rows); + could_replace_path = true; } else if (qep_tab != nullptr && qep_tab->table_ref != nullptr && qep_tab->table_ref->is_recursive_reference()) { path = NewFollowTailAccessPath(thd, table, count_examined_rows); } else { path = NewTableScanAccessPath(thd, table, count_examined_rows); + could_replace_path = true; } + + if (pq_replace_path) *pq_replace_path = could_replace_path; + if (qep_tab != nullptr && qep_tab->position() != nullptr) { SetCostOnTableAccessPath(*thd->cost_model(), qep_tab->position(), /*is_after_filter=*/false, path); @@ -320,6 +333,344 @@ int IndexRangeScanIterator::Read() { return 0; } +ParallelScanIterator::ParallelScanIterator(THD *thd, QEP_TAB *tab, TABLE *table, + ha_rows *examined_rows, JOIN *join, + Gather_operator *gather, + bool stab_output, uint ref_length) + : TableRowIterator(thd, table), + m_record(table->record[0]), + m_examined_rows(examined_rows), + m_dop(gather->m_dop), + m_join(join), + m_gather(gather), + m_record_gather(nullptr), + m_order(nullptr), + m_tab(tab), + m_stable_sort(stab_output), + m_ref_length(ref_length) { + thd->pq_iterator = this; +} + +/** + * construct filesort on leader when needing stab_output or merge_sort + * + * @retavl: false if success, and otherwise true + */ +bool ParallelScanIterator::pq_make_filesort(Filesort **sort) { + *sort = NULL; + + /** construct sort order based on group */ + if (m_join->pq_rebuilt_group) { + assert(m_join->query_block->saved_group_list_ptrs); + restore_list(m_join->query_block->saved_group_list_ptrs, + m_join->query_block->group_list); + m_order = restore_optimized_group_order( + m_join->query_block->group_list, + m_join->saved_optimized_vars.optimized_group_flags); + } else { + /** + * if sorting is built after the first rewritten table, then + * we have no need to rebuilt the sort order on leader, because + * leader will do SortingIterator. + */ + if (m_join->pq_last_sort_idx >= (int)m_join->tables && + m_join->qep_tab[m_join->pq_last_sort_idx].filesort != nullptr) { + return false; + } else { + if ((m_order = m_join->order.order) == nullptr) { + if (m_join->m_ordered_index_usage == JOIN::ORDERED_INDEX_ORDER_BY && + m_join->query_block->saved_order_list_ptrs) { + restore_list(m_join->query_block->saved_order_list_ptrs, + m_join->query_block->order_list); + m_order = restore_optimized_group_order( + m_join->query_block->order_list, + m_join->saved_optimized_vars.optimized_order_flags); + } else { + std::vector used_key_fields; + if (get_table_key_fields(&m_join->qep_tab0[m_tab->pos], + used_key_fields) || + DBUG_EVALUATE_IF("pq_msort_error1", true, false)) + return true; + + if (set_key_order(m_tab, used_key_fields, &m_order, + &m_join->ref_items[REF_SLICE_PQ_TMP]) || + DBUG_EVALUATE_IF("pq_msort_error2", true, false)) + return true; + } + } + } + } + + /** support stable sort on TABLE/INDEX SCAN */ + if (m_order || m_stable_sort) { + *sort = m_tab->filesort; + if (!(*sort)) { + (*sort) = new (m_join->thd->pq_mem_root) + Filesort(m_join->thd, {m_tab->table()}, false, m_order, HA_POS_ERROR, + false, false, false, false); + if (!(*sort) || DBUG_EVALUATE_IF("pq_msort_error3", true, false)) + return true; + } + } + return false; +} + +/** + * init the mq_record_gather + */ +bool ParallelScanIterator::pq_init_record_gather() { + THD *thd = m_join->thd; + Filesort *sort = NULL; + if (pq_make_filesort(&sort)) return true; + m_record_gather = new (thd->pq_mem_root) MQ_record_gather(thd, m_tab); + if (!m_record_gather || + m_record_gather->mq_scan_init(sort, m_gather->m_dop, m_ref_length, + m_stable_sort) || + DBUG_EVALUATE_IF("pq_msort_error4", true, false)) + return true; + + /** set each worker's MQ_handle */ + for (uint i = 0; i < m_gather->m_dop; i++) { + m_gather->m_workers[i]->m_handle = + m_record_gather->m_exchange->get_mq_handle(i); + } + return false; +} + +/** + * launch worker threads + * + * @retval: false if success, and otherwise true + */ +bool ParallelScanIterator::pq_launch_worker() { + THD *thd = m_join->thd; + assert(thd == current_thd); + + Gather_operator *gather = m_tab->gather; + PQ_worker_manager **workers = gather->m_workers; + int launch_workers = 0; + + /** when workers encounter error during execution, directly abort the parallel + * execution */ + for (uint i = 0; i < m_gather->m_dop; i++) { + assert(!workers[i]->thd_worker && + (workers[i]->m_status == PQ_worker_state::INIT)); + if (thd->is_error() || thd->pq_error) goto err; + my_thread_handle id; + id.thread = 0; + /** + * pq_worker_error8: all workers are fialed to landuch + * pq_worker_error9: worker's id in [0, 2, 4, ..] are failed to lanuch + */ + if (DBUG_EVALUATE_IF("pq_worker_error8", false, true) && + DBUG_EVALUATE_IF("pq_worker_error9", (i % 2), true)) { + mysql_thread_create(key_thread_parallel_query, &id, NULL, pq_worker_exec, + (void *)workers[i]); + } + workers[i]->thread_id = id; + int expected_status = PQ_worker_state::READY | PQ_worker_state::COMPELET | + PQ_worker_state::ERROR; + if (id.thread != 0) { + /** Record the thread id so that we can later determine whether the thread + * started */ + workers[i]->m_active = workers[i]->wait_for_status(thd, expected_status); + /** partial workers may fail before execution */ + if (!workers[i]->m_active || + DBUG_EVALUATE_IF("pq_worker_error7", (i >= m_gather->m_dop / 2), + false)) { + goto err; + } + launch_workers++; + } else { + sql_print_warning("worker %d has failed to start up\n", i); + MQueue_handle *mq_handler = m_record_gather->m_exchange->get_mq_handle(i); + if (mq_handler) mq_handler->set_datched_status(MQ_HAVE_DETACHED); + } + } + /** if all workers are not launched, then directly return false */ + if (!launch_workers) goto err; + return false; + +err: + for (uint i = 0; i < m_gather->m_dop; i++) { + if (workers[i]->thread_id.thread && workers[i]->thd_worker) { + workers[i]->thd_worker->pq_error = true; + } + } + return true; +} + +/** + * wait all workers finish their execution + */ +void ParallelScanIterator::pq_wait_workers_finished() { + THD *leader_thd = m_join->thd; + assert(leader_thd == current_thd); + + /** + * leader first detached the message queue, and then wait workers finish + * the execution. The reason for detach MQ is that leader has fetched the + * satisfied #records (e.g., limit operation). + */ + if (m_record_gather) { + Exchange *exchange = m_record_gather->m_exchange; + MQueue_handle *m_handle = nullptr; + for (uint i = 0; i < m_gather->m_dop; i++) { + if ((m_handle = exchange->get_mq_handle(i))) { + m_handle->set_datched_status(MQ_HAVE_DETACHED); + } + } + } + + /** + * wait all such workers to finish execution, two conditions must meet: + * c1: the worker thread has been created + * c2: the worker has not yet finished + */ + int expected_status = PQ_worker_state::COMPELET | PQ_worker_state::ERROR; + for (uint i = 0; i < m_gather->m_dop; i++) { + if (m_gather->m_workers[i]->thread_id.thread != 0) // c1 + { + if (m_gather->m_workers[i]->m_active && + !(((unsigned int)m_gather->m_workers[i]->m_status) & + PQ_worker_state::COMPELET)) { + m_gather->m_workers[i]->wait_for_status(leader_thd, expected_status); + } + my_thread_join(&m_gather->m_workers[i]->thread_id, NULL); + } + } +} + +int ParallelScanIterator::pq_error_code() { + THD *thd = m_join->thd; + + if (m_gather->m_ha_err == HA_ERR_TABLE_DEF_CHANGED) { + m_gather->m_ha_err = 0; + return HA_ERR_TABLE_DEF_CHANGED; + } + + if (thd->is_killed()) { + thd->send_kill_message(); + } + + /** collect worker threads status from DA info */ + JOIN *tmplate_join = m_gather->m_template_join; + THD *temp_thd = tmplate_join->thd; + thd->pq_status_reset(); + thd->pq_merge_status(temp_thd); + Diagnostics_area *da = temp_thd->get_stmt_da(); + if (temp_thd->is_error()) { + temp_thd->raise_condition(da->mysql_errno(), da->returned_sqlstate(), + Sql_condition::SL_ERROR, da->message_text()); + } + + if (da->cond_count() > 0) { + Diagnostics_area::Sql_condition_iterator it = da->sql_conditions(); + const Sql_condition *cond; + while ((cond = it++)) { + thd->raise_condition(cond->mysql_errno(), NULL, cond->severity(), + cond->message_text()); + } + } + /** output parallel error code */ + if (!temp_thd->is_error() && !thd->is_error() && thd->pq_error && + !thd->running_explain_analyze) { + my_error(ER_PARALLEL_EXEC_ERROR, MYF(0)); + } + return 1; +} + +bool ParallelScanIterator::Init() { + assert(current_thd == m_join->thd); + if (m_gather->init() || /** cur innodb data, + should be called first(will change dop based on + split count) */ + pq_init_record_gather() || /** init mq_record_gather */ + pq_launch_worker() || /** launch worker threads */ + DBUG_EVALUATE_IF("pq_worker_error6", true, false)) { + m_join->thd->pq_error = true; + return true; + } + return false; +} + +int ParallelScanIterator::Read() { + /** kill query */ + if (m_join->thd->is_killed()) { + m_join->thd->send_kill_message(); + return 1; + } + /** fetch message from MQ to table->record[0] */ + if (m_record_gather->mq_scan_next()) return 0; + return -1; +} + +int ParallelScanIterator::End() { + /** wait all workers to finish their execution */ + pq_wait_workers_finished(); + /** output error code */ + return pq_error_code(); +} + +ParallelScanIterator::~ParallelScanIterator() { + table()->file->ha_index_or_rnd_end(); + /** cleanup m_record_gather */ + if (m_record_gather) { + m_record_gather->mq_scan_end(); + } +} + +PQblockScanIterator::PQblockScanIterator(THD *thd, TABLE *table, uchar *record, + ha_rows *examined_rows, + Gather_operator *gather, + bool need_rowid) + : TableRowIterator(thd, table), + m_record(record), + m_examined_rows(examined_rows), + m_pq_ctx(gather->m_pq_ctx), + keyno(gather->keyno), + m_gather(gather), + m_need_rowid(need_rowid) { + thd->pq_iterator = this; +} + +bool PQblockScanIterator::Init() { + table()->file->pq_worker_scan_init(keyno, m_pq_ctx); + return false; +} + +int PQblockScanIterator::End() { + assert(thd() && thd()->pq_leader); + if (m_gather) m_gather->signalAll(); + return -1; +} + +PQblockScanIterator::~PQblockScanIterator() {} + +int PQblockScanIterator::Read() { + int tmp; + while ((tmp = table()->file->ha_pq_next(m_record, m_pq_ctx))) { + /* + ha_rnd_next can return RECORD_DELETED for MyISAM when one thread is + reading and another deleting without locks. + */ + if (tmp == HA_ERR_RECORD_DELETED && !thd()->killed) continue; + return HandleError(tmp); + } + + if (m_examined_rows != nullptr) { + ++*m_examined_rows; + } + // write row_id into file + if (m_need_rowid) { + assert(table()->file->ht->db_type == DB_TYPE_INNODB); + assert(table()->record[0] == m_record); + table()->file->position(m_record); + } + + return 0; +} + TableScanIterator::TableScanIterator(THD *thd, TABLE *table, double expected_rows, ha_rows *examined_rows) diff --git a/sql/row_iterator.h b/sql/row_iterator.h index 0f014582e247..aaf126fcee0c 100644 --- a/sql/row_iterator.h +++ b/sql/row_iterator.h @@ -2,6 +2,7 @@ #define SQL_ROW_ITERATOR_H_ /* Copyright (c) 2018, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -186,6 +187,14 @@ class RowIterator { virtual RowIterator *real_iterator() { return this; } virtual const RowIterator *real_iterator() const { return this; } + /** + * Ends the iterator + * @return 0: the normal iterator + * @return 1: the ParallelScanIterator + * @retrun -1: the PQblockScanIterator + */ + virtual int End() { return 0; } + protected: THD *thd() const { return m_thd; } diff --git a/sql/sorting_iterator.h b/sql/sorting_iterator.h index 18ce47b14b59..8eb9c14f3880 100644 --- a/sql/sorting_iterator.h +++ b/sql/sorting_iterator.h @@ -2,6 +2,7 @@ #define SQL_SORTING_ITERATOR_H_ /* Copyright (c) 2018, 2021, Oracle and/or its affiliates. + Copyright (c) 2022, Huawei Technologies Co., Ltd. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, @@ -86,6 +87,8 @@ class SortingIterator final : public RowIterator { int Read() override { return m_result_iterator->Read(); } + int End() override { return m_source_iterator->End(); } + void SetNullRowFlag(bool is_null_row) override { if (m_result_iterator == nullptr) { // If we don't have a result yet, it will come up with the flag unset.