Lightweight 0.20260303.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>
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 /// The name of the column to add.
336 std::string columnName;
337 /// The type of the column to add.
338 SqlColumnTypeDefinition columnType;
339 /// Whether the column is nullable.
340 SqlNullable nullable = SqlNullable::Null;
341 };
342
343 /// Drops a column only if it exists.
345 {
346 /// The name of the column to drop.
347 std::string columnName;
348 };
349
350 /// Drops an index only if it exists.
352 {
353 /// The name of the column whose index to drop.
354 std::string columnName;
355 };
356
357} // namespace SqlAlterTableCommands
358
359/// @brief Represents a single SQL ALTER TABLE command.
360///
361/// @ingroup QueryBuilder
362using SqlAlterTableCommand = std::variant<SqlAlterTableCommands::RenameTable,
363 SqlAlterTableCommands::AddColumn,
365 SqlAlterTableCommands::AlterColumn,
366 SqlAlterTableCommands::AddIndex,
367 SqlAlterTableCommands::RenameColumn,
368 SqlAlterTableCommands::DropColumn,
370 SqlAlterTableCommands::DropIndex,
372 SqlAlterTableCommands::AddForeignKey,
373 SqlAlterTableCommands::AddCompositeForeignKey,
374 SqlAlterTableCommands::DropForeignKey>;
375
376/// @brief Represents a SQL ALTER TABLE plan on a given table.
377///
378/// @ingroup QueryBuilder
380{
381 /// The schema name of the table to alter.
382 std::string_view schemaName;
383
384 /// The name of the table to alter.
385 std::string_view tableName;
386
387 /// The list of commands to execute on the table.
388 std::vector<SqlAlterTableCommand> commands;
389};
390
391/// @brief Represents a SQL DROP TABLE plan.
392///
393/// @ingroup QueryBuilder
395{
396 /// The schema name of the table to drop.
397 std::string_view schemaName;
398
399 /// The name of the table to drop.
400 std::string_view tableName;
401
402 /// If true, generates DROP TABLE IF EXISTS instead of DROP TABLE.
403 bool ifExists { false };
404
405 /// If true, drops all foreign key constraints referencing this table first.
406 /// On PostgreSQL, uses CASCADE. On MS SQL, drops FK constraints explicitly.
407 bool cascade { false };
408};
409
410/// @brief Represents a raw SQL plan.
411///
412/// @ingroup QueryBuilder
414{
415 /// The raw SQL to execute.
416 std::string_view sql;
417};
418
419/// @brief Represents a SQL INSERT data plan for migrations.
420///
421/// This structure represents an INSERT statement for a migration plan.
422///
423/// @ingroup QueryBuilder
425{
426 /// The schema name of the table to insert into.
427 std::string schemaName;
428
429 /// The name of the table to insert into.
430 std::string tableName;
431
432 /// The columns and their values to insert.
433 std::vector<std::pair<std::string, SqlVariant>> columns;
434};
435
436/// @brief Represents a SQL UPDATE data plan for migrations.
437///
438/// This structure represents an UPDATE statement for a migration plan.
439///
440/// @ingroup QueryBuilder
442{
443 /// The schema name of the table to update.
444 std::string schemaName;
445
446 /// The name of the table to update.
447 std::string tableName;
448
449 /// The columns and their values to set.
450 std::vector<std::pair<std::string, SqlVariant>> setColumns;
451
452 /// The column name for the WHERE clause.
453 std::string whereColumn;
454
455 /// The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
456 std::string whereOp;
457
458 /// The value for the WHERE clause.
460};
461
462/// @brief Represents a SQL DELETE data plan for migrations.
463///
464/// This structure represents a DELETE statement for a migration plan.
465///
466/// @ingroup QueryBuilder
468{
469 /// The schema name of the table to delete from.
470 std::string schemaName;
471
472 /// The name of the table to delete from.
473 std::string tableName;
474
475 /// The column name for the WHERE clause.
476 std::string whereColumn;
477
478 /// The comparison operator for the WHERE clause (e.g., "=", "<>", etc.).
479 std::string whereOp;
480
481 /// The value for the WHERE clause.
483};
484
485/// @brief Represents a SQL CREATE INDEX plan for migrations.
486///
487/// This structure represents a CREATE INDEX statement for a migration plan.
488///
489/// @ingroup QueryBuilder
491{
492 /// The schema name of the table to create the index on.
493 std::string schemaName;
494
495 /// The name of the index to create.
496 std::string indexName;
497
498 /// The name of the table to create the index on.
499 std::string tableName;
500
501 /// The columns to include in the index.
502 std::vector<std::string> columns;
503
504 /// If true, creates a UNIQUE index.
505 bool unique { false };
506
507 /// If true, generates CREATE INDEX IF NOT EXISTS.
508 bool ifNotExists { false };
509};
510
511// clang-format off
512
513/// @brief Represents a single SQL migration plan element.
514///
515/// This variant represents a single SQL migration plan element.
516///
517/// @ingroup QueryBuilder
518using SqlMigrationPlanElement = std::variant<
519 SqlCreateTablePlan,
527>;
528
529// clang-format on
530
531/// Formats the given SQL migration plan element as a list of SQL statements.
532///
533/// @param formatter The SQL query formatter to use.
534/// @param element The SQL migration plan element to format.
535///
536/// @return A list of SQL statements.
537///
538/// @ingroup QueryBuilder
539[[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql(SqlQueryFormatter const& formatter,
540 SqlMigrationPlanElement const& element);
541
542/// @brief Represents a SQL migration plan.
543///
544/// This structure represents a SQL migration plan that can be executed on a database.
545///
546/// @ingroup QueryBuilder
547struct [[nodiscard]] SqlMigrationPlan
548{
549 /// The SQL query formatter to use.
551 /// The migration plan steps.
552 std::vector<SqlMigrationPlanElement> steps {};
553
554 /// Converts the migration plan to a list of SQL statements.
555 [[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql() const;
556};
557
558/// @brief Formats the given SQL migration plan as a list of SQL statements.
559///
560/// @param formatter The SQL query formatter to use.
561/// @param plans The SQL migration plans to format.
562///
563/// @return A list of SQL statements.
564///
565/// @ingroup QueryBuilder
566[[nodiscard]] LIGHTWEIGHT_API std::vector<std::string> ToSql(SqlQueryFormatter const& formatter,
567 std::vector<SqlMigrationPlan> const& plans);
568
569} // namespace Lightweight
API to format SQL queries for different SQL dialects.
std::variant< SqlAlterTableCommands::RenameTable, SqlAlterTableCommands::AddColumn, SqlAlterTableCommands::AddColumnIfNotExists, SqlAlterTableCommands::AlterColumn, SqlAlterTableCommands::AddIndex, SqlAlterTableCommands::RenameColumn, SqlAlterTableCommands::DropColumn, SqlAlterTableCommands::DropColumnIfExists, SqlAlterTableCommands::DropIndex, SqlAlterTableCommands::DropIndexIfExists, SqlAlterTableCommands::AddForeignKey, SqlAlterTableCommands::AddCompositeForeignKey, SqlAlterTableCommands::DropForeignKey > SqlAlterTableCommand
Represents a single SQL ALTER TABLE command.
LIGHTWEIGHT_API std::vector< std::string > ToSql(SqlQueryFormatter const &formatter, SqlMigrationPlanElement const &element)
SqlPrimaryKeyType
Represents a primary key type.
std::variant< SqlCreateTablePlan, SqlAlterTablePlan, SqlDropTablePlan, SqlCreateIndexPlan, SqlRawSqlPlan, SqlInsertDataPlan, SqlUpdateDataPlan, SqlDeleteDataPlan > SqlMigrationPlanElement
Represents a single SQL migration plan element.
constexpr auto SqlColumnTypeDefinitionOf
Represents a SQL column type definition of T.
Adds a column only if it does not already exist.
SqlNullable nullable
Whether the column is nullable.
SqlColumnTypeDefinition columnType
The type of the column to add.
std::string columnName
The name of the column to add.
std::string columnName
The name of the column to drop.
std::string columnName
The name of the column whose index to drop.
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.
SqlQueryFormatter const & formatter
The SQL query formatter to use.
LIGHTWEIGHT_API std::vector< std::string > ToSql() const
Converts the migration plan to a list of SQL statements.
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.