pub enum Operation {
Show 25 variants
CreateTable {
name: String,
columns: Vec<ColumnDefinition>,
constraints: Vec<Constraint>,
without_rowid: Option<bool>,
interleave_in_parent: Option<InterleaveSpec>,
partition: Option<PartitionOptions>,
},
DropTable {
name: String,
},
AddColumn {
table: String,
column: ColumnDefinition,
mysql_options: Option<AlterTableOptions>,
},
DropColumn {
table: String,
column: String,
},
AlterColumn {
table: String,
column: String,
old_definition: Option<ColumnDefinition>,
new_definition: ColumnDefinition,
mysql_options: Option<AlterTableOptions>,
},
RenameTable {
old_name: String,
new_name: String,
},
RenameColumn {
table: String,
old_name: String,
new_name: String,
},
AddConstraint {
table: String,
constraint_sql: String,
},
DropConstraint {
table: String,
constraint_name: String,
},
CreateIndex {
table: String,
columns: Vec<String>,
unique: bool,
index_type: Option<IndexType>,
where_clause: Option<String>,
concurrently: bool,
expressions: Option<Vec<String>>,
mysql_options: Option<AlterTableOptions>,
operator_class: Option<String>,
},
DropIndex {
table: String,
columns: Vec<String>,
},
RunSQL {
sql: String,
reverse_sql: Option<String>,
},
RunRust {
code: String,
reverse_code: Option<String>,
},
AlterTableComment {
table: String,
comment: Option<String>,
},
AlterUniqueTogether {
table: String,
unique_together: Vec<Vec<String>>,
},
AlterModelOptions {
table: String,
options: HashMap<String, String>,
},
CreateInheritedTable {
name: String,
columns: Vec<ColumnDefinition>,
base_table: String,
join_column: String,
},
AddDiscriminatorColumn {
table: String,
column_name: String,
default_value: String,
},
MoveModel {
model_name: String,
from_app: String,
to_app: String,
rename_table: bool,
old_table_name: Option<String>,
new_table_name: Option<String>,
},
CreateSchema {
name: String,
if_not_exists: bool,
},
DropSchema {
name: String,
cascade: bool,
if_exists: bool,
},
CreateExtension {
name: String,
if_not_exists: bool,
schema: Option<String>,
},
BulkLoad {
table: String,
source: BulkLoadSource,
format: BulkLoadFormat,
options: BulkLoadOptions,
},
SetAutoIncrementValue {
table: String,
column: String,
value: i64,
},
CreateCompositePrimaryKey {
table: String,
columns: Vec<String>,
constraint_name: Option<String>,
},
}Expand description
A migration operation (legacy enum for backward compatibility)
This enum is maintained for backward compatibility with existing code.
New code should use the specific operation types from the models, fields,
and special modules instead.
Variants§
CreateTable
CreateTable variant.
Fields
columns: Vec<ColumnDefinition>The columns.
constraints: Vec<Constraint>The constraints.
interleave_in_parent: Option<InterleaveSpec>The interleave in parent.
partition: Option<PartitionOptions>The partition.
DropTable
DropTable variant.
AddColumn
AddColumn variant.
Fields
column: ColumnDefinitionThe column.
mysql_options: Option<AlterTableOptions>The mysql options.
DropColumn
DropColumn variant.
AlterColumn
AlterColumn variant.
Fields
old_definition: Option<ColumnDefinition>Original column definition (before alteration). This is required for generating accurate rollback SQL. If None, rollback will attempt to reconstruct from ProjectState.
new_definition: ColumnDefinitionThe new definition.
mysql_options: Option<AlterTableOptions>The mysql options.
RenameTable
RenameTable variant.
RenameColumn
RenameColumn variant.
AddConstraint
AddConstraint variant.
DropConstraint
DropConstraint variant.
CreateIndex
CreateIndex variant.
Fields
index_type: Option<IndexType>Index type (B-Tree, Hash, GIN, GiST, etc.)
If not specified, the database will use its default index type (typically B-Tree).
where_clause: Option<String>Partial index condition (WHERE clause)
Creates a partial index that only indexes rows matching this condition. Example: “status = ‘active’” creates an index only for active rows.
concurrently: boolCreate index concurrently (PostgreSQL-specific)
When true, creates the index without locking the table for writes. This is slower but allows concurrent operations during index creation.
expressions: Option<Vec<String>>Expression index (PostgreSQL, SQLite, MySQL 8.0+)
Index on computed expressions rather than simple column references.
When specified, these expressions are used instead of columns.
§Examples
// Index on lowercase email for case-insensitive lookups
expressions: Some(vec!["LOWER(email)"]),Note: When expressions is Some, columns is ignored for SQL generation.
mysql_options: Option<AlterTableOptions>MySQL ALTER TABLE options (ALGORITHM, LOCK)
operator_class: Option<String>Operator class for index columns (PostgreSQL-specific)
Specifies a non-default operator class for the index.
Commonly used with extension-provided operator classes like gin_trgm_ops
for trigram similarity search with the pg_trgm extension.
§Examples
// GIN index with trigram operator class for fuzzy text search
CreateIndex {
table: "products".to_string(),
columns: vec!["name".to_string()],
index_type: Some(IndexType::Gin),
operator_class: Some("gin_trgm_ops"),
...
}DropIndex
DropIndex variant.
RunSQL
RunSQL variant.
RunRust
RunRust variant.
AlterTableComment
AlterTableComment variant.
AlterUniqueTogether
AlterUniqueTogether variant.
AlterModelOptions
AlterModelOptions variant.
CreateInheritedTable
CreateInheritedTable variant.
Fields
columns: Vec<ColumnDefinition>The columns.
AddDiscriminatorColumn
AddDiscriminatorColumn variant.
Fields
MoveModel
Move a model from one app to another
This operation handles cross-app model moves by:
- Optionally renaming the table (if naming convention changes between apps)
- Updating FK references to use the new table name
Note: This generates a RenameTable SQL if table name changes. The state tracking (from_app -> to_app) is handled at the ProjectState level.
Fields
CreateSchema
Create a database schema (PostgreSQL, MySQL 5.0.2+)
Creates a new database schema namespace. In MySQL, this is equivalent to creating a database.
Fields
DropSchema
Drop a database schema
Drops an existing database schema. Use with caution as this will drop all objects in the schema.
Fields
CreateExtension
Create a PostgreSQL extension (PostgreSQL-specific)
Creates a PostgreSQL extension like PostGIS, uuid-ossp, etc. This operation is only executed on PostgreSQL databases.
Fields
BulkLoad
Bulk data loading operation
Loads large amounts of data efficiently using database-native bulk loading commands:
- PostgreSQL:
COPY table FROM source WITH (FORMAT csv, ...) - MySQL:
LOAD DATA [LOCAL] INFILE 'path' INTO TABLE table ... - SQLite: Not supported (falls back to INSERT statements)
§Performance
Bulk loading is typically 10-100x faster than individual INSERT statements for large datasets.
§Examples
use reinhardt_db::migrations::{Operation, BulkLoadSource, BulkLoadFormat, BulkLoadOptions};
// PostgreSQL COPY FROM file
let op = Operation::BulkLoad {
table: "events".to_string(),
source: BulkLoadSource::File("/tmp/events.csv"),
format: BulkLoadFormat::Csv,
options: BulkLoadOptions::new()
.with_header(true)
.with_delimiter(','),
};
// MySQL LOAD DATA LOCAL INFILE
let op = Operation::BulkLoad {
table: "events".to_string(),
source: BulkLoadSource::File("/tmp/events.csv"),
format: BulkLoadFormat::Csv,
options: BulkLoadOptions::new()
.with_local(true)
.with_delimiter(','),
};Fields
source: BulkLoadSourceSource of the data
format: BulkLoadFormatFormat of the data
options: BulkLoadOptionsAdditional loading options
SetAutoIncrementValue
Reset the auto-increment counter for a table
Sets the next value produced by the table’s auto-increment mechanism. Typical uses include seeding IDs after a bulk import or shifting the sequence above a range reserved for historical data.
§Backend Behavior
- PostgreSQL / CockroachDB:
SELECT setval(pg_get_serial_sequence('{table}', '{column}'), {value}, false)(resolves the sequence dynamically so both defaultSERIALconventions and user-defined sequence names work;falsemakes the NEXT generated value equal{value}). - MySQL:
ALTER TABLE {table} AUTO_INCREMENT = {value}. - SQLite:
INSERT OR REPLACE INTO sqlite_sequence(name, seq) VALUES (...)(robust against tables that have not yet inserted any rows, where a simpleUPDATEwould silently no-op).
Fields
CreateCompositePrimaryKey
Create a composite (multi-column) PRIMARY KEY constraint on an existing table
Emits ALTER TABLE {table} ADD CONSTRAINT {name} PRIMARY KEY ({cols})
on every supported backend. When constraint_name is None the name
defaults to {table}_pkey, matching PostgreSQL’s conventional
auto-generated identifier.
columns must be non-empty; emitting an empty column list would
produce invalid SQL and is rejected as an InvalidMigration error at
SQL generation time.
Implementations§
Source§impl Operation
impl Operation
Sourcepub fn state_forwards(&self, app_label: &str, state: &mut ProjectState)
pub fn state_forwards(&self, app_label: &str, state: &mut ProjectState)
Apply this operation to the project state (forward)
Sourcepub fn to_sql(&self, dialect: &SqlDialect) -> String
pub fn to_sql(&self, dialect: &SqlDialect) -> String
Generate forward SQL
Sourcepub fn to_reverse_sql(
&self,
dialect: &SqlDialect,
project_state: &ProjectState,
) -> Result<Option<String>, MigrationError>
pub fn to_reverse_sql( &self, dialect: &SqlDialect, project_state: &ProjectState, ) -> Result<Option<String>, MigrationError>
Generate reverse SQL (for rollback)
§Arguments
dialect- SQL dialect for generating database-specific SQLproject_state- Project state for accessing model definitions (needed for DropTable, etc.)
§Returns
Ok(Some(sql))- Reverse SQL generated successfullyOk(None)- Operation is not reversible (see Design Limitation below)Err(_)- Error generating reverse SQL
§Design Limitation
Destructive operations (DropTable, DropColumn, DropConstraint, AlterColumn)
require a pre-operation ProjectState snapshot to generate reverse SQL. When the
project_state parameter does not contain the necessary model/column/constraint
definition, this method returns Ok(None) instead of failing.
This is an intentional design decision: the migration system cannot reconstruct
lost schema information. Callers must provide the state from before the operation
was applied to enable proper rollback. This matches Django’s migration behavior
where state_forwards must be called before operations are reversed.
Sourcepub fn state_backwards(&self, app_label: &str, state: &mut ProjectState)
pub fn state_backwards(&self, app_label: &str, state: &mut ProjectState)
Apply operation to project state (backward/reverse)
This method updates the ProjectState to reflect the reverse of this operation. Used during migration rollback to track state changes.
§Arguments
app_label- Application label for the model being modifiedstate- Mutable reference to the ProjectState to update
§Limitations
Some operations cannot fully reverse state without additional snapshot information:
DropTable: Cannot recreate model structure (columns, constraints) without snapshotDropColumn: Cannot recreate column definition without snapshotAlterColumn: Cannot restore original column definition without snapshot
For these operations, use to_reverse_sql with ProjectState before the operation
is applied to generate proper reverse SQL.
Source§impl Operation
impl Operation
Sourcepub fn requires_sqlite_recreation(&self) -> bool
pub fn requires_sqlite_recreation(&self) -> bool
Check if this operation requires SQLite table recreation
Sourcepub fn reverse_requires_sqlite_recreation(&self) -> bool
pub fn reverse_requires_sqlite_recreation(&self) -> bool
Check if the reverse of this operation requires SQLite table recreation
When rolling back a migration on SQLite, some reverse operations also require table recreation. This method identifies those cases.
| Forward Operation | Reverse Operation | Requires Recreation |
|---|---|---|
| AddColumn | DropColumn | Yes |
| AlterColumn | AlterColumn | Yes |
| AddConstraint | DropConstraint | Yes |
| DropConstraint | AddConstraint | Yes |
Sourcepub fn to_reverse_operation(
&self,
project_state: &ProjectState,
) -> Result<Option<Operation>, MigrationError>
pub fn to_reverse_operation( &self, project_state: &ProjectState, ) -> Result<Option<Operation>, MigrationError>
Generate the reverse operation (for rollback on SQLite)
This method returns the conceptual reverse Operation, which can be used
with handle_sqlite_recreation() for databases that don’t support direct
ALTER TABLE operations.
§Arguments
project_state- Project state for accessing model definitions
§Returns
Ok(Some(op))- Reverse operation generated successfullyOk(None)- Operation is not reversible or state information is missingErr(_)- Error generating reverse operation
Source§impl Operation
impl Operation
Sourcepub fn to_statement(&self) -> OperationStatement
pub fn to_statement(&self) -> OperationStatement
Convert Operation to reinhardt-query statement or sanitized raw SQL
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Operation
impl<'de> Deserialize<'de> for Operation
Source§fn deserialize<__D>(
__deserializer: __D,
) -> Result<Operation, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(
__deserializer: __D,
) -> Result<Operation, <__D as Deserializer<'de>>::Error>where
__D: Deserializer<'de>,
Source§impl MigrationOperation for Operation
impl MigrationOperation for Operation
Source§fn normalize(&self) -> Operation
fn normalize(&self) -> Operation
Normalize operation for semantic comparison
Returns a normalized version where order-independent elements are sorted. This enables detection of semantically equivalent operations regardless of element ordering.
Source§impl Serialize for Operation
impl Serialize for Operation
Source§fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
fn serialize<__S>(
&self,
__serializer: __S,
) -> Result<<__S as Serializer>::Ok, <__S as Serializer>::Error>where
__S: Serializer,
Source§impl ToTokens for Operation
impl ToTokens for Operation
Source§fn to_tokens(&self, tokens: &mut TokenStream)
fn to_tokens(&self, tokens: &mut TokenStream)
Source§fn to_token_stream(&self) -> TokenStream
fn to_token_stream(&self) -> TokenStream
Source§fn into_token_stream(self) -> TokenStreamwhere
Self: Sized,
fn into_token_stream(self) -> TokenStreamwhere
Self: Sized,
impl StructuralPartialEq for Operation
Auto Trait Implementations§
impl Freeze for Operation
impl RefUnwindSafe for Operation
impl Send for Operation
impl Sync for Operation
impl Unpin for Operation
impl UnsafeUnpin for Operation
impl UnwindSafe for Operation
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<E> ServerFnErrorAssertions<E> for Ewhere
E: Debug,
impl<E> ServerFnErrorAssertions<E> for Ewhere
E: Debug,
Source§fn should_contain_message(&self, expected: &str)where
E: Display,
fn should_contain_message(&self, expected: &str)where
E: Display,
Source§fn should_have_message(&self, expected: &str)where
E: Display,
fn should_have_message(&self, expected: &str)where
E: Display,
Source§impl<T> Spanned for Twhere
T: Spanned + ?Sized,
impl<T> Spanned for Twhere
T: Spanned + ?Sized,
Source§fn span(&self) -> Span
fn span(&self) -> Span
Span covering the complete contents of this syntax tree
node, or Span::call_site() if this node is empty.