good_ormning/sqlite/graph/
field.rs1use std::collections::{
2 HashSet,
3 HashMap,
4};
5use crate::{
6 sqlite::{
7 schema::field::Field,
8 types::{
9 to_sql_type,
10 Type,
11 },
12 query::{
13 utils::SqliteQueryCtx,
14 expr::{
15 ExprType,
16 Binding,
17 check_same,
18 },
19 },
20 },
21 graphmigrate::Comparison,
22 utils::Tokens,
23};
24use super::{
25 GraphId,
26 utils::{
27 SqliteNodeData,
28 SqliteMigrateCtx,
29 SqliteNodeDataDispatch,
30 },
31 Node,
32};
33
34#[derive(Clone)]
35pub(crate) struct NodeField_ {
36 pub def: Field,
37}
38
39impl NodeField_ {
40 pub fn compare(&self, old: &Self, created: &HashSet<GraphId>) -> Comparison {
41 if created.contains(&GraphId::Table(self.def.table.0.schema_id.clone())) {
42 return Comparison::Recreate;
43 }
44 let t = &self.def.type_.type_;
45 let old_t = &old.def.type_.type_;
46 if self.def.id != old.def.id || t.opt != old_t.opt || t.type_.type_ != old_t.type_.type_ {
47 Comparison::Update
48 } else {
49 Comparison::DoNothing
50 }
51 }
52
53 fn display_path(&self) -> rpds::Vector<String> {
54 rpds::vector![self.def.to_string()]
55 }
56}
57
58impl SqliteNodeData for NodeField_ {
59 fn update(&self, ctx: &mut SqliteMigrateCtx, old: &Self) {
60 if self.def.id != old.def.id {
61 let mut stmt = Tokens::new();
62 stmt
63 .s("alter table")
64 .id(&self.def.table.0.id)
65 .s("rename column")
66 .id(&old.def.id)
67 .s("to")
68 .id(&self.def.id);
69 ctx.statements.push(stmt.to_string());
70 }
71 let t = &self.def.type_.type_;
72 let old_t = &old.def.type_.type_;
73 if t.opt != old_t.opt {
74 ctx.errs.err(&self.display_path(), format!("Column optionality cannot be changed in sqlite"));
75 }
76 if t.type_.type_ != old_t.type_.type_ {
77 ctx.errs.err(&self.display_path(), format!("Column types cannot be changed in sqlite"));
78 }
79 }
80}
81
82impl SqliteNodeDataDispatch for NodeField_ {
83 fn create(&self, ctx: &mut SqliteMigrateCtx) {
84 let path = self.display_path();
85 if &self.def.schema_id.0 == "rowid" {
86 return;
87 }
88 let mut stmt = Tokens::new();
89 stmt
90 .s("alter table")
91 .id(&self.def.table.0.id)
92 .s("add column")
93 .id(&self.def.id)
94 .s(to_sql_type(&self.def.type_.type_.type_.type_));
95 if !self.def.type_.type_.opt {
96 if let Some(d) = &self.def.type_.migration_default {
97 stmt.s("not null default");
98 let mut qctx = SqliteQueryCtx::new(ctx.errs.clone(), HashMap::new());
99 let e_res = d.build(&mut qctx, &path, &HashMap::new());
100 check_same(&mut qctx.errs, &path, &ExprType(vec![(Binding::empty(), Type {
101 type_: self.def.type_.type_.type_.clone(),
102 opt: false,
103 array: false,
104 })]), &e_res.0);
105 if !qctx.rust_args.is_empty() {
106 qctx
107 .errs
108 .err(
109 &path,
110 format!(
111 "Default expressions must not have any parameters, but this has {} parameters",
112 qctx.rust_args.len()
113 ),
114 );
115 }
116 stmt.s(&e_res.1.to_string());
117 } else {
118 ctx.errs.err(&path, format!("New column missing default"));
119 }
120 }
121 ctx.statements.push(stmt.to_string());
122 }
123
124 fn delete(&self, ctx: &mut SqliteMigrateCtx) {
125 if &self.def.schema_id.0 == "rowid" {
126 return;
127 }
128 ctx
129 .statements
130 .push(
131 Tokens::new().s("alter table").id(&self.def.table.id).s("drop column").id(&self.def.id).to_string(),
132 );
133 }
134
135 fn create_coalesce(&mut self, other: Node) -> Option<Node> {
136 Some(other)
137 }
138
139 fn delete_coalesce(&mut self, other: Node) -> Option<Node> {
140 Some(other)
141 }
142}