pub enum Operation {
CreateTable {
table: String,
columns: Vec<Column>,
unique_together: Vec<Vec<String>>,
indexes: Vec<Vec<String>>,
},
DropTable {
table: String,
},
AddColumn {
table: String,
column: Column,
},
DropColumn {
table: String,
column: String,
},
AlterColumn {
table: String,
column: String,
new_columns: Vec<Column>,
prev_columns: Option<Vec<Column>>,
},
RenameTable {
from: String,
to: String,
},
CreateM2MTable {
junction_table: String,
parent_table: String,
parent_col: String,
child_table: String,
child_col: String,
parent_ty: SqlType,
child_ty: SqlType,
},
DropM2MTable {
junction_table: String,
},
RenameColumn {
table: String,
from: String,
to: String,
column: Option<Column>,
},
RunSql {
sql: String,
reverse_sql: Option<String>,
},
}Expand description
One operation inside a migration. The migration engine renders each
operation to SQL via the active backend (M4 DatabaseBackend:: map_type) and runs them in declaration order inside one
transaction per migration file.
M5 v1 shipped table-level ops; M8 v1 adds AddColumn and
DropColumn. AlterColumn, index / constraint ops, and
RunSql / RunCode are deferred (see docs/specs/06-migration- engine.md).
Variants§
CreateTable
Create a new table. columns is in declaration order; the
engine builds a sea-query Table::create() over them and runs
the rendered DDL. unique_together lowers to inline
UNIQUE (col1, col2) clauses; indexes lowers to follow-up
CREATE INDEX statements after the table is created. Both
default to empty for backward-compat with older snapshots.
Fields
DropTable
Drop an existing table.
AddColumn
Add a new column to an existing table. Rendered as
ALTER TABLE x ADD COLUMN y TYPE [NOT NULL]. SQLite refuses a
non-nullable add against a populated table without a default;
the engine surfaces that as a sqlx error at apply time (M8 v1).
A future op AddColumnWithDefault lifts the restriction once
the #[umbral(default = ...)] attribute lands.
DropColumn
Drop a column from an existing table. Rendered as
ALTER TABLE x DROP COLUMN y. SQLite 3.35+ and Postgres
support this natively; older SQLite would need a table-
recreation dance the engine doesn’t implement.
AlterColumn
Alter a column’s nullable flag (the only safe in-place change
the engine ships at M5.1). Self-contained: carries the full
new column list so the SQLite table-recreation dance can
rebuild the schema without re-reading the snapshot. The
column field names the specific column that triggered the
alter (used for the filename suffix and diagnostics); the
new_columns list is the post-change schema.
Fields
prev_columns: Option<Vec<Column>>Snapshot of the table’s columns before this alter. Carried
so the Postgres renderer can decide per-column whether it
needs a TYPE/USING clause vs a SET/DROP NOT NULL — without
re-walking the snapshot file. Option + serde(default)
keeps older on-disk migrations deserialising cleanly; ops
produced before this field existed get None and fall back
to the legacy nullable-only Postgres path.
RenameTable
Rename an existing table. Emitted by diff when a model’s table
name changes but its Model::NAME (the Rust struct name) stays
the same (first-pass detection), or when the column shapes are
bit-identical and the struct name changed too (second-pass
heuristic detection). Both SQLite and Postgres render as
ALTER TABLE "<from>" RENAME TO "<to>".
The migration tracking table records (plugin, name) of each
applied migration — it is not affected by a table rename inside
the migration.
CreateM2MTable
Create a many-to-many junction table. Auto-emitted when a model
gains an M2M<T> field. Closes BUG-16 phase 2.
The junction table name is parent_table_field_name. Columns:
parent_id (FK to parent), child_id (FK to target), both with
ON DELETE CASCADE. Composite PK (parent_id, child_id).
parent_ty and child_ty carry the SQL types of the
referenced PK columns — BigInt for an i64 PK, Text for a
String slug, Uuid for a uuid::Uuid. The renderer maps
these to the right column type per backend; without them the
junction’s child_id INTEGER would reject a string codename
at insert time. #[serde(default)] keeps older snapshot files
(pre-phase-2) round-tripping — they default to BigInt,
matching the original i64-only behaviour.
Fields
DropM2MTable
Drop a many-to-many junction table. Auto-emitted when an M2M<T>
field is removed from a model.
RenameColumn
Gap 88: rename a column on an existing table. Emitted by the
diff engine when a single column with one shape was dropped
and one with the same shape was added in the same diff —
the heuristic match for “the user renamed title to
headline.” Both SQLite (3.25+) and Postgres render as
ALTER TABLE "<t>" RENAME COLUMN "<from>" TO "<to>".
column carries the post-rename column shape so the
snapshot stays in sync. The migration only renames; never
alters other column attributes — a rename combined with a
type change emits a RenameColumn AND a follow-on AlterColumn
against the new name.
RunSql
Gap #69: a raw-SQL data migration. Unlike every other
variant it changes rows, not the schema model — so the
autodetector NEVER emits it (it has no model-state effect), and
a migration carrying only RunSql ops has
snapshot_after == snapshot_before. It is always hand-authored:
generate an empty migration with makemigrations --empty <plugin>, then add the RunSql op by editing the file.
sql is the forward statement(s), executed verbatim on the
per-migration transaction — same string on both backends (raw
SQL the renderer passes through untouched), so the author owns
portability. reverse_sql is the optional un-apply statement
(used by a future migrate --reverse); None means
irreversible.
Under schema-per-tenant the op runs per tenant schema (the
schema-migrate loop applies every op under the
<schema>, public search_path), so a tenant-app RunSql writes
tenant rows while reading shared public lookup tables — the
boundary-spanning data migration. A shared-app RunSql runs once
in public via the normal migrate.
Implementations§
Source§impl Operation
impl Operation
Sourcepub fn table_name(&self) -> &str
pub fn table_name(&self) -> &str
The primary table this operation targets. For RenameTable,
returns the source name (the post-rename to lives in the new
snapshot, but routing decisions look up the model meta by its
pre-rename from).
Used by run_in’s per-DB dispatch loop to route each op to the
pool where its table actually lives.
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Operation
impl<'de> Deserialize<'de> for Operation
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Operation
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
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> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere
T: ?Sized,
Source§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the foreground set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red() and
green(), which have the same functionality but are
pithier.
§Example
Set foreground color to white using fg():
use yansi::{Paint, Color};
painted.fg(Color::White);Set foreground color to white using white().
use yansi::Paint;
painted.white();Source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
Source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
Source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
Source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
Source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
Source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
Source§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self with the background set to
value.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red() and
on_green(), which have the same functionality but
are pithier.
§Example
Set background color to red using fg():
use yansi::{Paint, Color};
painted.bg(Color::Red);Set background color to red using on_red().
use yansi::Paint;
painted.on_red();Source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
Source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
Source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
Source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Source§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling Attribute value.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold() and
underline(), which have the same functionality
but are pithier.
§Example
Make text bold using attr():
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);Make text bold using using bold().
use yansi::Paint;
painted.bold();Source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Source§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi Quirk value.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask() and
wrap(), which have the same functionality but are
pithier.
§Example
Enable wrapping using .quirk():
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);Enable wrapping using wrap().
use yansi::Paint;
painted.wrap();Source§fn clear(&self) -> Painted<&T>
👎Deprecated since 1.0.1: renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
fn clear(&self) -> Painted<&T>
renamed to resetting() due to conflicts with Vec::clear().
The clear() method will be removed in a future release.
Source§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the Condition value
applies. Replaces any previous condition.
See the crate level docs for more details.
§Example
Enable styling painted only when both stdout and stderr are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);