Lightweight 0.20261105.1
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 /// Whether the archive holds several schemas, so each table's chunks go below its schema's folder.
46 bool multiSchema;
47};
48
49/// Builds a SELECT query with ORDER BY for deterministic results.
50///
51/// This is critical for:
52/// 1. MS SQL Server which requires ORDER BY when using OFFSET
53/// 2. Deterministic results for resumption after transient errors
54///
55/// For MS SQL Server, DECIMAL columns are wrapped in CONVERT(VARCHAR, ...) to preserve
56/// full precision, as the ODBC driver loses precision when reading DECIMAL as SQL_C_CHAR.
57///
58/// @param formatter The SQL query formatter for the database.
59/// @param serverType The type of database server.
60/// @param schema The schema name.
61/// @param tableName The table name.
62/// @param columns The table columns.
63/// @param primaryKeys The primary key columns.
64/// @param offset The row offset for pagination.
65/// @return The SQL SELECT query string.
66std::string BuildSelectQueryWithOffset(SqlQueryFormatter const& formatter,
67 SqlServerType serverType,
68 std::string_view schema,
69 std::string const& tableName,
70 std::vector<SqlSchema::Column> const& columns,
71 std::vector<std::string> const& primaryKeys,
72 size_t offset);
73
74/// Queries the inclusive [MIN(pk), MAX(pk)] bounds of @p table's @p pkColumn.
75/// @param stmt The statement to execute the scalar queries on.
76/// @param table The table to inspect.
77/// @param pkColumn The single numeric primary-key column.
78/// @return The bounds, or std::nullopt if the table is empty.
79[[nodiscard]] LIGHTWEIGHT_API std::optional<std::pair<int64_t, int64_t>> QueryPkBounds(SqlStatement& stmt,
80 SqlSchema::Table const& table,
81 std::string const& pkColumn);
82
83/// Deletes stale window sub-chunk entries [firstStale, end) of a table's window
84/// @p windowIndex from the worker's chunk archive (and their checksums). Used after a per-window
85/// retry produced fewer sub-chunks than an earlier attempt (live data drift), so restore never
86/// reads stale rows: names still in the worker's current archive are deleted outright, names
87/// already sealed are tombstoned so the finalize merge skips them.
88/// @param archive The worker's chunk archive the window's sub-chunks were written to.
89/// @param ctx The backup context (checksums map).
90/// @param chunkDirectory The table's chunk folder below `data/` (see @ref ChunkDirectory).
91/// @param windowIndex The plan-time window index.
92/// @param firstStale First stale sub-chunk id (== sub-chunk count of the final attempt).
93/// @param end One past the last sub-chunk id any attempt flushed.
94LIGHTWEIGHT_API void DeleteStaleSubChunks(WorkerChunkArchive& archive,
95 BackupContext& ctx,
96 std::string_view chunkDirectory,
97 uint32_t windowIndex,
98 size_t firstStale,
99 size_t end);
100
101/// Processes a single chunk (a bounded row-range of a table) into compressed msgpack chunk
102/// entries in the worker's chunk archive.
103/// @param ctx The backup context.
104/// @param conn The database connection for this worker (borrowed from the pool).
105/// @param chunk The chunk (table + row window) to process.
106/// @param archive The worker's private chunk archive.
107void ProcessChunkBackup(BackupContext& ctx, SqlConnection& conn, detail::Chunk const& chunk, WorkerChunkArchive& archive);
108
109/// Backup worker: pops chunks from the queue and processes them on its borrowed connection,
110/// writing compressed chunk entries into its private archive (sealed before returning).
111/// @param chunkQueue The thread-safe queue of chunks to process.
112/// @param ctx The backup context.
113/// @param conn The database connection for this worker.
114/// @param archive The worker's private chunk archive.
115void ChunkWorker(ThreadSafeQueue<detail::Chunk>& chunkQueue,
116 BackupContext ctx,
117 SqlConnection& conn,
118 WorkerChunkArchive& archive);
119
120} // namespace Lightweight::SqlBackup::detail