From 9348e56e808940f820bd0b5313edd042d165c21b Mon Sep 17 00:00:00 2001 From: Kirk Rodrigues <2454684+kirkrodrigues@users.noreply.github.com> Date: Tue, 2 Jul 2024 06:46:46 -0400 Subject: [PATCH] Refactor SQLitePreparedSelectStatement.* --- .../src/clp/SQLitePreparedSelectStatement.cpp | 43 ++++++----- .../src/clp/SQLitePreparedSelectStatement.hpp | 75 ++++++++++--------- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/components/core/src/clp/SQLitePreparedSelectStatement.cpp b/components/core/src/clp/SQLitePreparedSelectStatement.cpp index d86c2e8ec..285bc37e1 100644 --- a/components/core/src/clp/SQLitePreparedSelectStatement.cpp +++ b/components/core/src/clp/SQLitePreparedSelectStatement.cpp @@ -14,12 +14,15 @@ #include "ErrorCode.hpp" #include "SQLitePreparedStatement.hpp" +using std::string; +using std::vector; + namespace clp { auto SQLitePreparedSelectStatement::create_sqlite_prepared_select_statement( - std::vector const& columns_to_select, + vector const& columns_to_select, std::string_view table, - std::vector const& where_clause, - std::vector const& ordering_clause, + vector const& where_clause_predicates, + vector const& sort_keys, sqlite3* db_handle ) -> SQLitePreparedSelectStatement { if (columns_to_select.empty()) { @@ -27,11 +30,11 @@ auto SQLitePreparedSelectStatement::create_sqlite_prepared_select_statement( ErrorCode_Failure, __FILENAME__, __LINE__, - "clp::SQLitePreparedSelectStatement Failed: no column to select." + "clp::SQLitePreparedSelectStatement: No columns to select." ); } - std::unordered_map idx_map; + std::unordered_map selected_column_to_idx; fmt::memory_buffer statement_buffer; auto statement_buffer_ix{std::back_inserter(statement_buffer)}; @@ -43,45 +46,45 @@ auto SQLitePreparedSelectStatement::create_sqlite_prepared_select_statement( ); size_t idx{0}; for (auto const& column : columns_to_select) { - idx_map.emplace(column, idx++); + selected_column_to_idx.emplace(column, idx++); } - if (false == where_clause.empty()) { + if (false == where_clause_predicates.empty()) { bool is_first{true}; - for (auto const& filter : where_clause) { - fmt::format_to(statement_buffer_ix, " {} {}", is_first ? "WHERE" : "AND", filter); + for (auto const& predicate : where_clause_predicates) { + fmt::format_to(statement_buffer_ix, " {} {}", is_first ? "WHERE" : "AND", predicate); is_first = false; } } - if (false == ordering_clause.empty()) { + if (false == sort_keys.empty()) { fmt::format_to(statement_buffer_ix, " ORDER BY"); bool is_first{true}; - for (auto const& ordering : ordering_clause) { + for (auto const& sort_key : sort_keys) { if (is_first) { - fmt::format_to(statement_buffer_ix, " {}", ordering); + fmt::format_to(statement_buffer_ix, " {}", sort_key); is_first = false; continue; } - fmt::format_to(statement_buffer_ix, ", {}", ordering); + fmt::format_to(statement_buffer_ix, ", {}", sort_key); } } return SQLitePreparedSelectStatement{ {statement_buffer.data(), statement_buffer.size()}, db_handle, - idx_map + selected_column_to_idx }; } -auto SQLitePreparedSelectStatement::get_selected_column_idx(std::string const& selected_column +auto SQLitePreparedSelectStatement::get_selected_column_idx(string const& column_name ) const -> size_t { - auto const idx_it{m_idx_map.find(selected_column)}; - if (m_idx_map.cend() == idx_it) { - std::string const msg{ - "clp::SQLitePreparedSelectStatement Failed with unknown selected column: " + auto const idx_it{m_selected_column_to_idx.find(column_name)}; + if (m_selected_column_to_idx.cend() == idx_it) { + string const msg{ + "clp::SQLitePreparedSelectStatement: " + column_name + " is not a selected column." }; - throw OperationFailed(ErrorCode_Failure, __FILENAME__, __LINE__, msg + selected_column); + throw OperationFailed(ErrorCode_BadParam, __FILENAME__, __LINE__, msg + column_name); } return idx_it->second; } diff --git a/components/core/src/clp/SQLitePreparedSelectStatement.hpp b/components/core/src/clp/SQLitePreparedSelectStatement.hpp index d53e199b4..0a052934c 100644 --- a/components/core/src/clp/SQLitePreparedSelectStatement.hpp +++ b/components/core/src/clp/SQLitePreparedSelectStatement.hpp @@ -2,7 +2,6 @@ #define CLP_SQLITEPREPAREDSELECTSTATEMENT_HPP #include -#include #include #include #include @@ -14,8 +13,8 @@ #include "TraceableException.hpp" /** - * This class provides abstractions to a sqlite select statement. It maintains a map to lookup the - * index of a selected column in the statement from a given name. + * A SQLite `SELECT` prepared statement that maintains a mapping between each selected column and + * its index, so that each column in the result set can be retrieved using its name. */ namespace clp { class SQLitePreparedSelectStatement : public SQLitePreparedStatement { @@ -40,63 +39,65 @@ class SQLitePreparedSelectStatement : public SQLitePreparedStatement { std::string m_msg; }; - // Factory functions. + // Factory functions /** - * Constructs and returns a SQLite select statement with given parameters. - * @param columns_to_select The name of columns to select. + * Constructs a SQLite `SELECT` statement with the given parameters. + * @param columns_to_select The names of the columns to select. * @param table The name of the table to select from. - * @param where_clause SQLite `WHERE` clause to filter rows in the result set. Each element is - * a formatted comparison. All the comparisons are chained with `AND` logic operator. - * @param ordering_clause SQLite `ORDER BY` clause to sort the result set. + * @param where_clause_predicates Optional predicates for the `WHERE` clause. + * @param sort_keys Optional sort keys for the `ORDER BY` clause. These may be in the form + * "" OR " ". * @param db_handle - * @return a new constructed select statement. + * @return The SQLite statement. * @throw clp::SQLitePreparedStatement::OperationFailed on failure. */ [[nodiscard]] static auto create_sqlite_prepared_select_statement( std::vector const& columns_to_select, std::string_view table, - std::vector const& where_clause, - std::vector const& ordering_clause, + std::vector const& where_clause_predicates, + std::vector const& sort_keys, sqlite3* db_handle ) -> SQLitePreparedSelectStatement; - ~SQLitePreparedSelectStatement() override = default; - - // Deletes copy constructor and assignment. + // Constructors and assignment operators + // Disable copy constructor and assignment operator SQLitePreparedSelectStatement(SQLitePreparedSelectStatement const&) = delete; auto operator=(SQLitePreparedSelectStatement const&) -> SQLitePreparedSelectStatement& = delete; - // Defines default move constructor and assignment. + // Use default move constructor and assignment operator SQLitePreparedSelectStatement(SQLitePreparedSelectStatement&& rhs) noexcept = default; auto operator=(SQLitePreparedSelectStatement&& rhs ) noexcept -> SQLitePreparedSelectStatement& = default; + // Destructor + ~SQLitePreparedSelectStatement() override = default; + // Methods /** - * @param selected_column - * @return The int value from the selected column. - * @throw OperationFailed if the name is not a valid selected column. + * @param column_name + * @return The selected column's value as an int. + * @throw OperationFailed if the name is not a selected column. */ - [[nodiscard]] auto column_int(std::string const& selected_column) const -> int { + [[nodiscard]] auto column_int(std::string const& column_name) const -> int { return SQLitePreparedStatement::column_int( - static_cast(get_selected_column_idx(selected_column)) + static_cast(get_selected_column_idx(column_name)) ); } /** - * @param selected_column - * @return The int64 value from the selected column. - * @throw OperationFailed if the name is not a valid selected column. + * @param column_name + * @return The selected column's value as an int64. + * @throw OperationFailed if the name is not a selected column. */ - [[nodiscard]] auto column_int64(std::string const& selected_column) const -> int64_t { + [[nodiscard]] auto column_int64(std::string const& column_name) const -> int64_t { return SQLitePreparedStatement::column_int64( - static_cast(get_selected_column_idx(selected_column)) + static_cast(get_selected_column_idx(column_name)) ); } /** * @param selected_column - * @param value Returns the string value from the selected column. + * @param value Returns the selected column's value as a string. * @throw OperationFailed if the name is not a valid selected column. */ auto column_string(std::string const& selected_column, std::string& value) const -> void { @@ -108,26 +109,26 @@ class SQLitePreparedSelectStatement : public SQLitePreparedStatement { private: /** - * Constructor. It should not be accessible outside of the class. - * `create_sqlite_prepared_select_statement` should be used to create an instance of this - * class. + * @param statement + * @param db_handle + * @param selected_column_to_idx */ explicit SQLitePreparedSelectStatement( std::string_view statement, sqlite3* db_handle, - std::unordered_map idx_map + std::unordered_map selected_column_to_idx ) : SQLitePreparedStatement{statement.data(), statement.size(), db_handle}, - m_idx_map{std::move(idx_map)} {} + m_selected_column_to_idx{std::move(selected_column_to_idx)} {} /** - * @param selected_column - * @return The idx of the selected column in the statement. - * @throw OperationFailed if the name doesn't appear in the select statement. + * @param column_name + * @return Index of the selected column in the statement. + * @throw OperationFailed if the name is not a selected column. */ - [[nodiscard]] auto get_selected_column_idx(std::string const& selected_column) const -> size_t; + [[nodiscard]] auto get_selected_column_idx(std::string const& column_name) const -> size_t; - std::unordered_map m_idx_map; + std::unordered_map m_selected_column_to_idx; }; } // namespace clp