Lightweight 0.1.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 virtual ~SqlMigrationExecutor() = default;
41
42 virtual void OnCreateTable(SqlCreateTablePlan const& createTable) = 0;
43 virtual void OnAlterTable(SqlAlterTablePlan const& alterTable) = 0;
44
45 virtual void OnDropTable(std::string_view tableName) = 0;
46};
47
48// Main API to use for managing SQL migrations
49class MigrationManager
50{
51 public:
52 using MigrationList = std::list<MigrationBase const*>;
53
54 LIGHTWEIGHT_API static MigrationManager& GetInstance()
55 {
56 static MigrationManager instance;
57 return instance;
58 }
59
60 LIGHTWEIGHT_API void AddMigration(MigrationBase const* migration);
61
62 [[nodiscard]] LIGHTWEIGHT_API MigrationList const& GetAllMigrations() const noexcept;
63
64 [[nodiscard]] LIGHTWEIGHT_API MigrationBase const* GetMigration(MigrationTimestamp timestamp) const;
65
66 LIGHTWEIGHT_API void RemoveAllMigrations();
67
68 [[nodiscard]] LIGHTWEIGHT_API std::list<MigrationBase const*> GetPending() const noexcept;
69
70 using ExecuteCallback = std::function<void(MigrationBase const& /*migration*/, size_t /*current*/, size_t /*total*/)>;
71
72 LIGHTWEIGHT_API void ApplySingleMigration(MigrationTimestamp timestamp);
73 LIGHTWEIGHT_API void ApplySingleMigration(MigrationBase const& migration);
74 LIGHTWEIGHT_API size_t ApplyPendingMigrations(ExecuteCallback const& feedbackCallback = {});
75
76 LIGHTWEIGHT_API void CreateMigrationHistory();
77 [[nodiscard]] LIGHTWEIGHT_API std::vector<MigrationTimestamp> GetAppliedMigrationIds() const;
78
79 [[nodiscard]] LIGHTWEIGHT_API DataMapper& GetDataMapper();
80
81 [[nodiscard]] LIGHTWEIGHT_API DataMapper& GetDataMapper() const
82 {
83 return const_cast<MigrationManager*>(this)->GetDataMapper();
84 }
85
86 LIGHTWEIGHT_API void CloseDataMapper();
87
88 LIGHTWEIGHT_API SqlTransaction Transaction();
89
90 private:
91 MigrationList _migrations;
92 mutable std::optional<DataMapper> _mapper;
93};
94
95// Represents a single unique SQL migration
96class MigrationBase
97{
98 public:
99 MigrationBase(MigrationTimestamp timestamp, std::string_view title):
100 _timestamp { timestamp },
101 _title { title }
102 {
103 MigrationManager::GetInstance().AddMigration(this);
104 }
105
106 virtual ~MigrationBase() = default;
107
108 virtual void Execute(SqlMigrationQueryBuilder& planer) const = 0;
109
110 [[nodiscard]] MigrationTimestamp GetTimestamp() const noexcept
111 {
112 return _timestamp;
113 }
114
115 [[nodiscard]] std::string_view GetTitle() const noexcept
116 {
117 return _title;
118 }
119
120 private:
121 MigrationTimestamp _timestamp;
122 std::string_view _title;
123};
124
125class Migration: public MigrationBase
126{
127 public:
128 Migration(MigrationTimestamp timestamp,
129 std::string_view title,
130 std::function<void(SqlMigrationQueryBuilder&)> const& plan):
131 MigrationBase(timestamp, title),
132 _plan { plan }
133 {
134 }
135
136 void Execute(SqlMigrationQueryBuilder& planer) const override
137 {
138 _plan(planer);
139 }
140
141 private:
142 std::function<void(SqlMigrationQueryBuilder&)> _plan;
143};
144
145} // namespace SqlMigration
146
147#define LIGHTWEIGHT_CONCATENATE(s1, s2) s1##s2
148
149#define LIGHTWEIGHT_MIGRATION_INSTANCE(timestamp) migration_##timestamp
150
151// Example use:
152//
153// LIGHTWEIGHT_SQL_MIGRATION(std::chrono::system_clock(...), "Create table 'MyTable'")
154// {
155// // ...
156// }
157#define LIGHTWEIGHT_SQL_MIGRATION(timestamp, description) \
158 struct Migration_##timestamp: public SqlMigration::MigrationBase \
159 { \
160 explicit Migration_##timestamp(): \
161 MigrationBase(SqlMigration::MigrationTimestamp { timestamp }, description) \
162 { \
163 } \
164 \
165 void Execute(SqlMigrationQueryBuilder& planer) const override; \
166 }; \
167 \
168 static Migration_##timestamp LIGHTWEIGHT_CONCATENATE(migration_, timestamp); \
169 \
170 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.