169 lines
12 KiB
C++
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 ¶ms, 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 ¤t, 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 ¶ms) -> 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 ¶ms, 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);
|
|
}
|
|
|
|
}
|