good_ormning/sqlite/graph/
table.rs1use std::collections::HashSet;
2use crate::{
3 sqlite::{
4 schema::{
5 table::Table,
6 field::Field,
7 constraint::{
8 Constraint,
9 ConstraintType,
10 },
11 },
12 types::to_sql_type,
13 },
14 graphmigrate::Comparison,
15 utils::Tokens,
16};
17use super::{
18 utils::{
19 SqliteNodeData,
20 SqliteMigrateCtx,
21 SqliteNodeDataDispatch,
22 },
23 Node,
24 GraphId,
25};
26
27#[derive(Clone)]
28pub struct NodeTable_ {
29 pub def: Table,
30 pub fields: Vec<Field>,
31 pub constraints: Vec<Constraint>,
32}
33
34impl NodeTable_ {
35 pub fn compare(&self, old: &Self, _created: &HashSet<GraphId>) -> Comparison {
36 if old.def.id != self.def.id {
37 Comparison::Update
38 } else {
39 Comparison::DoNothing
40 }
41 }
42}
43
44impl SqliteNodeData for NodeTable_ {
45 fn update(&self, ctx: &mut SqliteMigrateCtx, old: &Self) {
46 if old.def.id != self.def.id {
47 let mut stmt = Tokens::new();
48 stmt.s("alter table").id(&old.def.id).s("rename to").id(&self.def.id);
49 ctx.statements.push(stmt.to_string());
50 }
51 }
52}
53
54impl SqliteNodeDataDispatch for NodeTable_ {
55 fn create_coalesce(&mut self, other: Node) -> Option<Node> {
56 match other {
57 Node::Field(f) if f.def.table == self.def => {
58 self.fields.push(f.def.clone());
59 None
60 },
61 Node::Constraint(c) if c.def.table == self.def => {
62 self.constraints.push(c.def.clone());
63 None
64 },
65 other => Some(other),
66 }
67 }
68
69 fn delete_coalesce(&mut self, other: Node) -> Option<Node> {
70 match other {
71 Node::Field(f) if f.def.table == self.def => None,
72 Node::Constraint(e) if e.def.table == self.def => None,
73 Node::Index(e) if e.def.table == self.def => None,
74 other => Some(other),
75 }
76 }
77
78 fn create(&self, ctx: &mut SqliteMigrateCtx) {
79 let mut stmt = Tokens::new();
80 stmt.s("create table").id(&self.def.id).s("(");
81 let mut i = 0usize;
82 for f in &self.fields {
83 if f.id == "rowid" {
84 continue;
85 }
86 if i > 0 {
87 stmt.s(",");
88 }
89 i += 1;
90 stmt.id(&f.id).s(to_sql_type(&f.0.type_.type_.type_.type_));
91 if !f.type_.type_.opt {
92 stmt.s("not null");
93 }
94 }
95 for c in &self.constraints {
96 if i > 0 {
97 stmt.s(",");
98 }
99 i += 1;
100 stmt.s("constraint").id(&c.id);
101 match &c.type_ {
102 ConstraintType::PrimaryKey(x) => {
103 stmt.s("primary key (").f(|t| {
104 for (i, field) in x.fields.iter().enumerate() {
105 if i > 0 {
106 t.s(",");
107 }
108 t.id(&field.id);
109 }
110 }).s(")");
111 },
112 ConstraintType::ForeignKey(x) => {
113 stmt.s("foreign key (").f(|t| {
114 for (i, pair) in x.fields.iter().enumerate() {
115 if i > 0 {
116 t.s(",");
117 }
118 t.id(&pair.0.id);
119 }
120 }).s(") references ").f(|t| {
121 for (i, pair) in x.fields.iter().enumerate() {
122 if i == 0 {
123 t.id(&pair.1.table.id).s("(");
124 } else {
125 t.s(",");
126 }
127 t.id(&pair.1.id);
128 }
129 }).s(")");
130 },
131 }
132 }
133 stmt.s(")");
134 ctx.statements.push(stmt.to_string());
135 }
136
137 fn delete(&self, ctx: &mut SqliteMigrateCtx) {
138 ctx.statements.push(Tokens::new().s("drop table").id(&self.def.id).to_string());
139 }
140}