Lightweight 0.20251202.0
Loading...
Searching...
No Matches
MigrationPlan.hpp
1// SPDX-License-Identifier: Apache-2.0
2
3#pragma once
4
5#include "../Api.hpp"
6#include "../SqlColumnTypeDefinitions.hpp"
7#include "../SqlDataBinder.hpp"
8#include "../Utils.hpp"
9
10#include <reflection-cpp/reflection.hpp>
11
12#include <string>
13#include <string_view>
14#include <variant>
15#include <vector>
16
17namespace Lightweight
18{
19
20class SqlQueryFormatter;
21
22namespace detail
23{
24
25 template <typename T>
26 struct SqlColumnTypeDefinitionOf
27 {
28 static_assert(AlwaysFalse<T>, "Unsupported type for SQL column definition.");
29 };
30
31 template <>
32 struct SqlColumnTypeDefinitionOf<std::string>
33 {
34 static constexpr auto value = SqlColumnTypeDefinitions::Text {};
35 };
36
37 template <>
38 struct SqlColumnTypeDefinitionOf<bool>
39 {
40 static constexpr auto value = SqlColumnTypeDefinitions::Bool {};
41 };
42
43 template <>
44 struct SqlColumnTypeDefinitionOf<char>
45 {
46 static constexpr auto value = SqlColumnTypeDefinitions::Char { 1 };
47 };
48
49 template <>
50 struct SqlColumnTypeDefinitionOf<SqlDate>
51 {
52 static constexpr auto value = SqlColumnTypeDefinitions::Date {};
53 };
54
55 template <>
56 struct SqlColumnTypeDefinitionOf<SqlDateTime>
57 {
58 static constexpr auto value = SqlColumnTypeDefinitions::DateTime {};
59 };
60
61 template <>
62 struct SqlColumnTypeDefinitionOf<SqlTime>
63 {
64 static constexpr auto value = SqlColumnTypeDefinitions::Time {};
65 };
66
67 template <size_t Precision, size_t Scale>
68 struct SqlColumnTypeDefinitionOf<SqlNumeric<Precision, Scale>>
69 {
70 static constexpr auto value = SqlColumnTypeDefinitions::Decimal { .precision = Precision, .scale = Scale };
71 };
72
73 template <>
74 struct SqlColumnTypeDefinitionOf<SqlGuid>
75 {
76 static constexpr auto value = SqlColumnTypeDefinitions::Guid {};
77 };
78
79 template <typename T>
80 requires(detail::OneOf<T, int16_t, uint16_t>)
81 struct SqlColumnTypeDefinitionOf<T>
82 {
83 static constexpr auto value = SqlColumnTypeDefinitions::Smallint {};
84 };
85
86 template <typename T>
87 requires(detail::OneOf<T, int32_t, uint32_t>)
88 struct SqlColumnTypeDefinitionOf<T>
89 {
90 static constexpr auto value = SqlColumnTypeDefinitions::Integer {};
91 };
92
93 template <typename T>
94 requires(detail::OneOf<T, int64_t, uint64_t>)
95 struct SqlColumnTypeDefinitionOf<T>
96 {
97 static constexpr auto value = SqlColumnTypeDefinitions::Bigint {};
98 };
99
100 template <typename T>
101 requires(detail::OneOf<T, float, double>)
102 struct SqlColumnTypeDefinitionOf<T>
103 {
104 static constexpr auto value = SqlColumnTypeDefinitions::Real {};
105 };
106
107 template <size_t N, typename CharT>
108 requires(detail::OneOf<CharT, char>)
109 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::VARIABLE_SIZE>>
110 {
111 static constexpr auto value = SqlColumnTypeDefinitions::Varchar { N };
112 };
113
114 template <size_t N, typename CharT>
115 requires(detail::OneOf<CharT, char16_t, char32_t, wchar_t>)
116 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::VARIABLE_SIZE>>
117 {
118 static constexpr auto value = SqlColumnTypeDefinitions::NVarchar { N };
119 };
120
121 template <size_t N, typename CharT>
122 requires(detail::OneOf<CharT, char>)
123 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::FIXED_SIZE>>
124 {
125 static constexpr auto value = SqlColumnTypeDefinitions::Char { N };
126 };
127
128 template <size_t N, typename CharT>
129 requires(detail::OneOf<CharT, char16_t, char32_t, wchar_t>)
130 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::FIXED_SIZE>>
131 {
132 static constexpr auto value = SqlColumnTypeDefinitions::NChar { N };
133 };
134
135 template <size_t N, typename CharT>
136 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::FIXED_SIZE_RIGHT_TRIMMED>>
137 {
138 static constexpr auto value = SqlColumnTypeDefinitions::Char { N };
139 };
140
141 template <size_t N, typename CharT>
142 requires(detail::OneOf<CharT, char16_t, char32_t, wchar_t>)
143 struct SqlColumnTypeDefinitionOf<SqlFixedString<N, CharT, SqlFixedStringMode::FIXED_SIZE_RIGHT_TRIMMED>>
144 {
145 static constexpr auto value = SqlColumnTypeDefinitions::NChar { N };
146 };
147
148 template <size_t N, typename CharT>
149 requires(detail::OneOf<CharT, char>)
150 struct SqlColumnTypeDefinitionOf<SqlDynamicString<N, CharT>>
151 {
152 static constexpr auto value = SqlColumnTypeDefinitions::Varchar { N };
153 };
154
155 template <size_t N, typename CharT>
156 requires(detail::OneOf<CharT, char8_t, char16_t, char32_t, wchar_t>)
157 struct SqlColumnTypeDefinitionOf<SqlDynamicString<N, CharT>>
158 {
159 static constexpr auto value = SqlColumnTypeDefinitions::NVarchar { N };
160 };
161
162 template <typename T>
163 struct SqlColumnTypeDefinitionOf<std::optional<T>>
164 {
165 static constexpr auto value = SqlColumnTypeDefinitionOf<T>::value;
166 };
167
168 template <>
169 struct SqlColumnTypeDefinitionOf<SqlText>
170 {
171 static constexpr auto value = SqlColumnTypeDefinitions::Text {};
172 };
173
174 template <size_t N>
175 struct SqlColumnTypeDefinitionOf<SqlDynamicBinary<N>>
176 {
177 static constexpr auto value = SqlColumnTypeDefinitions::VarBinary { N };
178 };
179
180} // namespace detail
181
182/// @brief Represents a SQL column type definition of T.
183///
184/// @ingroup QueryBuilder
185template <typename T>
186constexpr auto SqlColumnTypeDefinitionOf = detail::SqlColumnTypeDefinitionOf<T>::value;
187
188/// @brief Represents a primary key type.
189///
190/// This enumeration represents the primary key type of a column.
191///
192/// @ingroup QueryBuilder
193enum class SqlPrimaryKeyType : uint8_t
194{
195 NONE,
196 MANUAL,
197 AUTO_INCREMENT,
198 GUID,
199};
200
201/// @brief Represents a foreign key reference definition.
202///
203/// @ingroup QueryBuilder
205{
206 /// The table name that the foreign key references.
207 std::string tableName;
208
209 /// The column name that the foreign key references.
210 std::string columnName;
211};
212
213/// @brief Represents a SQL column declaration.
214///
215/// @ingroup QueryBuilder
217{
218 /// The name of the column.
219 std::string name;
220
221 /// The type of the column.
222 SqlColumnTypeDefinition type;
223
224 /// The primary key type of the column.
225 SqlPrimaryKeyType primaryKey { SqlPrimaryKeyType::NONE };
226
227 /// The foreign key reference definition of the column.
228 std::optional<SqlForeignKeyReferenceDefinition> foreignKey {};
229
230 /// Indicates if the column is required (non-nullable).
231 bool required { false };
232
233 /// Indicates if the column is unique.
234 bool unique { false };
235
236 /// The default value of the column.
237 std::string defaultValue {};
238
239 /// Indicates if the column is indexed.
240 bool index { false };
241
242 /// The 1-based index in the primary key (0 if not part of a specific order).
243 uint16_t primaryKeyIndex { 0 };
244};
245
246/// @brief Represents a composite foreign key constraint.
247///
248/// @ingroup QueryBuilder
250{
251 /// The columns in the current table.
252 std::vector<std::string> columns;
253
254 /// The referenced table name.
256
257 /// The referenced columns in the referenced table.
258 std::vector<std::string> referencedColumns;
259};
260
261struct SqlCreateTablePlan
262{
263 std::string schemaName;
264 std::string tableName;
265 std::vector<SqlColumnDeclaration> columns;
266 std::vector<SqlCompositeForeignKeyConstraint> foreignKeys;
267 bool ifNotExists { false }; ///< If true, generates CREATE TABLE IF NOT EXISTS.
268};
269
270namespace SqlAlterTableCommands
271{
272
273 struct RenameTable
274 {
275 std::string_view newTableName;
276 };
277
278 struct AddColumn
279 {
280 std::string columnName;
281 SqlColumnTypeDefinition columnType;
282 SqlNullable nullable = SqlNullable::Null;
283 };
284
285 struct AlterColumn
286 {
287 std::string columnName;
288 SqlColumnTypeDefinition columnType;
289 SqlNullable nullable = SqlNullable::Null;
290 };
291
292 struct AddIndex
293 {
294 std::string_view columnName;
295 bool unique = false;
296 };
297
298 struct RenameColumn
299 {
300 std::string_view oldColumnName;
301 std::string_view newColumnName;
302 };
303
304 struct DropColumn
305 {
306 std::string_view columnName;
307 };
308
309 struct DropIndex
310 {
311 std::string_view columnName;
312 };
313
314 struct AddForeignKey
315 {
316 std::string columnName;
317 SqlForeignKeyReferenceDefinition referencedColumn;
318 };
319
320 struct AddCompositeForeignKey
321 {
322 std::vector<std::string> columns;
323 std::string referencedTableName;
324 std::vector<std::string> referencedColumns;
325 };
326
327 struct DropForeignKey
328 {
329 std::string columnName;
330 };
331
332 /// Adds a column only if it does not already exist.
334 {
335 std::string columnName;
336 SqlColumnTypeDefinition columnType;
337 SqlNullable nullable = SqlNullable::Null;
338 };
339
340 /// Drops a column only if it exists.
342 {
343 std::string columnName;
344 };
345
346 /// Drops an index only if it exists.
348 {
349 std::string columnName;
350 };
351
352} // namespace SqlAlterTableCommands
353
354/// @brief Represents a single SQL ALTER TABLE command.
355///
356/// @ingroup QueryBuilder
357using SqlAlterTableCommand = std::variant<SqlAlterTableCommands::RenameTable,
358 SqlAlterTableCommands::AddColumn,
360 SqlAlterTableCommands::AlterColumn,
361 SqlAlterTableCommands::AddIndex,
362 SqlAlterTableCommands::RenameColumn,
363 SqlAlterTableCommands::DropColumn,
365 SqlAlterTableCommands::DropIndex,
367 SqlAlterTableCommands::AddForeignKey,
368 SqlAlterTableCommands::AddCompositeForeignKey,
369 SqlAlterTableCommands::DropForeignKey>;
370
371/// @brief Represents a SQL ALTER TABLE plan on a given table.
372///
373/// @ingroup QueryBuilder
375{
376 /// The schema name of the table to alter.
377 std::string_view schemaName;
378
379 /// The name of the table to alter.
380 std::string_view tableName;
381
382 /// The list of commands to execute on the table.
383 std::vector<SqlAlterTableCommand> commands;
384};
385
386/// @brief Represents a SQL DROP TABLE plan.
387///
388/// @ingroup QueryBuilder
390{
391 /// The schema name of the table to drop.
392 std::string_view schemaName;
393
394 /// The name of the table to drop.
395 std::string_view tableName;
396
397 /// If true, generates DROP TABLE IF EXISTS instead of DROP TABLE.
398 bool ifExists { false };
399
400 /// If true, drops all foreign key constraints referencing this table first.
401 /// On PostgreSQL, uses CASCADE. On MS SQL, drops FK constraints explicitly.
402 bool cascade { false };
403};
404
405/// @brief Represents a raw SQL plan.
406///
407/// @ingroup QueryBuilder
409{
410 /// The raw SQL to execute.
411 std::string_view sql;
412};
413
414/// @brief Represents a SQL INSERT data plan for migrations.
415///
416/// This structure represents an INSERT statement for a migration plan.
417///
418/// @ingroup QueryBuilder
420{
421 /// The schema name of the table to insert into.
422 std::string schemaName;
423
424 /// The name of the table to insert into.
425 std::string tableName;
426
427 /// The columns and their values to insert.
428 std::vector<std::pair<std::string, SqlVariant>> columns;
429};
430
431/// @brief Represents a SQL UPDATE data plan for migrations.
432///
433/// This structure represents an UPDATE statement for a migration plan.
434///
435/// @ingroup QueryBuilder
437{
438 /// The schema name of the table to update.
439 std::string schemaName;
440
441 /// The name of the table to update.
442 std::string tableName;
443
444 /// The columns and their values to set.
445 std::vector<std::pair<std::string, SqlVariant>> setColumns;
446
447 /// The column name for the WHERE clause.
448 std::string whereColumn;
449
450 /// The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
451 std::string whereOp;
452
453 /// The value for the WHERE clause.
455};
456
457/// @brief Represents a SQL DELETE data plan for migrations.
458///
459/// This structure represents a DELETE statement for a migration plan.
460///
461/// @ingroup QueryBuilder
463{
464 /// The schema name of the table to delete from.
465 std::string schemaName;
466
467 /// The name of the table to delete from.
468 std::string tableName;
469
470 /// The column name for the WHERE clause.
471 std::string whereColumn;
472
473 /// The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
474 std::string whereOp;
475
476 /// The value for the WHERE clause.
478};
479
480/// @brief Represents a SQL CREATE INDEX plan for migrations.
481///
482/// This structure represents a CREATE INDEX statement for a migration plan.
483///
484/// @ingroup QueryBuilder
486{
487 /// The schema name of the table to create the index on.
488 std::string schemaName;
489
490 /// The name of the index to create.
491 std::string indexName;
492
493 /// The name of the table to create the index on.
494 std::string tableName;
495
496 /// The columns to include in the index.
497 std::vector<std::string> columns;
498
499 /// If true, creates a UNIQUE index.
500 bool unique { false };
501
502 /// If true, generates CREATE INDEX IF NOT EXISTS.
503 bool ifNotExists { false };
504};
505
506// clang-format off
507
508/// @brief Represents a single SQL migration plan element.
509///
510/// This variant represents a single SQL migration plan element.
511///
512/// @ingroup QueryBuilder
513using SqlMigrationPlanElement = std::variant<
514 SqlCreateTablePlan,
515 SqlAlterTablePlan,
516 SqlDropTablePlan,
517 SqlCreateIndexPlan,
518 SqlRawSqlPlan,
519 SqlInsertDataPlan,
520 SqlUpdateDataPlan,
521 SqlDeleteDataPlan
522>;
523
524// clang-format on
525
526/// Formats the given SQL migration plan element as a list of SQL statements.
527///
528/// @param formatter The SQL query formatter to use.
529/// @param element The SQL migration plan element to format.
530///
531/// @return A list of SQL statements.
532///
533/// @ingroup QueryBuilder
534[[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql(SqlQueryFormatter const& formatter,
535 SqlMigrationPlanElement const& element);
536
537/// @brief Represents a SQL migration plan.
538///
539/// This structure represents a SQL migration plan that can be executed on a database.
540///
541/// @ingroup QueryBuilder
542struct [[nodiscard]] SqlMigrationPlan
543{
544 SqlQueryFormatter const& formatter;
545 std::vector<SqlMigrationPlanElement> steps {};
546
547 [[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql() const;
548};
549
550/// @brief Formats the given SQL migration plan as a list of SQL statements.
551///
552/// @param formatter The SQL query formatter to use.
553/// @param plans The SQL migration plans to format.
554///
555/// @return A list of SQL statements.
556///
557/// @ingroup QueryBuilder
558[[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql(SqlQueryFormatter const& formatter,
559 std::vector<SqlMigrationPlan> const& plans);
560
561} // namespace Lightweight
API to format SQL queries for different SQL dialects.
Adds a column only if it does not already exist.
Represents a SQL ALTER TABLE plan on a given table.
std::string_view schemaName
The schema name of the table to alter.
std::string_view tableName
The name of the table to alter.
std::vector< SqlAlterTableCommand > commands
The list of commands to execute on the table.
Represents a SQL column declaration.
bool required
Indicates if the column is required (non-nullable).
bool index
Indicates if the column is indexed.
SqlColumnTypeDefinition type
The type of the column.
std::string name
The name of the column.
std::optional< SqlForeignKeyReferenceDefinition > foreignKey
The foreign key reference definition of the column.
SqlPrimaryKeyType primaryKey
The primary key type of the column.
std::string defaultValue
The default value of the column.
bool unique
Indicates if the column is unique.
uint16_t primaryKeyIndex
The 1-based index in the primary key (0 if not part of a specific order).
Represents a composite foreign key constraint.
std::vector< std::string > columns
The columns in the current table.
std::string referencedTableName
The referenced table name.
std::vector< std::string > referencedColumns
The referenced columns in the referenced table.
Represents a SQL CREATE INDEX plan for migrations.
std::vector< std::string > columns
The columns to include in the index.
std::string schemaName
The schema name of the table to create the index on.
bool ifNotExists
If true, generates CREATE INDEX IF NOT EXISTS.
std::string indexName
The name of the index to create.
std::string tableName
The name of the table to create the index on.
bool unique
If true, creates a UNIQUE index.
Represents a SQL DELETE data plan for migrations.
std::string whereOp
The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
std::string tableName
The name of the table to delete from.
std::string whereColumn
The column name for the WHERE clause.
std::string schemaName
The schema name of the table to delete from.
SqlVariant whereValue
The value for the WHERE clause.
Represents a SQL DROP TABLE plan.
std::string_view schemaName
The schema name of the table to drop.
std::string_view tableName
The name of the table to drop.
bool ifExists
If true, generates DROP TABLE IF EXISTS instead of DROP TABLE.
Represents a foreign key reference definition.
std::string tableName
The table name that the foreign key references.
std::string columnName
The column name that the foreign key references.
Represents a SQL INSERT data plan for migrations.
std::vector< std::pair< std::string, SqlVariant > > columns
The columns and their values to insert.
std::string schemaName
The schema name of the table to insert into.
std::string tableName
The name of the table to insert into.
Represents a SQL migration plan.
Represents a raw SQL plan.
std::string_view sql
The raw SQL to execute.
Represents a SQL UPDATE data plan for migrations.
std::string schemaName
The schema name of the table to update.
SqlVariant whereValue
The value for the WHERE clause.
std::vector< std::pair< std::string, SqlVariant > > setColumns
The columns and their values to set.
std::string tableName
The name of the table to update.
std::string whereOp
The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
std::string whereColumn
The column name for the WHERE clause.
Represents a value that can be any of the supported SQL data types.