3#include "../schema/column.hpp"
4#include "../schema/core.hpp"
5#include "../schema/fixed_string.hpp"
6#include "../schema/table.hpp"
14#include <boost/pfr.hpp>
38 const std::string&
context =
"") {
79 return std::vector<std::string>{};
82 return std::vector<std::string>{};
87template <schema::TableConcept Table>
98 }
catch (
const std::exception& e) {
99 return std::unexpected(
101 "Failed to generate CREATE TABLE SQL: " + std::string(e.what()),
102 std::string(Table::table_name)));
109 }
catch (
const std::exception& e) {
110 return std::unexpected(
112 "Failed to generate DROP TABLE SQL: " + std::string(e.what()),
113 std::string(Table::table_name)));
121template <schema::TableConcept Table>
132 }
catch (
const std::exception& e) {
133 return std::unexpected(
135 "Failed to generate DROP TABLE SQL: " + std::string(e.what()),
136 std::string(Table::table_name)));
143 }
catch (
const std::exception& e) {
144 return std::unexpected(
146 "Failed to generate CREATE TABLE SQL: " + std::string(e.what()),
147 std::string(Table::table_name)));
155template <
typename Column>
158 std::string table_name_;
163 : table_name_(
std::move(table_name)), column_(
column) {}
167 return "ALTER TABLE " + table_name_ +
" ADD COLUMN " + column_.sql_definition() +
";";
168 }
catch (
const std::exception& e) {
169 return std::unexpected(
171 "Failed to generate ADD COLUMN SQL: " + std::string(e.what()),
172 table_name_ +
"." + std::string(Column::name)));
178 return "ALTER TABLE " + table_name_ +
" DROP COLUMN " + std::string(Column::name) +
";";
179 }
catch (
const std::exception& e) {
180 return std::unexpected(
182 "Failed to generate DROP COLUMN SQL: " + std::string(e.what()),
183 table_name_ +
"." + std::string(Column::name)));
191template <
typename Column>
194 std::string table_name_;
199 : table_name_(
std::move(table_name)), column_(
column) {}
203 return "ALTER TABLE " + table_name_ +
" DROP COLUMN " + std::string(Column::name) +
";";
204 }
catch (
const std::exception& e) {
205 return std::unexpected(
207 "Failed to generate DROP COLUMN SQL: " + std::string(e.what()),
208 table_name_ +
"." + std::string(Column::name)));
214 return "ALTER TABLE " + table_name_ +
" ADD COLUMN " + column_.sql_definition() +
";";
215 }
catch (
const std::exception& e) {
216 return std::unexpected(
218 "Failed to generate ADD COLUMN SQL: " + std::string(e.what()),
219 table_name_ +
"." + std::string(Column::name)));
229 std::string table_name_;
230 std::string old_name_;
231 std::string new_name_;
235 : table_name_(
std::move(table_name)), old_name_(
std::move(old_name)),
236 new_name_(
std::move(new_name)) {}
239 if (old_name_.empty() || new_name_.empty()) {
242 table_name_ +
"." + old_name_ +
" -> " + new_name_));
244 return "ALTER TABLE " + table_name_ +
" RENAME COLUMN " + old_name_ +
" TO " + new_name_ +
";";
248 if (old_name_.empty() || new_name_.empty()) {
251 table_name_ +
"." + new_name_ +
" -> " + old_name_));
253 return "ALTER TABLE " + table_name_ +
" RENAME COLUMN " + new_name_ +
" TO " + old_name_ +
";";
262 std::string table_name_;
263 std::string old_name_;
264 std::string new_name_;
268 : table_name_(
std::move(table_name)), old_name_(
std::move(old_name)),
269 new_name_(
std::move(new_name)) {}
272 if (old_name_.empty() || new_name_.empty()) {
275 table_name_ +
" constraint: " + old_name_ +
" -> " + new_name_));
277 return "ALTER TABLE " + table_name_ +
" RENAME CONSTRAINT " + old_name_ +
" TO " + new_name_ +
282 if (old_name_.empty() || new_name_.empty()) {
285 table_name_ +
" constraint: " + new_name_ +
" -> " + old_name_));
287 return "ALTER TABLE " + table_name_ +
" RENAME CONSTRAINT " + new_name_ +
" TO " + old_name_ +
297 std::string table_name_;
298 std::string target_column_;
299 std::string source_column_;
300 std::string forward_transform_;
301 std::string backward_transform_;
305 std::string forward_transform, std::string backward_transform)
306 : table_name_(
std::move(table_name)), target_column_(
std::move(target_column)),
307 source_column_(
std::move(source_column)), forward_transform_(
std::move(forward_transform)),
308 backward_transform_(
std::move(backward_transform)) {}
311 if (forward_transform_.empty()) {
313 "Forward transformation cannot be empty",
314 table_name_ +
"." + target_column_));
316 return "UPDATE " + table_name_ +
" SET " + target_column_ +
" = " + forward_transform_ +
";";
320 if (backward_transform_.empty()) {
322 "Backward transformation cannot be empty",
323 table_name_ +
"." + source_column_));
325 return "UPDATE " + table_name_ +
" SET " + source_column_ +
" = " + backward_transform_ +
";";
334 std::vector<std::unique_ptr<MigrationOperation>> operations_;
341 template <
typename Op,
typename... Args>
343 operations_.push_back(std::make_unique<Op>(std::forward<Args>(args)...));
348 std::vector<std::string> sqls;
349 sqls.reserve(operations_.size());
351 for (
const auto& op : operations_) {
352 auto sql_result = op->to_sql();
354 return std::unexpected(sql_result.error());
356 sqls.push_back(*sql_result);
363 std::vector<std::string> sqls;
364 sqls.reserve(operations_.size());
367 for (
auto it = operations_.rbegin(); it != operations_.rend(); ++it) {
368 auto sql_result = (*it)->rollback_sql();
370 return std::unexpected(sql_result.error());
372 sqls.push_back(*sql_result);
378 const std::string&
name()
const {
return name_; }
381 bool empty()
const {
return operations_.empty(); }
384 size_t size()
const {
return operations_.size(); }
ADD COLUMN migration operation.
MigrationResult< std::string > rollback_sql() const override
AddColumnOperation(std::string table_name, const Column &column)
MigrationResult< std::string > to_sql() const override
OperationType type() const override
CREATE TABLE migration operation.
OperationType type() const override
MigrationResult< std::string > to_sql() const override
MigrationResult< std::string > rollback_sql() const override
CreateTableOperation(const Table &table)
DROP COLUMN migration operation.
MigrationResult< std::string > to_sql() const override
DropColumnOperation(std::string table_name, const Column &column)
OperationType type() const override
MigrationResult< std::string > rollback_sql() const override
DROP TABLE migration operation.
DropTableOperation(const Table &table)
MigrationResult< std::string > to_sql() const override
OperationType type() const override
MigrationResult< std::string > rollback_sql() const override
Base class for migration operations.
virtual MigrationResult< std::vector< std::string > > bind_params() const
virtual MigrationResult< std::string > to_sql() const =0
virtual MigrationResult< std::vector< std::string > > rollback_bind_params() const
virtual ~MigrationOperation()=default
virtual MigrationResult< std::string > rollback_sql() const =0
virtual OperationType type() const =0
Container for migration operations.
Migration(std::string name)
const std::string & name() const
Get migration name.
bool empty() const
Check if migration is empty.
MigrationResult< std::vector< std::string > > rollback_sql() const
Generate rollback migration SQL.
void add_operation(Args &&... args)
Add an operation to the migration.
size_t size() const
Get number of operations.
MigrationResult< std::vector< std::string > > forward_sql() const
Generate forward migration SQL.
RENAME COLUMN migration operation.
RenameColumnOperation(std::string table_name, std::string old_name, std::string new_name)
MigrationResult< std::string > to_sql() const override
MigrationResult< std::string > rollback_sql() const override
OperationType type() const override
RENAME CONSTRAINT migration operation.
RenameConstraintOperation(std::string table_name, std::string old_name, std::string new_name)
OperationType type() const override
MigrationResult< std::string > rollback_sql() const override
MigrationResult< std::string > to_sql() const override
UPDATE DATA migration operation for column transformations.
MigrationResult< std::string > rollback_sql() const override
UpdateDataOperation(std::string table_name, std::string target_column, std::string source_column, std::string forward_transform, std::string backward_transform)
OperationType type() const override
MigrationResult< std::string > to_sql() const override
Represents a column in a database table.
Generate CREATE TABLE SQL statement for a table struct.
std::string to_sql() const
Generate DROP TABLE SQL statement for a table struct.
std::string to_sql() const
drop_table & if_exists(bool if_exists=true)
std::expected< T, MigrationError > MigrationResult
Result type for migration operations.
OperationType
Enum for migration operation types.
MigrationErrorType
Error types for migration operations.
@ INVALID_TABLE_STRUCTURE
@ MIGRATION_GENERATION_FAILED
Error information for migration operations.
std::string format() const
Get a formatted error message.
std::string context
Additional context (table name, column name, etc.)
static MigrationError make(MigrationErrorType type, const std::string &message, const std::string &context="")
Create a MigrationError with automatic formatting.