Files
noto/src/detail/sqlite_support.hpp
T
khodowany 2f3870baff
publish / publish (push) Successful in 16m12s
Cleanup
2026-10-08 02:13:03 -05:00

169 lines
12 KiB
C++

#pragma once
#include <chrono>
#include <cstddef>
#include <cstdint>
#include <expected>
#include <filesystem>
#include <functional>
#include <memory>
#include <optional>
#include <ostream>
#include <string>
#include <string_view>
#include <system_error>
#include <utility>
#include <variant>
#include <vector>
#include <sys/types.h>
#include <boost/asio/awaitable.hpp>
#include <sqlite3.h>
#include <modulus.hpp>
#include <noto/config.hpp>
#include <noto/detail/core.hpp>
#include <noto/detail/errors.hpp>
#include <noto/detail/sql.hpp>
#include <noto/schema.hpp>
#include <noto/transaction.hpp>
namespace noto::detail {
struct pending_statement_finalize {
pending_statement_finalize(std::shared_ptr<noto::detail::connection_core> owner_value, sqlite3_stmt *statement_value, std::bool_t counted_value);
pending_statement_finalize(pending_statement_finalize const &) = delete;
auto operator=(pending_statement_finalize const &) -> pending_statement_finalize & = delete;
~pending_statement_finalize();
auto finish() noexcept -> void;
std::shared_ptr<noto::detail::connection_core> owner{};
sqlite3_stmt *statement{};
std::bool_t counted{};
};
struct pending_transaction_rollback {
explicit pending_transaction_rollback(std::shared_ptr<noto::detail::connection_core> owner_value);
pending_transaction_rollback(pending_transaction_rollback const &) = delete;
auto operator=(pending_transaction_rollback const &) -> pending_transaction_rollback & = delete;
~pending_transaction_rollback();
auto finish() noexcept -> void;
std::shared_ptr<noto::detail::connection_core> owner{};
std::bool_t active{true};
};
struct file_identity {
dev_t device{};
ino_t inode{};
};
struct protected_path {
std::filesystem::path normalized{};
std::optional<file_identity> identity{};
};
struct export_column {
std::string quoted_name{};
};
struct export_table {
std::string quoted_name{};
std::vector<export_column> columns{};
};
struct export_schema {
std::vector<export_table> tables{};
std::vector<std::string> table_sql{};
std::vector<std::string> post_data_sql{};
std::bool_t has_sqlite_sequence{};
};
auto invalid_statement() -> std::expected<void, modulus::error>;
auto unavailable(std::string message) -> std::expected<void, modulus::error>;
auto invalid(std::string message) -> std::expected<void, modulus::error>;
auto timeout(std::string message) -> std::expected<void, modulus::error>;
auto resource_exhausted(std::string message) -> std::expected<void, modulus::error>;
auto contains_null(std::string_view value) -> std::bool_t;
auto sqlite_int_max() -> std::size_t;
auto validate_sqlite_milliseconds(std::chrono::milliseconds value, std::string_view label) -> std::expected<void, modulus::error>;
auto validate_path(std::string_view path, std::string_view label) -> std::expected<void, modulus::error>;
auto errno_status(std::string operation, std::int32_t code) -> std::expected<void, modulus::error>;
auto filesystem_status(std::string operation, std::error_code const &code) -> std::expected<void, modulus::error>;
auto close_fd(std::int32_t fd, std::string_view operation) -> std::expected<void, modulus::error>;
auto sync_file_path(std::string const &path, std::string_view operation) -> std::expected<void, modulus::error>;
auto sync_parent_directory(std::string const &path, std::string_view operation) -> std::expected<void, modulus::error>;
auto make_temporary_path(std::string const &target, std::string_view operation) -> std::expected<std::string, modulus::error>;
auto remove_file_noexcept(std::string const &path) noexcept -> void;
auto remove_file_if_exists(std::string const &path, std::string_view operation) -> std::expected<void, modulus::error>;
auto remove_database_sidecars(std::string const &path, std::string_view operation) -> std::expected<void, modulus::error>;
auto remove_database_files_noexcept(std::string const &path) noexcept -> void;
auto replace_file_atomically(std::string const &temporary, std::string const &destination, std::string_view operation) -> std::expected<void, modulus::error>;
auto validate_database_name(std::string_view name, std::string_view label) -> std::expected<void, modulus::error>;
auto open_flags(noto::connection_config const &config) -> std::int32_t;
auto valid_token(std::string_view value) -> std::bool_t;
auto transaction_mode_sql(noto::transaction_mode mode) -> std::string_view;
auto begin_operation(noto::detail::connection_core &core, std::string_view operation) -> std::expected<void, modulus::error>;
auto finish_operation(noto::detail::connection_core &core, std::expected<void, modulus::error> status) -> std::expected<void, modulus::error>;
auto validate_backup_options(noto::backup_options const &options) -> std::expected<void, modulus::error>;
auto validate_export_options(noto::export_options const &options) -> std::expected<void, modulus::error>;
auto exec_direct(sqlite3 *database, std::string const &sql, std::string_view operation) -> std::expected<void, modulus::error>;
auto configure_busy_timeout(sqlite3 *database, std::chrono::milliseconds timeout, std::string_view operation) -> std::expected<void, modulus::error>;
auto pragma_value_sql(std::variant<std::bool_t, std::int64_t, std::string> const &value) -> std::expected<std::string, modulus::error>;
auto set_pragma(sqlite3 *database, std::string const &name, std::variant<std::bool_t, std::int64_t, std::string> const &value) -> std::expected<void, modulus::error>;
auto open_configured_database(noto::connection_config const &config, std::chrono::milliseconds busy_timeout, sqlite3 **output) -> std::expected<void, modulus::error>;
auto retry_timeout(noto::detail::connection_core const &core, noto::backup_options const &options) -> std::chrono::milliseconds;
auto async_step_backup(noto::detail::connection_core &core, sqlite3_backup *backup, noto::backup_options const &options, std::string_view operation) -> boost::asio::awaitable<std::expected<std::int32_t, modulus::error>>;
auto close_sqlite_handle(sqlite3 *handle, std::string_view operation, std::expected<void, modulus::error> status) -> std::expected<void, modulus::error>;
auto async_copy_restore_source_to_file(noto::detail::connection_core &core, std::string const &path, std::string const &temporary, noto::backup_options const &options) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
auto close_database_for_atomic_restore(noto::detail::connection_core &core) -> std::expected<void, modulus::error>;
auto reopen_database_after_restore(noto::detail::connection_core &core) -> std::expected<void, modulus::error>;
auto restore_atomic_failure(noto::detail::connection_core &core, std::expected<void, modulus::error> status) -> std::expected<void, modulus::error>;
auto statement_is_open(noto::detail::statement_core const &core) -> std::bool_t;
auto untrack_statement(noto::detail::statement_core &statement) -> void;
auto bind_value(sqlite3_stmt *statement, std::int32_t index, noto::sqlite_value const &value, sqlite3 *database) -> std::expected<void, modulus::error>;
auto bind_values(sqlite3_stmt *statement, std::vector<noto::sqlite_value> const &params, sqlite3 *database) -> std::expected<void, modulus::error>;
auto column_value(sqlite3_stmt *statement, std::int32_t index) -> noto::sqlite_value;
auto current_row(sqlite3_stmt *statement) -> std::vector<noto::sqlite_value>;
auto column_names(sqlite3_stmt *statement) -> std::vector<std::string>;
auto value_result_bytes(noto::sqlite_value const &value) -> std::size_t;
auto add_result_bytes(std::size_t &current, std::size_t addition, noto::execute_options const &options) -> std::expected<void, modulus::error>;
auto track_result_columns(std::vector<std::string> const &columns, std::size_t &result_bytes, noto::execute_options const &options) -> std::expected<void, modulus::error>;
auto append_result_row(noto::query_result &result, std::vector<noto::sqlite_value> row, std::size_t &result_bytes, noto::execute_options const &options) -> std::expected<void, modulus::error>;
auto reset_statement_after_execute_failure(sqlite3_stmt *statement, sqlite3 *database, std::expected<void, modulus::error> status) -> std::expected<void, modulus::error>;
auto reset_and_bind(sqlite3_stmt *statement, sqlite3 *database, std::vector<noto::sqlite_value> const &params) -> std::expected<void, modulus::error>;
auto collect_result(sqlite3_stmt *statement, sqlite3 *database, noto::execute_options const &options) -> std::expected<noto::query_result, modulus::error>;
auto trailing_sql_is_empty(std::char_t const *tail) -> std::bool_t;
auto prepare_statement(sqlite3 *database, std::string const &sql, sqlite3_stmt **statement, std::string_view operation) -> std::expected<void, modulus::error>;
auto same_identity(file_identity const &left, file_identity const &right) -> std::bool_t;
auto normalized_path(std::string const &path, std::string_view operation) -> std::expected<std::filesystem::path, modulus::error>;
auto identity_for_path(std::filesystem::path const &path, std::string_view operation) -> std::expected<std::optional<file_identity>, modulus::error>;
auto protected_path_for(std::string const &path, std::string_view operation) -> std::expected<protected_path, modulus::error>;
auto same_protected_path(protected_path const &left, protected_path const &right) -> std::bool_t;
auto live_database_paths(sqlite3 *database) -> std::expected<std::vector<std::string>, modulus::error>;
auto validate_output_not_live_database(sqlite3 *database, std::string const &path, std::string_view label) -> std::expected<void, modulus::error>;
auto execute_prepared(sqlite3 *database, std::string const &sql, std::vector<noto::sqlite_value> const &params, noto::execute_options const &options) -> std::expected<noto::query_result, modulus::error>;
auto hex_literal(std::byte const *data, std::size_t size) -> std::string;
auto text_hex_literal(std::string const &value) -> std::string;
auto literal_sql(noto::sqlite_value const &value) -> std::expected<std::string, modulus::error>;
auto write_limited(std::ostream &output, std::string_view text, noto::export_options const &options, std::size_t &written) -> std::expected<void, modulus::error>;
auto column_text(sqlite3_stmt *statement, std::int32_t index) -> std::optional<std::string>;
auto identifier_character(std::char_t character) -> std::bool_t;
auto consume_keyword(std::string_view sql, std::size_t &position, std::string_view keyword) -> std::bool_t;
auto create_virtual_table_sql(std::string_view sql) -> std::bool_t;
auto table_exists(sqlite3 *database, std::string const &table_name) -> std::expected<std::bool_t, modulus::error>;
auto exportable_columns(sqlite3 *database, std::string const &table_name) -> std::expected<std::vector<export_column>, modulus::error>;
auto collect_export_schema(sqlite3 *database) -> std::expected<export_schema, modulus::error>;
auto export_table_rows(noto::detail::connection_core &core, export_table const &table, std::function<std::expected<void, modulus::error>(std::string_view)> const &write, noto::export_options const &options) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
auto export_sqlite_sequence(noto::detail::connection_core &core, std::function<std::expected<void, modulus::error>(std::string_view)> const &write, noto::export_options const &options) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
auto write_export(noto::detail::connection_core &core, std::function<std::expected<void, modulus::error>(std::string_view)> const &write, noto::export_options const &options) -> boost::asio::awaitable<std::expected<void, modulus::error>>;
template <typename VALUE>
auto failure_from(modulus::error error) -> std::expected<VALUE, modulus::error> {
return noto::detail::fail<VALUE>(std::move(error));
}
template <typename VALUE>
auto failure_from(std::expected<void, modulus::error> status) -> std::expected<VALUE, modulus::error> {
return noto::detail::fail<VALUE>(status);
}
}