Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ pg = []
sqlite = []

[dependencies]
chrono = { version = "0.4", optional = true }
jiff = { version = "0.2", optional = true }
chrono = { version = "0.4", optional = true, features = ["serde"] }
jiff = { version = "0.2", optional = true, features = ["serde"] }
enum_dispatch = "0.3"
flowcontrol = "0.2.2"
genemichaels-lib = "0.5.0-pre3"
Expand All @@ -28,6 +28,7 @@ rpds = "1"
samevariant = "0.0"
stable-hash = "0.4"
syn = "2"
serde = { version = "1", features = ["derive"] }

[workspace]
members = ["integration_tests", "runtime"]
Expand Down
499 changes: 189 additions & 310 deletions integration_tests/build_pg.rs

Large diffs are not rendered by default.

564 changes: 198 additions & 366 deletions integration_tests/build_sqlite.rs

Large diffs are not rendered by default.

48 changes: 28 additions & 20 deletions src/pg/graph/constraint.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,42 @@
use std::collections::HashSet;
use std::collections::{
HashSet,
HashMap,
};
use crate::{
graphmigrate::Comparison,
pg::schema::{
constraint::{
Constraint,
ConstraintType,
SchemaConstraintId,
},
table::SchemaTableId,
field::SchemaFieldId,
},
utils::Tokens,
};
use super::{
utils::{
NodeDataDispatch,
PgMigrateCtx,
NodeData,
},
GraphId,
NodeDataDispatch,
NodeData,
Node,
utils::PgMigrateCtx,
};

#[derive(Clone)]
pub(crate) struct NodeConstraint_ {
pub table_schema_id: SchemaTableId,
pub table_sql_name: String,
pub schema_id: SchemaConstraintId,
pub def: Constraint,
pub local_field_sql_names: HashMap<SchemaFieldId, String>,
pub remote_table_sql_name: Option<String>,
pub remote_field_sql_names: HashMap<SchemaFieldId, String>,
}

