Lightweight 0.20261105.1
Loading...
Searching...
No Matches
SQL Migration

Classes and functions for SQL schema migrations. More...

Classes

struct  Lightweight::SqlMigration::MigrationTimestamp
 
class  Lightweight::SqlMigration::MigrationException
 
struct  Lightweight::SqlMigration::ChecksumVerificationResult
 
struct  Lightweight::SqlMigration::RevertResult
 
struct  Lightweight::SqlMigration::MigrationStatus
 
struct  Lightweight::SqlMigration::MigrationRelease
 
struct  Lightweight::SqlMigration::MigrationReleaseOptions
 
struct  Lightweight::SqlMigration::MigrationHistoryState
 
struct  Lightweight::SqlMigration::BackupRecord
 
struct  Lightweight::SqlMigration::BackupRequirement
 
class  Lightweight::SqlMigration::UnicodeUpgradeUnitError
 
struct  Lightweight::SqlMigration::PreMigrateStepOptions
 
struct  Lightweight::SqlMigration::PreMigrateStepInfo
 
class  Lightweight::SqlMigration::PreMigrateStepError
 
class  Lightweight::SqlMigration::MigrationManager
 
class  Lightweight::SqlMigration::MigrationBase
 
struct  Lightweight::SqlMigration::MigrationMetadata
 

Macros

#define LIGHTWEIGHT_MIGRATION_PLUGIN()
 
#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTINIT(connArg, mgrArg)
 
#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTMIGRATE(connArg, mgrArg)
 
#define LIGHTWEIGHT_MIGRATION_INSTANCE(timestamp)   migration_##timestamp
 Represents the C++ migration object for a given timestamped migration.
 
#define LIGHTWEIGHT_SQL_MIGRATION(timestamp, description)
 Creates a new migration.
 
#define LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE(timestamp, description)
 Creates a new reversible migration whose Down() is defined out-of-line via LIGHTWEIGHT_SQL_MIGRATION_DOWN.
 
#define LIGHTWEIGHT_SQL_MIGRATION_DOWN(timestamp)    void Migration_##timestamp::Down(Lightweight::SqlMigrationQueryBuilder& plan) const
 Companion to LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE — defines the out-of-line Down() body.
 
#define LIGHTWEIGHT_SQL_RELEASE(version, ...)
 Associates a software release (version string) with the highest migration timestamp present at the time of that release.
 

Typedefs

using Lightweight::SqlMigration::PreMigrateStep = std::function< void(SqlConnection &, MigrationManager &, ProgressTask &, ExecutionMode)>
 

Enumerations

enum class  Lightweight::SqlMigration::BackupRecordKind : std::uint8_t { BackupRecordKind::Backup , BackupRecordKind::Restore , BackupRecordKind::Waived }
 
enum class  Lightweight::SqlMigration::ExecutionMode : std::uint8_t { ExecutionMode::Execute , ExecutionMode::DryRun }
 
enum class  Lightweight::SqlMigration::PreMigrateStepsOutcome : std::uint8_t { PreMigrateStepsOutcome::Completed , PreMigrateStepsOutcome::Cancelled }
 

Functions

LIGHTWEIGHT_API MigrationHistoryState Lightweight::SqlMigration::ReadMigrationHistoryState (DataMapper &dataMapper)
 
LIGHTWEIGHT_API std::optional< BackupRecord > Lightweight::SqlMigration::ReadLatestBackupRecord (DataMapper &dataMapper)
 
LIGHTWEIGHT_API std::expected< BackupRecord, SqlErrorInfo > Lightweight::SqlMigration::WriteBackupRecord (DataMapper &dataMapper, BackupRecord record)
 
LIGHTWEIGHT_API bool Lightweight::SqlMigration::BackupRecordCovers (BackupRecord const &record, MigrationHistoryState const &state) noexcept
 
LIGHTWEIGHT_API bool Lightweight::SqlMigration::IsValidSchemaName (std::string_view schema) noexcept
 

Variables

constexpr std::string_view Lightweight::SqlMigration::BackupRecordTableName = "schema_backups"
 
constexpr std::string_view Lightweight::SqlMigration::EmptyMigrationHistoryDigest
 

Detailed Description

Classes and functions for SQL schema migrations.

Macro Definition Documentation

