From 8b7c32666fa7ebf17b0ab64f70ba9b18b65d6ef4 Mon Sep 17 00:00:00 2001 From: Georgi Kodinov Date: Thu, 13 Jan 2022 10:54:14 +0200 Subject: [PATCH] Bug #33747036: Make the THD parameter to table_access_factory_v1::create accept NULL as valid RB#27558 Added support for table access running in a non-mysqld thread. Added test. --- .../test/table_access/test_table_access.cc | 38 ++++++++++++++++++- .../services/bits/table_access_bits.h | 5 ++- sql/server_component/table_access_service.cc | 18 +++++++-- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/components/test/table_access/test_table_access.cc b/components/test/table_access/test_table_access.cc index e5d15aecd917..7022a61f69f7 100644 --- a/components/test/table_access/test_table_access.cc +++ b/components/test/table_access/test_table_access.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2020, 2021, Oracle and/or its affiliates. +/* Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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, @@ -31,6 +31,7 @@ #include #include #include +#include REQUIRES_SERVICE_PLACEHOLDER_AS(mysql_current_thread_reader, current_thd_srv); REQUIRES_SERVICE_PLACEHOLDER_AS(udf_registration, udf_srv); @@ -822,6 +823,40 @@ static char *test_table_access_driver(UDF_INIT *, UDF_ARGS *args, char *result, return nullptr; } +#define CONST_STR_AND_LEN(x) x, sizeof(x) - 1 + +/** + @param [out] status: true for failure, false otherwise + */ +static void thd_function(bool *ret) { + TA_table tb = nullptr; + Table_access ta = nullptr; + size_t ticket = 0; + bool txn_started = false; + *ret = true; + + ta = ta_factory_srv->create(nullptr, 1); + if (!ta) goto cleanup; + ticket = ta_srv->add(ta, CONST_STR_AND_LEN("mysql"), CONST_STR_AND_LEN("db"), + TA_READ); + if (ta_srv->begin(ta)) goto cleanup; + txn_started = true; + tb = ta_srv->get(ta, ticket); + if (!tb) goto cleanup; + + *ret = false; +cleanup: + if (txn_started) ta_srv->rollback(ta); + if (ta) ta_factory_srv->destroy(ta); +} + +static bool test_native_thread() { + bool retval = true; + std::thread thd(thd_function, &retval); + thd.join(); + return retval; +} + mysql_service_status_t test_table_access_init() { if (udf_srv->udf_register(udf_name, Item_result::STRING_RESULT, (Udf_func_any)test_table_access_driver, udf_init, @@ -836,6 +871,7 @@ mysql_service_status_t test_table_access_init() { */ (void)test_math_insert_utf8mb3(nullptr); (void)test_math_insert_utf8mb4(nullptr); + if (test_native_thread()) return 1; return 0; } diff --git a/include/mysql/components/services/bits/table_access_bits.h b/include/mysql/components/services/bits/table_access_bits.h index 2bde15c57fb9..a8357261125d 100644 --- a/include/mysql/components/services/bits/table_access_bits.h +++ b/include/mysql/components/services/bits/table_access_bits.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2020, 2021, Oracle and/or its affiliates. +/* Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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, @@ -110,7 +110,8 @@ DEFINE_SERVICE_HANDLE(TA_key); Create a table access object. @sa destroy_table_access_v1_t - @param thd The current session. + @param thd The current session. Pass a null ptr if running from a non-MySQLd + thread @param count The maximum number of tables to access. @note The table access service will create a child session diff --git a/sql/server_component/table_access_service.cc b/sql/server_component/table_access_service.cc index 0b0b10c20e9f..ac638edef5dc 100644 --- a/sql/server_component/table_access_service.cc +++ b/sql/server_component/table_access_service.cc @@ -1,4 +1,4 @@ -/* Copyright (c) 2020, 2021, Oracle and/or its affiliates. +/* Copyright (c) 2020, 2022, Oracle and/or its affiliates. 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, @@ -580,12 +580,20 @@ void TA_key_impl::key_copy(uchar *record) { Table_access_impl::Table_access_impl(THD *thd, size_t count) : m_current_count(0), m_max_count(count), m_write(false), m_in_tx(false) { - assert(thd != nullptr); m_parent_thd = thd; m_child_thd = new THD(true); - m_child_thd->copy_table_access_properties(m_parent_thd); + if (m_parent_thd) + m_child_thd->copy_table_access_properties(m_parent_thd); + else { + void *dummy_p = nullptr; + m_child_thd->thread_stack = (char *)&dummy_p; + m_child_thd->security_context()->assign_user( + STRING_WITH_LEN("table_access")); + m_child_thd->security_context()->skip_grants("", ""); + my_thread_init(); + } m_child_thd->real_id = my_thread_self(); m_child_thd->set_new_thread_id(); @@ -616,7 +624,7 @@ Table_access_impl::~Table_access_impl() { m_child_thd->release_resources(); m_child_thd->restore_globals(); - m_parent_thd->store_globals(); + if (m_parent_thd) m_parent_thd->store_globals(); Global_THD_manager::get_instance()->remove_thd(m_child_thd); @@ -625,6 +633,8 @@ Table_access_impl::~Table_access_impl() { delete[] m_table_array; delete[] m_table_state_array; + if (!m_parent_thd) my_thread_end(); + // FIXME : kill flag ? // FIXME : nested THD status variables ? }