Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+156
View File
@@ -0,0 +1,156 @@
use super::{alter, history, schema};
use crate::database::{Column, Kind, Migration, Plan, Sql, Statement};
use std::collections::BTreeMap;
mod live;
mod registry;
const EMPTY: Plan = Plan {
create: Sql::same(""),
indexes: Sql::same(""),
postgres_columns: &[],
renames: &[],
migrations: &[],
seeds: &[],
seed_revision: "empty",
};
const fn column(name: &'static str, kind: &'static str) -> Column {
Column {
name,
kind,
default: None,
nullable: false,
generated: false,
constraints: &[],
}
}
const fn step(
name: &'static str,
revision: &'static str,
drops: &'static [&'static str],
) -> Migration {
Migration {
name,
revision,
drops,
before: &[],
after: &[],
}
}
#[test]
fn migration_history_is_an_immutable_contiguous_prefix() {
let plan = const {
Plan {
migrations: &[step("first", "one", &[]), step("second", "two", &[])],
..EMPTY
}
};
assert_eq!(history::validate(&[], &plan).unwrap(), 0);
assert_eq!(
history::validate(&[(0, "first".into(), "one".into())], &plan).unwrap(),
1
);
for records in [
vec![(1, "first".into(), "one".into())],
vec![(0, "second".into(), "two".into())],
vec![(0, "first".into(), "modified".into())],
vec![
(0, "first".into(), "one".into()),
(2, "second".into(), "two".into()),
],
] {
assert_eq!(
history::validate(&records, &plan).unwrap_err().kind,
Kind::Migration
);
}
assert_eq!(
history::validate(&[(0, "first".into(), "one".into())], &EMPTY)
.unwrap_err()
.kind,
Kind::Migration
);
}
#[test]
fn column_mapping_requires_exact_unused_drops_and_unambiguous_renames() {
let old = BTreeMap::from([
("id".into(), "bigint".into()),
("name".into(), "text".into()),
("removed".into(), "bigint".into()),
]);
let plan = const {
Plan {
postgres_columns: &[
column("id", "bigint"),
column("title", "text"),
column("new", "uuid"),
],
renames: &[("title", "name")],
migrations: &[step("remove", "one", &["removed"])],
..EMPTY
}
};
assert_eq!(
alter::sources(&old, &plan, 0).unwrap(),
[Some("id"), Some("name"), None]
);
assert_eq!(
alter::sources(&old, &plan, 1).unwrap_err().kind,
Kind::Migration
);
let mut ambiguous = old.clone();
ambiguous.insert("title".into(), "text".into());
assert_eq!(
alter::sources(&ambiguous, &plan, 0).unwrap_err().kind,
Kind::Migration
);
let missing = Plan {
renames: &[("title", "absent")],
..plan
};
assert_eq!(
alter::sources(&old, &missing, 0).unwrap_err().kind,
Kind::Migration
);
let duplicated = Plan {
postgres_columns: const {
&[
column("id", "bigint"),
column("title", "text"),
column("other", "text"),
]
},
renames: &[("title", "name"), ("other", "name")],
..missing
};
assert_eq!(
alter::sources(&old, &duplicated, 0).unwrap_err().kind,
Kind::Migration
);
}
#[test]
fn only_supported_storage_conversions_reach_postgres_ddl() {
for (old, next) in [
("text", "text"),
("numeric(6,2)", "numeric(8,3)"),
("numeric(8,3)", "numeric(6,2)"),
] {
assert!(alter::conversion(old, next));
}
for (old, next) in [
("double precision", "bigint"),
("bigint", "double precision"),
("text", "uuid"),
("bigint", "numeric(8,2)"),
("bytea", "text"),
("numeric(6,2)", "numeric(3,4)"),
] {
assert!(!alter::conversion(old, next));
}
assert_eq!(schema::quote("a\"b"), "\"a\"\"b\"");
}