◆ LIGHTWEIGHT_MIGRATION_PLUGIN

#define LIGHTWEIGHT_MIGRATION_PLUGIN ( )
Value:
/* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
extern "C" LIGHTWEIGHT_EXPORT Lightweight::SqlMigration::MigrationManager* AcquireMigrationManager() \
{ \
}
static LIGHTWEIGHT_API MigrationManager & GetInstance()

Requires the user to call LIGHTWEIGHT_MIGRATION_PLUGIN() in exactly one CPP file of the migration plugin.

Definition at line 1192 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_MIGRATION_PLUGIN_POSTINIT

#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTINIT (   connArg,
  mgrArg 
)
Value:
LIGHTWEIGHT_DETAIL_MIGRATION_PLUGIN_HOOK( \
LightweightMigrationPluginPostInitReported, LightweightMigrationPluginPostInitBody, connArg, mgrArg)

Optional hook executed once per plugin by dbtool, after migration history has been created and an active connection is available on the central manager. Plugins use this to perform one-shot bridging work that needs both a live SqlConnection and the merged MigrationManager — for example, importing legacy version tracking from a custom table into schema_migrations.

A hook body that throws is reported by the host and does not stop it. The macro exports the non-throwing C entry point LightweightMigrationPluginPostInitReported, which catches the exception and hands its message to the host, so no exception crosses the shared-library boundary, whatever exception model the plugin uses. Hosts skip, with a warning, a plugin that exports only the earlier LightweightMigrationPluginPostInit; rebuild such a plugin.

Use as:

{
MyPlugin::ImportLegacyVersions(manager, connection);
}
#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTINIT(connArg, mgrArg)

Definition at line 1251 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_MIGRATION_PLUGIN_POSTMIGRATE

#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTMIGRATE (   connArg,
  mgrArg 
)
Value:
LIGHTWEIGHT_DETAIL_MIGRATION_PLUGIN_HOOK( \
LightweightMigrationPluginPostMigrate, LightweightMigrationPluginPostMigrateBody, connArg, mgrArg)

Optional hook executed once per plugin by dbtool and dbtool-gui after a successful migrate, migrate-to-release or apply, including runs where nothing was pending. It runs on the migration connection while the migration lock is still held (unless the caller opted out of locking, as with dbtool --no-lock), and never for dry runs, read-only commands or a failed migration. Plugins use it for work that needs the migrated schema, such as seeding reference data.

A hook body that throws makes the command fail; the migrations it ran after stay applied. The macro exports a non-throwing C entry point that catches the exception and hands its message to the host, so no exception crosses the shared-library boundary.

Use as:

{
MyPlugin::SeedReferenceData(connection);
}
#define LIGHTWEIGHT_MIGRATION_PLUGIN_POSTMIGRATE(connArg, mgrArg)

Definition at line 1276 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_MIGRATION_INSTANCE

#define LIGHTWEIGHT_MIGRATION_INSTANCE (   timestamp)    migration_##timestamp

Represents the C++ migration object for a given timestamped migration.

Parameters
timestampTimestamp of the migration.

Definition at line 1586 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_SQL_MIGRATION

#define LIGHTWEIGHT_SQL_MIGRATION (   timestamp,
  description 
)
Value:
struct Migration_##timestamp: public Lightweight::SqlMigration::MigrationBase \
{ \
/** The migration's timestamp, exposed so @ref TimestampOf can extract it from the type. */ \
static constexpr Lightweight::SqlMigration::MigrationTimestamp TimeStamp { static_cast<uint64_t>(timestamp) }; \
explicit Migration_##timestamp(): \
Lightweight::SqlMigration::MigrationBase(TimeStamp, description) \
{ \
} \
\
void Up(Lightweight::SqlMigrationQueryBuilder& plan) const override; \
void Down(Lightweight::SqlMigrationQueryBuilder& /*plan*/) const override {} \
}; \
\
static Migration_##timestamp _LIGHTWEIGHT_CONCATENATE(migration_, timestamp); \
\
void Migration_##timestamp::Up(Lightweight::SqlMigrationQueryBuilder& plan) const
Query builder for building SQL migration queries.
Definition Migrate.hpp:521

Creates a new migration.

