Lightweight 0.20260617.0
Loading...
Searching...
No Matches
Backup.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../SqlConnection.hpp"
6#include "../SqlSchema.hpp"
7#include "../SqlStatement.hpp"
8#include "../ThreadSafeQueue.hpp"
9#include "ChunkPlanner.hpp"
10#include "SqlBackup.hpp"
11#include "WorkerChunkArchive.hpp"
12
13#include <cstdint>
14#include <filesystem>
15#include <map>
16#include <mutex>
17#include <optional>
18#include <string>
19#include <utility>
20
21#if defined(__clang__)
22 #pragma clang diagnostic push
23 #pragma clang diagnostic ignored "-Wnullability-extension"
24#endif
25#include <zip.h>
26#if defined(__clang__)
27 #pragma clang diagnostic pop
28#endif
29
30namespace Lightweight::SqlBackup::detail
31{
32
33/// Context for backup operations, shared between backup workers.
34struct BackupContext
35{
36 zip_t* zip;
37 std::mutex& zipMutex;
38 ProgressManager& progress;
39 SqlConnectionString const& connectionString;
40 std::string const& schema;
41 std::map<std::string, std::string>* checksums; // entryName -> SHA-256 hash
42 std::mutex* checksumMutex;
43 RetrySettings const& retrySettings;
44 BackupSettings const& backupSettings;
45};
46
47/// Builds a SELECT query with ORDER BY for deterministic results.
48///
49/// This is critical for:
50/// 1. MS SQL Server which requires ORDER BY when using OFFSET
51/// 2. Deterministic results for resumption after transient errors
52///
53/// For MS SQL Server, DECIMAL columns are wrapped in CONVERT(VARCHAR, ...) to preserve
54/// full precision, as the ODBC driver loses precision when reading DECIMAL as SQL_C_CHAR.
55///
56/// @param formatter The SQL query formatter for the database.
57/// @param serverType The type of database server.
58/// @param schema The schema name.
59/// @param tableName The table name.
60/// @param columns The table columns.
61/// @param primaryKeys The primary key columns.
62/// @param offset The row offset for pagination.
63/// @return The SQL SELECT query string.
64std::string BuildSelectQueryWithOffset(SqlQueryFormatter const& formatter,
65 SqlServerType serverType,
66 std::string_view schema,
67 std::string const& tableName,
68 std::vector<SqlSchema::Column> const& columns,
69 std::vector<std::string> const& primaryKeys,
70 size_t offset);
71
72/// Queries the inclusive [MIN(pk), MAX(pk)] bounds of @p table's @p pkColumn.
73/// @param stmt The statement to execute the scalar queries on.
74/// @param table The table to inspect.
75/// @param pkColumn The single numeric primary-key column.
76/// @return The bounds, or std::nullopt if the table is empty.
77[[nodiscard]] LIGHTWEIGHT_API std::optional<std::pair<int64_t, int64_t>> QueryPkBounds(SqlStatement& stmt,
78 SqlSchema::Table const& table,
79 std::string const& pkColumn);
80
81/// Deletes stale window sub-chunk entries [firstStale, end) of @p tableName's window
82/// @p windowIndex from the worker's chunk archive (and their checksums). Used after a per-window
83/// retry produced fewer sub-chunks than an earlier attempt (live data drift), so restore never
84/// reads stale rows: names still in the worker's current archive are deleted outright, names
85/// already sealed are tombstoned so the finalize merge skips them.
86/// @param archive The worker's chunk archive the window's sub-chunks were written to.
87/// @param ctx The backup context (checksums map).
88/// @param tableName The (unsanitized) table name.
89/// @param windowIndex The plan-time window index.
90/// @param firstStale First stale sub-chunk id (== sub-chunk count of the final attempt).
91/// @param end One past the last sub-chunk id any attempt flushed.
92LIGHTWEIGHT_API void DeleteStaleSubChunks(WorkerChunkArchive& archive,
93 BackupContext& ctx,
94 std::string const& tableName,
95 uint32_t windowIndex,
96 size_t firstStale,
97 size_t end);
98
99/// Processes a single chunk (a bounded row-range of a table) into compressed msgpack chunk
100/// entries in the worker's chunk archive.
101/// @param ctx The backup context.
102/// @param conn The database connection for this worker (borrowed from the pool).
103/// @param chunk The chunk (table + row window) to process.
104/// @param archive The worker's private chunk archive.
105void ProcessChunkBackup(BackupContext& ctx, SqlConnection& conn, detail::Chunk const& chunk, WorkerChunkArchive& archive);
106
107/// Backup worker: pops chunks from the queue and processes them on its borrowed connection,
108/// writing compressed chunk entries into its private archive (sealed before returning).
109/// @param chunkQueue The thread-safe queue of chunks to process.
110/// @param ctx The backup context.
111/// @param conn The database connection for this worker.
112/// @param archive The worker's private chunk archive.
113void ChunkWorker(ThreadSafeQueue<detail::Chunk>& chunkQueue,
114 BackupContext ctx,
115 SqlConnection& conn,
116 WorkerChunkArchive& archive);
117
118} // namespace Lightweight::SqlBackup::detail