-
Notifications
You must be signed in to change notification settings - Fork 481
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PS-9148: Add caching of dictionary table for component_masking_functions
https://perconadev.atlassian.net/browse/PS-9148 - Added caching of mysql.masking_dictionaries table content. - Implemented masking_dictionaries_flush() UDF which flushes data from the masking dictionaries table to the memory cache.
- Loading branch information
1 parent
6ec7af2
commit 21035cd
Showing
10 changed files
with
388 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
components/masking_functions/include/masking_functions/query_cache.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
/* Copyright (c) 2024 Percona LLC 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 as published by | ||
the Free Software Foundation; version 2 of the License. | ||
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 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, | ||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ | ||
|
||
#ifndef MASKING_FUNCTIONS_QUERY_CACHE_HPP | ||
#define MASKING_FUNCTIONS_QUERY_CACHE_HPP | ||
|
||
#include <map> | ||
#include <string> | ||
|
||
#include "masking_functions/sql_context.hpp" | ||
|
||
namespace masking_functions { | ||
|
||
class query_cache { | ||
public: | ||
query_cache(); | ||
|
||
bool check_term_presence_in_dictionary(const std::string &dictionary_name, | ||
const std::string &term) const; | ||
|
||
sql_context::optional_string select_random_term_for_dictionary( | ||
const std::string &dictionary_name) const; | ||
|
||
bool delete_for_dictionary(const std::string &dictionary_name); | ||
|
||
bool delete_for_dictionary_and_term(const std::string &dictionary_name, | ||
const std::string &term); | ||
|
||
bool insert_ignore_record(const std::string &dictionary_name, | ||
const std::string &term); | ||
bool load_cache(); | ||
|
||
private: | ||
sql_context::dict_container_type m_dict_cache; | ||
}; | ||
|
||
} // namespace masking_functions | ||
|
||
#endif // MASKING_FUNCTIONS_QUERY_CACHE_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
133 changes: 133 additions & 0 deletions
133
components/masking_functions/src/masking_functions/query_cache.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
/* Copyright (c) 2024 Percona LLC 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 as published by | ||
the Free Software Foundation; version 2 of the License. | ||
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 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, | ||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ | ||
|
||
#include "masking_functions/query_cache.hpp" | ||
|
||
#include "masking_functions/command_service_tuple.hpp" | ||
#include "masking_functions/primitive_singleton.hpp" | ||
#include "masking_functions/query_builder.hpp" | ||
|
||
#include <algorithm> | ||
|
||
namespace masking_functions { | ||
namespace { | ||
|
||
using global_command_services = masking_functions::primitive_singleton< | ||
masking_functions::command_service_tuple>; | ||
using global_query_builder = | ||
masking_functions::primitive_singleton<masking_functions::query_builder>; | ||
|
||
} // namespace | ||
|
||
query_cache::query_cache() { load_cache(); } | ||
|
||
bool query_cache::load_cache() { | ||
auto query = global_query_builder::instance().select_all_from_dictionary(); | ||
auto result = | ||
masking_functions::sql_context{global_command_services::instance()} | ||
.query_list(query); | ||
|
||
if (result.has_value()) { | ||
m_dict_cache.swap(result.value()); | ||
} | ||
|
||
return result.has_value(); | ||
} | ||
|
||
bool query_cache::check_term_presence_in_dictionary( | ||
const std::string &dictionary_name, const std::string &term) const { | ||
masking_functions::sql_context sql_ctx{global_command_services::instance()}; | ||
|
||
auto range = m_dict_cache.equal_range(dictionary_name); | ||
|
||
if (range.first == range.second) { | ||
return false; | ||
} | ||
|
||
if (term.length() == 0) { | ||
return true; | ||
} | ||
|
||
return std::find_if(range.first, range.second, [term](const auto &el) { | ||
return el.second == term; | ||
}) != range.second; | ||
} | ||
|
||
sql_context::optional_string query_cache::select_random_term_for_dictionary( | ||
const std::string &dictionary_name) const { | ||
auto range = m_dict_cache.equal_range(dictionary_name); | ||
|
||
if (range.first == range.second) { | ||
return std::nullopt; | ||
} | ||
|
||
int random_step = rand() % std::distance(range.first, range.second); | ||
std::advance(range.first, random_step); | ||
|
||
return sql_context::optional_string{std::in_place, range.first->second}; | ||
} | ||
|
||
bool query_cache::delete_for_dictionary(const std::string &dictionary_name) { | ||
masking_functions::sql_context sql_ctx{global_command_services::instance()}; | ||
auto query = | ||
global_query_builder::instance().delete_for_dictionary(dictionary_name); | ||
|
||
if (!sql_ctx.execute(query)) { | ||
return false; | ||
} | ||
|
||
m_dict_cache.erase(dictionary_name); | ||
return true; | ||
} | ||
|
||
bool query_cache::delete_for_dictionary_and_term( | ||
const std::string &dictionary_name, const std::string &term) { | ||
masking_functions::sql_context sql_ctx{global_command_services::instance()}; | ||
auto query = global_query_builder::instance().delete_for_dictionary_and_term( | ||
dictionary_name, term); | ||
|
||
if (!sql_ctx.execute(query)) { | ||
return false; | ||
} | ||
|
||
auto range = m_dict_cache.equal_range(dictionary_name); | ||
|
||
if (range.first != range.second) { | ||
auto it = std::find_if(range.first, range.second, [term](const auto &el) { | ||
return el.second == term; | ||
}); | ||
if (it != range.second) { | ||
m_dict_cache.erase(it); | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
bool query_cache::insert_ignore_record(const std::string &dictionary_name, | ||
const std::string &term) { | ||
masking_functions::sql_context sql_ctx{global_command_services::instance()}; | ||
auto query = global_query_builder::instance().insert_ignore_record( | ||
dictionary_name, term); | ||
|
||
if (!sql_ctx.execute(query)) { | ||
return false; | ||
} | ||
|
||
m_dict_cache.insert({dictionary_name, term}); | ||
return true; | ||
} | ||
|
||
} // namespace masking_functions |
Oops, something went wrong.