Lightweight 0.20250627.0
Loading...
Searching...
No Matches
SqlMigration.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "Api.hpp"
6#include "DataMapper/DataMapper.hpp"
7#include "SqlQuery.hpp"
8#include "SqlTransaction.hpp"
9
10#include <functional>
11#include <list>
12#include <optional>
13
14class SqlConnection;
15
16namespace SqlMigration
17{
18
19class MigrationBase;
20
21struct MigrationTimestamp
22{
23 uint64_t value {};
24
25 constexpr bool operator==(MigrationTimestamp const& other) const noexcept
26 {
27 return value == other.value;
28 }
29
30 constexpr bool operator!=(MigrationTimestamp const& other) const noexcept
31 {
32 return !(*this == other);
33 }
34};
35
36// Interface to be implemented by the user to execute SQL migrations
37class SqlMigrationExecutor
38{
39 public:
40 SqlMigrationExecutor(SqlMigrationExecutor const&) = default;
41 SqlMigrationExecutor(SqlMigrationExecutor&&) = delete;
42 SqlMigrationExecutor& operator=(SqlMigrationExecutor const&) = default;
43 SqlMigrationExecutor& operator=(SqlMigrationExecutor&&) = delete;
44 virtual ~SqlMigrationExecutor() = default;
45
46 virtual void OnCreateTable(SqlCreateTablePlan const& createTable) = 0;
47 virtual void OnAlterTable(SqlAlterTablePlan const& alterTable) = 0;
48
49 virtual void OnDropTable(std::string_view tableName) = 0;
50};
51
52// Main API to use for managing SQL migrations
53class MigrationManager
54{
55 public:
56 using MigrationList = std::list<MigrationBase const*>;
57
58 LIGHTWEIGHT_API static MigrationManager& GetInstance()
59 {
60 static MigrationManager instance;
61 return instance;
62 }
63
64 LIGHTWEIGHT_API void AddMigration(MigrationBase const* migration);
65
66 [[nodiscard]] LIGHTWEIGHT_API MigrationList const& GetAllMigrations() const noexcept;
67
68 [[nodiscard]] LIGHTWEIGHT_API MigrationBase const* GetMigration(MigrationTimestamp timestamp) const;
69
70 LIGHTWEIGHT_API void RemoveAllMigrations();
71
72 [[nodiscard]] LIGHTWEIGHT_API std::list<MigrationBase const*> GetPending() const noexcept;
73
74 using ExecuteCallback = std::function<void(MigrationBase const& /*migration*/, size_t /*current*/, size_t /*total*/)>;
75
76 LIGHTWEIGHT_API void ApplySingleMigration(MigrationTimestamp timestamp);
77 LIGHTWEIGHT_API void ApplySingleMigration(MigrationBase const& migration);
78 LIGHTWEIGHT_API size_t ApplyPendingMigrations(ExecuteCallback const& feedbackCallback = {});
79
80 LIGHTWEIGHT_API void CreateMigrationHistory();
81 [[nodiscard]] LIGHTWEIGHT_API std::vector<MigrationTimestamp> GetAppliedMigrationIds() const;
82
83 [[nodiscard]] LIGHTWEIGHT_API DataMapper& GetDataMapper();
84
85 [[nodiscard]] LIGHTWEIGHT_API DataMapper& GetDataMapper() const
86 {
87 return const_cast<MigrationManager*>(this)->GetDataMapper();
88 }
89
90 LIGHTWEIGHT_API void CloseDataMapper();
91
92 LIGHTWEIGHT_API SqlTransaction Transaction();
93
94 private:
95 MigrationList _migrations;
96 mutable std::optional<DataMapper> _mapper;
97};
98
99// Represents a single unique SQL migration
100class MigrationBase
101{
102 public:
103 MigrationBase(MigrationBase const&) = default;
104 MigrationBase(MigrationBase&&) = delete;
105 MigrationBase& operator=(MigrationBase const&) = default;
106 MigrationBase& operator=(MigrationBase&&) = delete;
107 MigrationBase(MigrationTimestamp timestamp, std::string_view title):
108 _timestamp { timestamp },
109 _title { title }
110 {
111 MigrationManager::GetInstance().AddMigration(this);
112 }
113
114 virtual ~MigrationBase() = default;
115
116 virtual void Execute(SqlMigrationQueryBuilder& planer) const = 0;
117
118 [[nodiscard]] MigrationTimestamp GetTimestamp() const noexcept
119 {
120 return _timestamp;
121 }
122
123 [[nodiscard]] std::string_view GetTitle() const noexcept
124 {
125 return _title;
126 }
127
128 private:
129 MigrationTimestamp _timestamp;
130 std::string_view _title;
131};
132
133class Migration: public MigrationBase
134{
135 public:
136 Migration(MigrationTimestamp timestamp,
137 std::string_view title,
138 std::function<void(SqlMigrationQueryBuilder&)> const& plan):
139 MigrationBase(timestamp, title),
140 _plan { plan }
141 {
142 }
143
144 void Execute(SqlMigrationQueryBuilder& planer) const override
145 {
146 _plan(planer);
147 }
148
149 private:
150 std::function<void(SqlMigrationQueryBuilder&)> _plan;
151};
152
153} // namespace SqlMigration
154
155#define LIGHTWEIGHT_CONCATENATE(s1, s2) s1##s2
156
157#define LIGHTWEIGHT_MIGRATION_INSTANCE(timestamp) migration_##timestamp
158
159// Example use:
160//
161// LIGHTWEIGHT_SQL_MIGRATION(std::chrono::system_clock(...), "Create table 'MyTable'")
162// {
163// // ...
164// }
165#define LIGHTWEIGHT_SQL_MIGRATION(timestamp, description) \
166 struct Migration_##timestamp: public SqlMigration::MigrationBase \
167 { \
168 explicit Migration_##timestamp(): \
169 MigrationBase(SqlMigration::MigrationTimestamp { timestamp }, description) \
170 { \
171 } \
172 \
173 void Execute(SqlMigrationQueryBuilder& planer) const override; \
174 }; \
175 \
176 static Migration_##timestamp LIGHTWEIGHT_CONCATENATE(migration_, timestamp); \
177 \
178 void Migration_##timestamp::Execute(SqlMigrationQueryBuilder& plan) const
Main API for mapping records to and from the database using high level C++ syntax.
Represents a connection to a SQL database.
Query builder for building SQL migration queries.
Definition Migrate.hpp:182
Represents a SQL ALTER TABLE plan on a given table.