diff --git a/sql/pq_condition.cc b/sql/pq_condition.cc index 5cc139cde346..35e87e4947bd 100644 --- a/sql/pq_condition.cc +++ b/sql/pq_condition.cc @@ -31,7 +31,7 @@ #include "sql/opt_range.h" #include "sql/sql_lex.h" -static const enum_field_types NO_PQ_SUPPORTED_FIELD_TYPES [] = { +const enum_field_types NO_PQ_SUPPORTED_FIELD_TYPES [] = { MYSQL_TYPE_TINY_BLOB, MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_BLOB, @@ -40,7 +40,7 @@ static const enum_field_types NO_PQ_SUPPORTED_FIELD_TYPES [] = { MYSQL_TYPE_GEOMETRY }; -static const Item_sum::Sumfunctype NO_PQ_SUPPORTED_AGG_FUNC_TYPES [] = { +const Item_sum::Sumfunctype NO_PQ_SUPPORTED_AGG_FUNC_TYPES [] = { Item_sum::COUNT_DISTINCT_FUNC, Item_sum::SUM_DISTINCT_FUNC, Item_sum::AVG_DISTINCT_FUNC, @@ -51,7 +51,7 @@ static const Item_sum::Sumfunctype NO_PQ_SUPPORTED_AGG_FUNC_TYPES [] = { Item_sum::VARIANCE_FUNC }; -static const Item_func::Functype NO_PQ_SUPPORTED_FUNC_TYPES [] = { +const Item_func::Functype NO_PQ_SUPPORTED_FUNC_TYPES [] = { Item_func::MATCH_FUNC, Item_func::SUSERVAR_FUNC, Item_func::FUNC_SP, @@ -61,7 +61,7 @@ static const Item_func::Functype NO_PQ_SUPPORTED_FUNC_TYPES [] = { Item_func::XML_FUNC }; -static const char* NO_PQ_SUPPORTED_FUNC_ARGS [] = { +const char* NO_PQ_SUPPORTED_FUNC_ARGS [] = { "rand", "json_valid", "json_length", @@ -80,11 +80,11 @@ static const char* NO_PQ_SUPPORTED_FUNC_ARGS [] = { "des_decrypt" // Data truncation }; -static const char* NO_PQ_SUPPORTED_FUNC_NO_ARGS [] = { +const char* NO_PQ_SUPPORTED_FUNC_NO_ARGS [] = { "release_all_locks" }; -static const Item_ref::Ref_Type NO_PQ_SUPPORTED_REF_TYPES[] = { +const Item_ref::Ref_Type NO_PQ_SUPPORTED_REF_TYPES[] = { Item_ref::OUTER_REF, Item_ref::AGGREGATE_REF }; @@ -92,7 +92,7 @@ static const Item_ref::Ref_Type NO_PQ_SUPPORTED_REF_TYPES[] = { /** * return true when type is a not_supported_field; return false otherwise. */ -static bool pq_not_support_datatype(enum_field_types type) { +bool pq_not_support_datatype(enum_field_types type) { for (const enum_field_types &field_type : NO_PQ_SUPPORTED_FIELD_TYPES) { if (type == field_type) { return true; @@ -105,7 +105,7 @@ static bool pq_not_support_datatype(enum_field_types type) { /** * check PQ supported function type */ -static bool pq_not_support_functype(Item_func::Functype type) { +bool pq_not_support_functype(Item_func::Functype type) { for (const Item_func::Functype &func_type : NO_PQ_SUPPORTED_FUNC_TYPES) { if (type == func_type) { return true; @@ -118,7 +118,7 @@ static bool pq_not_support_functype(Item_func::Functype type) { /** * check PQ supported function */ -static bool pq_not_support_func(Item_func *func) { +bool pq_not_support_func(Item_func *func) { if (pq_not_support_functype(func->functype())) { return true; } @@ -141,7 +141,7 @@ static bool pq_not_support_func(Item_func *func) { /** * check PQ support aggregation function */ -static bool pq_not_support_aggr_functype(Item_sum::Sumfunctype type) { +bool pq_not_support_aggr_functype(Item_sum::Sumfunctype type) { for (const Item_sum::Sumfunctype &sum_func_type : NO_PQ_SUPPORTED_AGG_FUNC_TYPES) { if (sum_func_type == type) { return true; @@ -154,7 +154,7 @@ static bool pq_not_support_aggr_functype(Item_sum::Sumfunctype type) { /** * check PQ supported ref function */ -static bool pq_not_support_ref(Item_ref *ref) { +bool pq_not_support_ref(Item_ref *ref) { Item_ref::Ref_Type type = ref->ref_type(); for (auto &ref_type : NO_PQ_SUPPORTED_REF_TYPES) { if (type == ref_type) { @@ -172,9 +172,9 @@ struct PQ_CHECK_ITEM_TYPE { PQ_CHECK_ITEM_FUN fun_ptr; }; -static bool check_pq_support_fieldtype(Item *item); +bool check_pq_support_fieldtype(Item *item); -static bool check_pq_support_fieldtype_of_field_item(Item *item) { +bool check_pq_support_fieldtype_of_field_item(Item *item) { Field *field = static_cast(item)->field; DBUG_ASSERT(field); // not supported for generated column @@ -186,7 +186,7 @@ static bool check_pq_support_fieldtype_of_field_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_func_item(Item *item) { +bool check_pq_support_fieldtype_of_func_item(Item *item) { Item_func *func = static_cast(item); DBUG_ASSERT(func); @@ -241,7 +241,7 @@ static bool check_pq_support_fieldtype_of_func_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_cond_item(Item *item) { +bool check_pq_support_fieldtype_of_cond_item(Item *item) { Item_cond *cond = static_cast(item); DBUG_ASSERT(cond); @@ -261,7 +261,7 @@ static bool check_pq_support_fieldtype_of_cond_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_sum_func_item(Item *item) { +bool check_pq_support_fieldtype_of_sum_func_item(Item *item) { Item_sum *sum = static_cast(item); if (!sum || pq_not_support_aggr_functype(sum->sum_func())) { return false; @@ -277,7 +277,7 @@ static bool check_pq_support_fieldtype_of_sum_func_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_ref_item(Item *item) { +bool check_pq_support_fieldtype_of_ref_item(Item *item) { Item_ref *item_ref = down_cast(item); if (!item_ref || pq_not_support_ref(item_ref)) { return false; @@ -291,7 +291,7 @@ static bool check_pq_support_fieldtype_of_ref_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_cache_item(Item *item) { +bool check_pq_support_fieldtype_of_cache_item(Item *item) { Item_cache *item_cache = dynamic_cast(item); if (item_cache == nullptr) { return false; @@ -306,7 +306,7 @@ static bool check_pq_support_fieldtype_of_cache_item(Item *item) { return true; } -static bool check_pq_support_fieldtype_of_row_item(Item *item) { +bool check_pq_support_fieldtype_of_row_item(Item *item) { // check each item in Item_row Item_row *row_item = down_cast(item); for (uint i = 0; i < row_item->cols(); i++) { @@ -320,7 +320,7 @@ static bool check_pq_support_fieldtype_of_row_item(Item *item) { return true; } -static PQ_CHECK_ITEM_TYPE g_check_item_type[] = { +PQ_CHECK_ITEM_TYPE g_check_item_type[] = { {Item::INVALID_ITEM, nullptr}, {Item::FIELD_ITEM, check_pq_support_fieldtype_of_field_item}, {Item::FUNC_ITEM, check_pq_support_fieldtype_of_func_item}, @@ -361,7 +361,7 @@ static PQ_CHECK_ITEM_TYPE g_check_item_type[] = { * true : supported * false : not supported */ -static bool check_pq_support_fieldtype(Item *item) { +bool check_pq_support_fieldtype(Item *item) { if (item == nullptr || pq_not_support_datatype(item->data_type())) { return false; } @@ -380,7 +380,7 @@ static bool check_pq_support_fieldtype(Item *item) { * true: contained * false: */ -static bool check_pq_sort_aggregation(const ORDER_with_src &order_list) { +bool check_pq_sort_aggregation(const ORDER_with_src &order_list) { if (!order_list.order) { return false; } @@ -812,7 +812,7 @@ bool suite_for_parallel_query(JOIN *join) { return true; } -static bool check_pq_running_threads(uint dop, ulong timeout_ms) { +bool check_pq_running_threads(uint dop, ulong timeout_ms) { bool success = false; mysql_mutex_lock(&LOCK_pq_threads_running); if (parallel_threads_running + dop > parallel_max_threads) { diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 39921d80c6b7..97322d77e833 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -339,6 +339,40 @@ void THD::enter_stage(const PSI_stage_info *new_stage, return; } +void THD::enter_cond(mysql_cond_t *cond, mysql_mutex_t *mutex, + const PSI_stage_info *stage, PSI_stage_info *old_stage, + const char *src_function, const char *src_file, + int src_line) { + DBUG_TRACE; + mysql_mutex_assert_owner(mutex); + /* + Sic: We don't lock LOCK_current_cond here. + If we did, we could end up in deadlock with THD::awake() + which locks current_mutex while LOCK_current_cond is locked. + */ + current_mutex = mutex; + current_cond = cond; + enter_stage(stage, old_stage, src_function, src_file, src_line); + return; +} + +void THD::exit_cond(const PSI_stage_info *stage, const char *src_function, + const char *src_file, int src_line) { + DBUG_TRACE; + /* + current_mutex must be unlocked _before_ LOCK_current_cond is + locked (if that would not be the case, you'll get a deadlock if someone + does a THD::awake() on you). + */ + mysql_mutex_assert_not_owner(current_mutex.load()); + mysql_mutex_lock(&LOCK_current_cond); + current_mutex = nullptr; + current_cond = nullptr; + mysql_mutex_unlock(&LOCK_current_cond); + enter_stage(stage, nullptr, src_function, src_file, src_line); + return; +} + void Open_tables_state::set_open_tables_state(Open_tables_state *state) { this->open_tables = state->open_tables; diff --git a/sql/sql_class.h b/sql/sql_class.h index 62e252b06ba8..9d1850a820e6 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -2674,36 +2674,10 @@ class THD : public MDL_context_owner, void enter_cond(mysql_cond_t *cond, mysql_mutex_t *mutex, const PSI_stage_info *stage, PSI_stage_info *old_stage, const char *src_function, const char *src_file, - int src_line) { - DBUG_TRACE; - mysql_mutex_assert_owner(mutex); - /* - Sic: We don't lock LOCK_current_cond here. - If we did, we could end up in deadlock with THD::awake() - which locks current_mutex while LOCK_current_cond is locked. - */ - current_mutex = mutex; - current_cond = cond; - enter_stage(stage, old_stage, src_function, src_file, src_line); - return; - } + int src_line); void exit_cond(const PSI_stage_info *stage, const char *src_function, - const char *src_file, int src_line) { - DBUG_TRACE; - /* - current_mutex must be unlocked _before_ LOCK_current_cond is - locked (if that would not be the case, you'll get a deadlock if someone - does a THD::awake() on you). - */ - mysql_mutex_assert_not_owner(current_mutex.load()); - mysql_mutex_lock(&LOCK_current_cond); - current_mutex = nullptr; - current_cond = nullptr; - mysql_mutex_unlock(&LOCK_current_cond); - enter_stage(stage, nullptr, src_function, src_file, src_line); - return; - } + const char *src_file, int src_line); virtual int is_killed() const final { return killed; } virtual THD *get_thd() { return this; } diff --git a/unittest/gunit/CMakeLists.txt b/unittest/gunit/CMakeLists.txt index 2650e439c980..71027294a62d 100644 --- a/unittest/gunit/CMakeLists.txt +++ b/unittest/gunit/CMakeLists.txt @@ -363,3 +363,4 @@ ADD_SUBDIRECTORY(group_replication) ADD_SUBDIRECTORY(libmysqlgcs) ADD_SUBDIRECTORY(temptable) ADD_SUBDIRECTORY(binlogevents) +ADD_SUBDIRECTORY(parallel_query) diff --git a/unittest/gunit/parallel_query/CMakeLists.txt b/unittest/gunit/parallel_query/CMakeLists.txt new file mode 100644 index 000000000000..b759d51b0dfb --- /dev/null +++ b/unittest/gunit/parallel_query/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. +# +# 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, +# as published by the Free Software Foundation. +# +# This program is also distributed with certain software (including +# but not limited to OpenSSL) that is licensed under separate terms, +# as designated in a particular file or component or in included license +# documentation. The authors of MySQL hereby grant you an additional +# permission to link the program and your derivative works with the +# separately licensed software that they have included with MySQL. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License, version 2.0, for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +SET(TESTS + pq_condition +) + +SET(ALL_PARALLEL_TESTS) +FOREACH(test ${TESTS}) + LIST(APPEND ALL_PARALLEL_TESTS ${test}-t.cc) +ENDFOREACH() + +IF(WIN32) + LIST(APPEND ALL_PARALLEL_TESTS ../../../sql/nt_servc.cc) +ENDIF() +MYSQL_ADD_EXECUTABLE(parallel_tests-t ${ALL_PARALLEL_TESTS} + ENABLE_EXPORTS + EXCLUDE_ON_SOLARIS + ADD_TEST parallel_tests-t) + +TARGET_LINK_LIBRARIES(parallel_tests-t + gunit_large + server_unittest_library + ) + +# Download TBB from https://www.threadingbuildingblocks.org +#SET(TBB_INCDIR /path/to/tbb43_20150611oss/include) +#SET(TBB_LIBDIR /path/to/tbb43_20150611oss/build/linux_intel64_gcc_cc4.9.1_libc2.12_kernel2.6.39_release) +#TARGET_LINK_LIBRARIES(parallel_tests-t tbb -L${TBB_LIBDIR} -Wl,-rpath=${TBB_LIBDIR}) +#INCLUDE_DIRECTORIES(${TBB_INCDIR}) + +TARGET_LINK_LIBRARIES(parallel_tests-t perfschema) + +ADD_DEPENDENCIES(parallel_tests-t GenError) + +FOREACH(test ${TESTS}) + SET(SRC_FILES ${test}-t.cc) + IF(WIN32) + LIST(APPEND SRC_FILES ../../../sql/nt_servc.cc) + ENDIF() + + MYSQL_ADD_EXECUTABLE(${test}-t ${SRC_FILES} + ENABLE_EXPORTS SKIP_INSTALL EXCLUDE_FROM_ALL) + + TARGET_LINK_LIBRARIES(${test}-t + gunit_large + server_unittest_library + ) + + ADD_DEPENDENCIES(${test}-t GenError) + +ENDFOREACH() + diff --git a/unittest/gunit/parallel_query/pq_condition-t.cc b/unittest/gunit/parallel_query/pq_condition-t.cc new file mode 100644 index 000000000000..35c2ca09d13b --- /dev/null +++ b/unittest/gunit/parallel_query/pq_condition-t.cc @@ -0,0 +1,325 @@ +/* Copyright (c) 2021, Huawei and/or its affiliates. All rights reserved. + + 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, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include +#include +#include + +#include "sql/pq_condition.h" +#include "sql/sql_class.h" +#include "sql/item_func.h" +#include "sql/item_cmpfunc.h" +#include "sql/item_sum.h" +#include "sql/sql_optimizer.h" +#include "sql/item_json_func.h" +#include "field_types.h" +#include "unittest/gunit/test_utils.h" +#include "unittest/gunit/parsertest.h" +#include "unittest/gunit/base_mock_field.h" +#include "unittest/gunit/fake_table.h" + + +using namespace std; +using my_testing::Server_initializer; + + +extern uint parallel_threads_running; +extern ulong parallel_max_threads; +extern bool pq_not_support_datatype(enum_field_types type); +extern bool pq_not_support_functype(Item_func::Functype type); +extern bool pq_not_support_func(Item_func *func); +extern bool pq_not_support_aggr_functype(Item_sum::Sumfunctype type); +extern bool pq_not_support_ref(Item_ref *ref); +extern bool check_pq_support_fieldtype_of_field_item(Item *item); +extern bool check_pq_support_fieldtype_of_func_item(Item *item); +extern bool check_pq_support_fieldtype_of_ref_item(Item *item); +extern bool check_pq_support_fieldtype_of_cache_item(Item *item); +extern bool check_pq_support_fieldtype(Item *item); +extern bool choose_parallel_scan_table(JOIN *join); +extern void set_pq_dop(THD *thd); +extern bool suite_for_parallel_query(THD *thd); +extern bool suite_for_parallel_query(JOIN *join); +extern bool check_pq_running_threads(uint dop, ulong timeout_ms); + + +namespace parallel_query_test { + +class PqConditionTest : public ::testing::Test { +protected: + virtual void SetUp() { initializer.SetUp(); } + virtual void TearDown() { initializer.TearDown(); } + + Server_initializer initializer; + MEM_ROOT m_mem_root; + Base_mock_field_json m_field; + Fake_TABLE m_table{&m_field}; + + Item_string *new_item_string(const char *str) { + return new Item_string(str, std::strlen(str), &my_charset_utf8mb4_bin); + } +}; + +TEST_F(PqConditionTest, pq_not_support_datatype) { + bool result; + + result = pq_not_support_datatype(MYSQL_TYPE_TINY_BLOB); + EXPECT_EQ(true, result); + + result = pq_not_support_datatype(MYSQL_TYPE_DECIMAL); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, pq_not_support_functype) { + bool result; + + result = pq_not_support_functype(Item_func::JSON_FUNC); + EXPECT_EQ(true, result); + + result = pq_not_support_functype(Item_func::EQ_FUNC); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, pq_not_support_func) { + bool result; + THD *thd = initializer.thd(); + + auto item1 = new Item_int(1); + auto item2 = new Item_int(1); + auto item3 = new Item_func_eq(item1, item2); + + result = pq_not_support_func(item3); + EXPECT_EQ(false, result); + + auto item4 = new Item_func_release_all_locks(POS()); + result = pq_not_support_func(item4); + EXPECT_EQ(true, result); + + auto item5 = new Item_func_json_remove(thd, new Item_field(&m_field), new_item_string("$.x")); + result = pq_not_support_func(item5); + EXPECT_EQ(true, result); + + auto item6 = new Item_func_release_lock(POS(), nullptr); + result = pq_not_support_func(item6); + EXPECT_EQ(true, result); +} + +TEST_F(PqConditionTest, pq_not_support_aggr_functype) { + bool result; + + result = pq_not_support_aggr_functype(Item_sum::COUNT_DISTINCT_FUNC); + EXPECT_EQ(true, result); + + result = pq_not_support_aggr_functype(Item_sum::COUNT_FUNC); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, pq_not_support_ref) { + bool result; + Item_ref *item = new Item_ref(POS(), "db", "table", "field"); + + result = pq_not_support_ref(item); + EXPECT_EQ(false, result); + + auto item_field = new Item_field(&m_field); + item = new Item_outer_ref(nullptr, item_field, nullptr); + result = pq_not_support_ref(item); + EXPECT_EQ(true, result); +} + +TEST_F(PqConditionTest, check_pq_support_fieldtype_of_field_item) { + bool result; + Item *item = new Item_field(&m_field); + + result = check_pq_support_fieldtype_of_field_item(item); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_support_fieldtype_of_func_item) { + bool result; + Item *item = new Item_func_release_all_locks(POS()); + + result = check_pq_support_fieldtype_of_func_item(item); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_support_fieldtype_of_ref_item) { + bool result; + auto item_field = new Item_field(&m_field); + Item *item = new Item_outer_ref(nullptr, item_field, nullptr); + + result = check_pq_support_fieldtype_of_ref_item(item); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_support_fieldtype_of_cache_item) { + bool result; + + result = check_pq_support_fieldtype_of_cache_item(nullptr); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_support_fieldtype) { + bool result; + Item *item = new Item_field(&m_field); + + result = check_pq_support_fieldtype(item); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, choose_parallel_scan_table) { + bool result; + SELECT_LEX *select_lex = parse(&initializer, "SELECT * FROM t1", 0); + JOIN *join = new (&m_mem_root) JOIN(initializer.thd(), select_lex); + join->tables = 1; + join->qep_tab = new (&m_mem_root) QEP_TAB(); + join->qep_tab->set_qs(new (&m_mem_root) QEP_shared); + + result = choose_parallel_scan_table(join); + EXPECT_EQ(true, result); +} + +TEST_F(PqConditionTest, set_pq_dop) { + THD *thd = initializer.thd(); + thd->no_pq = true; + thd->pq_dop = 2; + thd->variables.parallel_default_dop = 4; + + set_pq_dop(thd); + EXPECT_NE(thd->pq_dop, thd->variables.parallel_default_dop); + + thd->no_pq = false; + thd->variables.force_parallel_execute = false; + set_pq_dop(thd); + EXPECT_NE(thd->pq_dop, thd->variables.parallel_default_dop); + + thd->variables.force_parallel_execute = true; + set_pq_dop(thd); + EXPECT_NE(thd->pq_dop, thd->variables.parallel_default_dop); + + thd->pq_dop = 0; + set_pq_dop(thd); + EXPECT_EQ(thd->pq_dop, thd->variables.parallel_default_dop); +} + +TEST_F(PqConditionTest, set_pq_condition_status) { + THD *thd = initializer.thd(); + thd->no_pq = false; + thd->pq_dop = 0; + thd->variables.force_parallel_execute = true; + thd->variables.parallel_default_dop = 4; + + set_pq_condition_status(thd); + EXPECT_EQ(PqConditionStatus::ENABLED, thd->m_suite_for_pq); + + thd->no_pq = true; + thd->pq_dop = 0; + set_pq_condition_status(thd); + EXPECT_EQ(PqConditionStatus::NOT_SUPPORTED, thd->m_suite_for_pq); +} + +TEST_F(PqConditionTest, suite_for_parallel_query_thd) { + THD *thd = initializer.thd(); + thd->in_sp_trigger = false; + thd->m_attachable_trx = nullptr; + thd->tx_isolation = ISO_READ_UNCOMMITTED; + bool result; + + result = suite_for_parallel_query(thd); + EXPECT_EQ(true, result); + + thd->tx_isolation = ISO_SERIALIZABLE; + result = suite_for_parallel_query(thd); + EXPECT_EQ(false, result); + + thd->tx_isolation = ISO_READ_UNCOMMITTED; + thd->begin_attachable_ro_transaction(); + result = suite_for_parallel_query(thd); + EXPECT_EQ(false, result); + thd->end_attachable_transaction(); + + thd->in_sp_trigger = true; + result = suite_for_parallel_query(thd); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, suite_for_parallel_query_join) { + bool result; + SELECT_LEX *select_lex = parse(&initializer, "SELECT * FROM t1", 0); + JOIN *join = new (&m_mem_root) JOIN(initializer.thd(), select_lex); + + join->best_read = 0; + join->primary_tables = 1; + join->saved_tmp_table_param = new (&m_mem_root) Temp_table_param(); + result = suite_for_parallel_query(join); + EXPECT_EQ(false, result); + + join->best_read = 1000; + join->primary_tables = 0; + result = suite_for_parallel_query(join); + EXPECT_EQ(false, result); + + join->primary_tables = 1; + join->select_distinct = true; + result = suite_for_parallel_query(join); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_running_threads) { + uint dop = 1; + ulong timeout_ms = 0; + bool result; + + parallel_threads_running = 0; + parallel_max_threads = 2; + + result = check_pq_running_threads(dop, timeout_ms); + EXPECT_EQ(true, result); + EXPECT_EQ(1, current_thd->pq_threads_running); + EXPECT_EQ(1, parallel_threads_running); + + result = check_pq_running_threads(dop, timeout_ms); + EXPECT_EQ(true, result); + EXPECT_EQ(2, current_thd->pq_threads_running); + EXPECT_EQ(2, parallel_threads_running); + + result = check_pq_running_threads(dop, timeout_ms); + EXPECT_EQ(false, result); + + timeout_ms = 1; + result = check_pq_running_threads(dop, timeout_ms); + EXPECT_EQ(false, result); +} + +TEST_F(PqConditionTest, check_pq_conditions) { + bool result; + THD *thd = initializer.thd(); + SELECT_LEX *select = thd->lex->unit->first_select(); + JOIN *join = new (&m_mem_root) JOIN(thd, select); + select->join = join; + + result = check_pq_conditions(thd); + EXPECT_EQ(false, result); +} + +} // namespace parallel_query_test + +