Parameters
timestampTimestamp of the migration.
descriptionDescription of the migration.
Note
The migration will be registered with the migration manager automatically.
#include <Lightweight/SqlMigration.hpp>
LIGHTWEIGHT_SQL_MIGRATION(20260117234120, "Create table 'MyTable'")
{
// Use 'plan' to define the migration steps, for example creating tables.
}
#define LIGHTWEIGHT_SQL_MIGRATION(timestamp, description)
Creates a new migration.
See also
Lightweight::SqlMigrationQueryBuilder

Definition at line 1606 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE

#define LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE (   timestamp,
  description 
)
Value:
struct Migration_##timestamp: public Lightweight::SqlMigration::MigrationBase \
{ \
explicit Migration_##timestamp(): \
Lightweight::SqlMigration::MigrationBase(Lightweight::SqlMigration::MigrationTimestamp { timestamp }, \
description) \
{ \
} \
\
void Up(Lightweight::SqlMigrationQueryBuilder& plan) const override; \
void Down(Lightweight::SqlMigrationQueryBuilder& plan) const override; \
\
[[nodiscard]] bool HasDownImplementation() const noexcept override \
{ \
return true; \
} \
}; \
\
static Migration_##timestamp _LIGHTWEIGHT_CONCATENATE(migration_, timestamp); \
\
void Migration_##timestamp::Up(Lightweight::SqlMigrationQueryBuilder& plan) const

Creates a new reversible migration whose Down() is defined out-of-line via LIGHTWEIGHT_SQL_MIGRATION_DOWN.

Use this variant when the migration needs to be reversible. Follow the macro with the Up() body, then later use LIGHTWEIGHT_SQL_MIGRATION_DOWN(timestamp) { ... } to provide the Down() body.

Parameters
timestampTimestamp of the migration.
descriptionDescription of the migration.
LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE(20260117234120, "Create table 'MyTable'")
{
plan.CreateTable("MyTable").PrimaryKey("id", Integer());
}
{
plan.DropTable("MyTable");
}
#define LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE(timestamp, description)
Creates a new reversible migration whose Down() is defined out-of-line via LIGHTWEIGHT_SQL_MIGRATION_...
#define LIGHTWEIGHT_SQL_MIGRATION_DOWN(timestamp)
Companion to LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE — defines the out-of-line Down() body.

Definition at line 1647 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_SQL_MIGRATION_DOWN

#define LIGHTWEIGHT_SQL_MIGRATION_DOWN (   timestamp)     void Migration_##timestamp::Down(Lightweight::SqlMigrationQueryBuilder& plan) const

Companion to LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE — defines the out-of-line Down() body.

Must be used in the same translation unit and follow the matching LIGHTWEIGHT_SQL_MIGRATION_REVERSIBLE(timestamp, ...) declaration.

Parameters
timestampTimestamp of the migration whose Down() body follows.

Definition at line 1677 of file SqlMigration.hpp.

◆ LIGHTWEIGHT_SQL_RELEASE

#define LIGHTWEIGHT_SQL_RELEASE (   version,
  ... 
)
Value:
static ::Lightweight::SqlMigration::detail::ReleaseRegistrar _LIGHTWEIGHT_CONCATENATE_INNER(_lw_release_, __COUNTER__) \
{ \
(version), __VA_ARGS__ \
}

Associates a software release (version string) with the highest migration timestamp present at the time of that release.

Declare one LIGHTWEIGHT_SQL_RELEASE per cut release, alongside the migrations that belong to it. The macro registers with the migration manager at static-initialization time. Multiple releases may coexist in the same translation unit.

Parameters
versionA string literal, e.g. "2.0.0".
...The highest migration timestamp of the release, optionally followed by its MigrationReleaseOptions, e.g. { .requiresBackup = true }.
LIGHTWEIGHT_SQL_RELEASE("1.0.0", 20260101120000);
LIGHTWEIGHT_SQL_RELEASE("2.0.0", 20260501120000, { .requiresBackup = true });
#define LIGHTWEIGHT_SQL_RELEASE(version,...)
Associates a software release (version string) with the highest migration timestamp present at the ti...

Definition at line 1697 of file SqlMigration.hpp.

Typedef Documentation

◆ PreMigrateStep

Work a plugin runs before the first pending migration of migrate, apply and migrate-to-release.