impl NodeConstraint_ {
pub fn compare(&self, old: &Self, created: &HashSet<GraphId>) -> Comparison {
if created.contains(&GraphId::Table(self.def.table.schema_id.clone())) || self.def.type_ != old.def.type_ {
if created.contains(&GraphId::Table(self.table_schema_id.clone())) || self.def.type_ != old.def.type_ {
Comparison::Recreate
} else if self.def.id != old.def.id {
Comparison::Update
Expand All @@ -43,34 +53,32 @@ impl NodeDataDispatch for NodeConstraint_ {

fn create(&self, ctx: &mut PgMigrateCtx) {
let mut stmt = Tokens::new();
stmt.s("alter table").id(&self.def.table.id).s("add constraint").id(&self.def.id);
stmt.s("alter table").id(&self.table_sql_name).s("add constraint").id(&self.def.id);
match &self.def.type_ {
ConstraintType::PrimaryKey(x) => {
stmt.s("primary key (").f(|t| {
for (i, field) in x.fields.iter().enumerate() {
for (i, field_schema_id) in x.fields.iter().enumerate() {
if i > 0 {
t.s(",");
}
t.id(&field.id);
t.id(self.local_field_sql_names.get(field_schema_id).unwrap());
}
}).s(")");
},
ConstraintType::ForeignKey(x) => {
stmt.s("foreign key (").f(|t| {
for (i, pair) in x.fields.iter().enumerate() {
for (i, (local_field, _)) in x.fields.iter().enumerate() {
if i > 0 {
t.s(",");
}
t.id(&pair.0.id);
t.id(self.local_field_sql_names.get(local_field).unwrap());
}
}).s(") references ").f(|t| {
for (i, pair) in x.fields.iter().enumerate() {
if i == 0 {
t.id(&pair.1.table.id).s("(");
} else {
}).s(") references ").id(self.remote_table_sql_name.as_ref().unwrap()).s("(").f(|t| {
for (i, (_, remote_field)) in x.fields.iter().enumerate() {
if i > 0 {
t.s(",");
}
t.id(&pair.1.id);
t.id(self.remote_field_sql_names.get(remote_field).unwrap());
}
}).s(")");
},
Expand All @@ -88,7 +96,7 @@ impl NodeDataDispatch for NodeConstraint_ {
.push(
Tokens::new()
.s("alter table")
.id(&self.def.table.id)
.id(&self.table_sql_name)
.s("drop constraint")
.id(&self.def.id)
.to_string(),
Expand All @@ -102,7 +110,7 @@ impl NodeData for NodeConstraint_ {
let mut stmt = Tokens::new();
stmt
.s("alter table")
.id(&self.def.table.0.id)
.id(&self.table_sql_name)
.s("rename constraint")
.id(&old.def.id)
.s("to")
Expand Down
68 changes: 47 additions & 21 deletions src/pg/graph/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,28 @@ use std::collections::{
};
use crate::{
pg::{
schema::field::Field,
schema::{
field::{
Field,
SchemaFieldId,
FieldRef,
},
table::SchemaTableId,
},
types::{
to_sql_type,
Type,
SimpleSimpleType,
},
PgQueryCtx,
PgTableInfo,
PgFieldInfo,
query::{
utils::PgQueryCtx,
expr::{
ExprType,
ExprValName,
check_same,
check_general_same,
Expr,
},
},
},
Expand All @@ -24,22 +34,23 @@ use crate::{
};
use super::{
GraphId,
utils::{
NodeData,
PgMigrateCtx,
NodeDataDispatch,
},
NodeDataDispatch,
NodeData,
Node,
utils::PgMigrateCtx,
};

#[derive(Clone)]
pub(crate) struct NodeField_ {
pub table_schema_id: SchemaTableId,
pub table_id: String, // SQL name
pub schema_id: SchemaFieldId,
pub def: Field,
}

impl NodeField_ {
pub fn compare(&self, old: &Self, created: &HashSet<GraphId>) -> Comparison {
if created.contains(&GraphId::Table(self.def.table.0.schema_id.clone())) {
if created.contains(&GraphId::Table(self.table_schema_id.clone())) {
return Comparison::Recreate;
}
let t = &self.def.type_.type_;
Expand All @@ -52,7 +63,7 @@ impl NodeField_ {
}

fn display_path(&self) -> rpds::Vector<String> {
rpds::vector![self.def.to_string()]
rpds::vector![format!("{}.{} ({}.{})", self.table_id, self.def.id, self.table_schema_id, self.schema_id)]
}
}

Expand All @@ -62,7 +73,7 @@ impl NodeData for NodeField_ {
let mut stmt = Tokens::new();
stmt
.s("alter table")
.id(&self.def.table.0.id)
.id(&self.table_id)
.s("rename column")
.id(&old.def.id)
.s("to")
Expand All @@ -77,7 +88,7 @@ impl NodeData for NodeField_ {
.push(
Tokens::new()
.s("alter table")
.id(&self.def.table.id)
.id(&self.table_id)
.s("alter column")
.id(&self.def.id)
.s("drop not null")
Expand All @@ -89,7 +100,7 @@ impl NodeData for NodeField_ {
.push(
Tokens::new()
.s("alter table")
.id(&self.def.table.id)
.id(&self.table_id)
.s("alter column")
.id(&self.def.id)
.s("set not null")
Expand All @@ -102,7 +113,7 @@ impl NodeData for NodeField_ {
.push(
Tokens::new()
.s("alter table")
.id(&self.def.table.id)
.id(&self.table_id)
.s("alter column")
.id(&self.def.id)
.s("set type")
Expand All @@ -122,17 +133,32 @@ impl NodeDataDispatch for NodeField_ {
let mut stmt = Tokens::new();
stmt
.s("alter table")
.id(&self.def.table.0.id)
.id(&self.table_id)
.s("add column")
.id(&self.def.id)
.s(to_sql_type(&self.def.type_.type_.type_.type_));
if !self.def.type_.type_.opt {
if let Some(d) = &self.def.type_.migration_default {
stmt.s("not null default");
let qctx_fields = HashMap::new();
let mut qctx = PgQueryCtx::new(ctx.errs.clone(), &qctx_fields);
let e_res = d.build(&mut qctx, &path, &HashMap::new());
check_same(&mut qctx.errs, &path, &ExprType(vec![(ExprValName::empty(), Type {
let mut qctx_tables = HashMap::new();
// Create a dummy table info for validation
let mut fields = HashMap::new();
let field_ref = FieldRef {
table_id: self.table_schema_id.clone(),
field_id: self.schema_id.clone(),
};
fields.insert(field_ref, PgFieldInfo {
sql_name: self.def.id.clone(),
type_: self.def.type_.type_.clone(),
});
qctx_tables.insert(crate::pg::schema::table::TableRef(self.table_schema_id.clone()), PgTableInfo {
sql_name: self.table_id.clone(),
fields: fields,
});
let mut qctx = PgQueryCtx::new(ctx.errs.clone(), &qctx_tables);
let expr: Expr = d.clone().into();
let e_res = expr.build(&mut qctx, &path, &HashMap::new());
check_general_same(&mut qctx, &path, &ExprType(vec![(ExprValName::empty(), Type {
type_: self.def.type_.type_.type_.clone(),
opt: false,
})]), &e_res.0);
Expand All @@ -159,7 +185,7 @@ impl NodeDataDispatch for NodeField_ {
.push(
Tokens::new()
.s("alter table")
.id(&self.def.table.id)
.id(&self.table_id)
.s("alter column")
.id(&self.def.id)
.s("drop default")
Expand All @@ -172,7 +198,7 @@ impl NodeDataDispatch for NodeField_ {
ctx
.statements
.push(
Tokens::new().s("alter table").id(&self.def.table.id).s("drop column").id(&self.def.id).to_string(),
Tokens::new().s("alter table").id(&self.table_id).s("drop column").id(&self.def.id).to_string(),
);
}

Expand Down
34 changes: 23 additions & 11 deletions src/pg/graph/index.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
use std::collections::HashSet;
use std::collections::{
HashSet,
HashMap,
};
use crate::{
graphmigrate::Comparison,
utils::Tokens,
pg::schema::index::Index,
pg::schema::{
index::{
Index,
SchemaIndexId,
},
table::SchemaTableId,
field::SchemaFieldId,
},
};
use super::{
utils::{
NodeDataDispatch,
PgMigrateCtx,
NodeData,
},
GraphId,
NodeDataDispatch,
NodeData,
Node,
utils::PgMigrateCtx,
};

#[derive(Clone)]
pub(crate) struct NodeIndex_ {
pub table_schema_id: SchemaTableId,
pub table_id: String, // SQL name
pub schema_id: SchemaIndexId,
pub def: Index,
pub field_sql_names: HashMap<SchemaFieldId, String>,
}

impl NodeIndex_ {
pub fn compare(&self, old: &Self, created: &HashSet<GraphId>) -> Comparison {
if created.contains(&GraphId::Table(self.def.table.schema_id.clone())) || self.def.fields != old.def.fields {
if created.contains(&GraphId::Table(self.table_schema_id.clone())) || self.def.fields != old.def.fields {
Comparison::Recreate
} else if self.def.id != old.def.id {
Comparison::Update
Expand All @@ -41,12 +53,12 @@ impl NodeDataDispatch for NodeIndex_ {
if self.def.unique {
t.s("unique");
}
}).s("index").id(&self.def.id).s("on").id(&self.def.table.id).s("(").f(|t| {
for (i, field) in self.def.fields.iter().enumerate() {
}).s("index").id(&self.def.id).s("on").id(&self.table_id).s("(").f(|t| {
for (i, field_schema_id) in self.def.fields.iter().enumerate() {
if i > 0 {
t.s(",");
}
t.id(&field.id);
t.id(self.field_sql_names.get(field_schema_id).unwrap());
}
}).s(")").to_string());
}
Expand Down
Loading