The first parameter is the migration connection, on which the host holds the migration lock unless it opted out of locking; then the host's manager, the step's own task and the execution mode, in which a dry run makes the step report its plan and change nothing.

Definition at line 411 of file SqlMigration.hpp.

Enumeration Type Documentation

◆ BackupRecordKind

enum class Lightweight::SqlMigration::BackupRecordKind : std::uint8_t
strong

What a schema_backups record documents.

Enumerator
Backup 

A verified backup archive was written; stored as backup.

Restore 

A backup archive was restored into the database; stored as restore.

Waived 

A migrating run went ahead without a backup because the user explicitly waived it; stored as waived. Never satisfies a requirement.

Definition at line 226 of file SqlMigration.hpp.

◆ ExecutionMode

enum class Lightweight::SqlMigration::ExecutionMode : std::uint8_t
strong

Whether an operation changes the database or only reports what it would change.

Enumerator
Execute 

Carry the operation out.

DryRun 

Report the plan and change nothing.

Definition at line 386 of file SqlMigration.hpp.

◆ PreMigrateStepsOutcome

enum class Lightweight::SqlMigration::PreMigrateStepsOutcome : std::uint8_t
strong

How MigrationManager::RunPreMigrateSteps ended.

Enumerator
Completed 

Every step ran; the migrations may follow.

Cancelled 

The task asked to cancel; the caller applies no migration.

Definition at line 425 of file SqlMigration.hpp.

Function Documentation

◆ ReadMigrationHistoryState()

LIGHTWEIGHT_API MigrationHistoryState Lightweight::SqlMigration::ReadMigrationHistoryState ( DataMapper &  dataMapper)

Reads the migration history from schema_migrations.

Physical rows only; the virtual-applied overlay does not count.

Parameters
dataMapperThe migration connection's mapper.
Returns
The state; empty when the table is missing. Other errors throw.

◆ ReadLatestBackupRecord()

LIGHTWEIGHT_API std::optional< BackupRecord > Lightweight::SqlMigration::ReadLatestBackupRecord ( DataMapper &  dataMapper)

Reads the newest backup or restore record, by id; waived records are skipped.

Parameters
dataMapperThe migration connection's mapper.
Returns
The record; empty when there is none or the table is missing. Other errors throw.

◆ WriteBackupRecord()

LIGHTWEIGHT_API std::expected< BackupRecord, SqlErrorInfo > Lightweight::SqlMigration::WriteBackupRecord ( DataMapper &  dataMapper,
BackupRecord  record 
)

Appends a record to schema_backups, creating the table when it is missing.

Parameters
dataMapperThe migration connection's mapper.
recordThe record to store; its id is ignored.
Returns
The record with the id the database assigned, or the database error.

◆ BackupRecordCovers()

LIGHTWEIGHT_API bool Lightweight::SqlMigration::BackupRecordCovers ( BackupRecord const &  record,
MigrationHistoryState const &  state 
)
noexcept

Whether record covers the database state state.

Only a backup or restore record can cover, and it does when it saw exactly the current migration history: its observedState.digest equals the state's. Any migration applied, re-applied, rolled back or re-stamped since changes the digest. Only values read from the database are compared, so createdAt and the clocks of the hosts involved play no part. Any other kind covers nothing.

Parameters
recordThe record to test.
stateThe current migration state.

◆ IsValidSchemaName()

LIGHTWEIGHT_API bool Lightweight::SqlMigration::IsValidSchemaName ( std::string_view  schema)
noexcept

Whether schema is a schema name MigrationManager::SetDefaultSchema accepts: [A-Za-z0-9_]+.

Parameters
schemaThe name to check.
Returns
False for an empty name and for any other character.

Variable Documentation

◆ BackupRecordTableName

constexpr std::string_view Lightweight::SqlMigration::BackupRecordTableName = "schema_backups"
inlineconstexpr

Name of the table that holds the backup records.

Definition at line 238 of file SqlMigration.hpp.

◆ EmptyMigrationHistoryDigest

constexpr std::string_view Lightweight::SqlMigration::EmptyMigrationHistoryDigest
inlineconstexpr
Initial value:
=
"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

The SHA-256 of an empty schema_migrations history (the digest of no rows).

Definition at line 243 of file SqlMigration.hpp.