mirams/db_sqlite/model/
sqlite_ipv4.rs

1
2use crate::db_sqlite::SqliteConnection;
3use crate::types::{Error, ErrorKind};
4
5use crate::ipv4::Ipv4AssignmentStore;
6
7use r2d2_sqlite::rusqlite;
8
9#[derive(Debug, Clone)]
10pub struct SqliteIpv4AssignmentStore {
11    db: SqliteConnection,
12}
13
14impl SqliteIpv4AssignmentStore {
15    pub fn new(db: SqliteConnection) -> Self {
16        SqliteIpv4AssignmentStore { db }
17    }
18}
19
20impl Ipv4AssignmentStore for SqliteIpv4AssignmentStore {
21    fn get_space(&self, space_id: i32) -> Result<crate::ipv4::AssignmentSpaceIpv4, Error> {
22        let conn = self.db.get_conn()?;
23        let mut stmt = conn.prepare("SELECT id, name, description, space_visibility, ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 WHERE id = ?")?;
24        let mut rows = stmt.query(rusqlite::params![space_id])?;
25        let row = rows.next()?;
26        let space = match row {
27            Some(row) => {
28                let space = crate::ipv4::AssignmentSpaceIpv4 {
29                    id: row.get(0)?,
30                    name: row.get(1)?,
31                    description: row.get(2)?,
32                    space_visibility: row.get(3)?,
33                    ipv4_prefix: row.get(4)?,
34                    ipv4_prefix_len: row.get(5)?,
35                };
36                Some(space)
37            },
38            None => None,
39        };
40        let space = if let Some(space) = space {
41            space
42        } else {
43            return Err(Error::new(ErrorKind::NotFound,"Space not found".to_string()));
44        };
45        Ok(space)
46    }
47
48    fn get_spaces(&self) -> Result<Vec<crate::ipv4::AssignmentSpaceIpv4>, Error> {
49        let conn = self.db.get_conn()?;
50        let mut stmt = conn.prepare("SELECT id, name, description, space_visibility, ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 ORDER BY ipv4_prefix ASC")?;
51        let mut rows = stmt.query(rusqlite::params![])?;
52        let mut spaces = Vec::new();
53        while let Some(row) = rows.next()? {
54            let space = crate::ipv4::AssignmentSpaceIpv4 {
55                id: row.get(0)?,
56                name: row.get(1)?,
57                description: row.get(2)?,
58                space_visibility: row.get(3)?,
59                ipv4_prefix: row.get(4)?,
60                ipv4_prefix_len: row.get(5)?,
61            };
62            spaces.push(space);
63        }
64        Ok(spaces)
65    }
66
67    fn create_space(&self, space: &crate::ipv4::AssignmentSpaceIpv4) -> Result<i32, Error> {
68        use crate::ipv4::ipv4_network_address;
69        use crate::ipv4::ipv4_broadcast_address;
70
71        let mut conn = self.db.get_conn()?;
72        let tx = conn.transaction()?;
73
74        {
75            let ipv4_network = ipv4_network_address(space.ipv4_prefix, (space.ipv4_prefix_len & 255) as u8);
76            let ipv4_broadcast = ipv4_broadcast_address(space.ipv4_prefix, (space.ipv4_prefix_len & 255) as u8);
77            let mut stmt = tx.prepare(
78                "SELECT COUNT(*) FROM assignment_space_ipv4 
79                WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
80            )?;
81            let count: i32 = stmt.query_row(
82                rusqlite::params![
83                    ipv4_network, ipv4_broadcast,
84                ],
85                |row| row.get(0)
86            )?;
87
88            if count > 0 {
89                return Err(Error::new(ErrorKind::InvalidInput, "Overlapping space exists".to_string()));
90            }
91        }
92
93        for i in 0..space.ipv4_prefix_len {
94            let ipv4_network = ipv4_network_address(space.ipv4_prefix, (i & 255) as u8);
95            let mut stmt = tx.prepare(
96                "SELECT COUNT(*) FROM assignment_space_ipv4 
97                WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
98            )?;
99            let count: i32 = stmt.query_row(
100                rusqlite::params![
101                    ipv4_network, i,
102                ],
103                |row| row.get(0)
104            )?;
105
106            if count > 0 {
107                return Err(Error::new(ErrorKind::InvalidInput, "Overlapping space exists".to_string()));
108            }
109        }
110
111        {
112            let mut stmt = tx.prepare(
113                "INSERT INTO assignment_space_ipv4 (name, description, space_visibility, ipv4_prefix, ipv4_prefix_len) 
114                VALUES (?, ?, ?, ?, ?)"
115            )?;
116            stmt.execute(rusqlite::params![
117                space.name, space.description, space.space_visibility, space.ipv4_prefix, space.ipv4_prefix_len
118            ])?;
119        }
120        
121        tx.commit()?;
122        
123        let id = conn.last_insert_rowid();
124        Ok(id as i32)
125    }
126
127    fn update_space(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
128        let conn = self.db.get_conn()?;
129        let mut stmt = conn.prepare("UPDATE assignment_space_ipv4 SET name = ?, description = ? WHERE id = ?")?;
130        stmt.execute(rusqlite::params![name, description, id])?;
131        Ok(())
132    }
133
134    fn delete_space(&self, space_id: i32) -> Result<(), Error> {
135        let conn = self.db.get_conn()?;
136        let mut stmt = conn.prepare("DELETE FROM assignment_space_ipv4 WHERE id = ?")?;
137        stmt.execute(rusqlite::params![space_id])?;
138        Ok(())    
139    }
140
141    fn get_pool(&self, pool_id: i32) -> Result<crate::ipv4::AssignmentPoolIpv4, Error> {
142        let conn = self.db.get_conn()?;
143        let mut stmt = conn.prepare("SELECT id, name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id FROM assignment_pool_ipv4 WHERE id = ?")?;
144        let mut rows = stmt.query(rusqlite::params![pool_id])?;
145        let row = rows.next()?;
146        let pool = match row {
147            Some(row) => {
148            let pool = crate::ipv4::AssignmentPoolIpv4 {
149                id: row.get(0)?,
150                name: row.get(1)?,
151                description: row.get(2)?,
152                pool_visibility: row.get(3)?,
153                ipv4_prefix: row.get(4)?,
154                ipv4_prefix_len: row.get(5)?,
155                assignment_space_id: row.get(6)?,
156            };
157            Some(pool)
158            },
159            None => None,
160        };
161        let pool = if let Some(pool) = pool {
162            pool
163        } else {
164            return Err(Error::new(ErrorKind::NotFound, "Pool not found".to_string()));
165        };
166        Ok(pool)
167    }
168
169    fn get_pools(&self, space_id: i32) -> Result<Vec<crate::ipv4::AssignmentPoolIpv4>, Error> {
170        let conn = self.db.get_conn()?;
171        let mut stmt = conn.prepare("SELECT id, name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id FROM assignment_pool_ipv4 WHERE assignment_space_id = ? ORDER BY ipv4_prefix ASC")?;
172        let mut rows = stmt.query(rusqlite::params![space_id])?;
173        let mut pools = Vec::new();
174        while let Some(row) = rows.next()? {
175            let pool = crate::ipv4::AssignmentPoolIpv4 {
176                id: row.get(0)?,
177                name: row.get(1)?,
178                description: row.get(2)?,
179                pool_visibility: row.get(3)?,
180                ipv4_prefix: row.get(4)?,
181                ipv4_prefix_len: row.get(5)?,
182                assignment_space_id: row.get(6)?,
183            };
184            pools.push(pool);
185        }
186        Ok(pools)
187    }
188
189    fn create_pool(&self, pool: &crate::ipv4::AssignmentPoolIpv4) -> Result<i32, Error> {
190        use crate::ipv4::ipv4_network_address;
191        use crate::ipv4::ipv4_broadcast_address;
192
193        let mut conn = self.db.get_conn()?;
194        let tx = conn.transaction()?;
195        {
196            let pool_network = ipv4_network_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
197            let pool_broadcast = ipv4_broadcast_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
198
199            let mut stmt = tx.prepare(
200            "SELECT ipv4_prefix, ipv4_prefix_len FROM assignment_space_ipv4 WHERE id = ?"
201            )?;
202            let mut rows = stmt.query(rusqlite::params![pool.assignment_space_id])?;
203            let row = rows.next()?;
204            let (space_network, space_broadcast) = match row {
205                Some(row) => {
206                    let space_prefix = row.get(0)?;
207                    let space_prefix_len: u8 = row.get(1)?;
208                    let space_network = ipv4_network_address(space_prefix, (space_prefix_len & 255) as u8);
209                    let space_broadcast = ipv4_broadcast_address(space_prefix, (space_prefix_len & 255) as u8);
210                    (space_network, space_broadcast)
211                },
212                None => return Err(Error::new(ErrorKind::NotFound, "Parent space not found".to_string())),
213            };
214
215            if pool_network < space_network || pool_broadcast > space_broadcast {
216            return Err(Error::new(ErrorKind::InvalidInput, "Pool is not contained within the parent space".to_string()));
217            }
218        }
219
220        {
221            let ipv4_network = ipv4_network_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
222            let ipv4_broadcast = ipv4_broadcast_address(pool.ipv4_prefix, (pool.ipv4_prefix_len & 255) as u8);
223            let mut stmt = tx.prepare(
224                "SELECT COUNT(*) FROM assignment_pool_ipv4 
225                WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
226            )?;
227            let count: i32 = stmt.query_row(
228                rusqlite::params![
229                    ipv4_network, ipv4_broadcast,
230                ],
231                |row| row.get(0)
232            )?;
233
234            if count > 0 {
235                return Err(Error::new(ErrorKind::InvalidInput, "Overlapping pool exists".to_string()));
236            }
237        }
238
239        for i in 0..pool.ipv4_prefix_len {
240            let ipv4_network = ipv4_network_address(pool.ipv4_prefix, (i & 255) as u8);
241            let mut stmt = tx.prepare(
242                "SELECT COUNT(*) FROM assignment_pool_ipv4 
243                WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
244            )?;
245            let count: i32 = stmt.query_row(
246                rusqlite::params![
247                    ipv4_network, i,
248                ],
249                |row| row.get(0)
250            )?;
251
252            if count > 0 {
253                return Err(Error::new(ErrorKind::InvalidInput, "Overlapping pool exists".to_string()));
254            }
255        }
256
257        {
258            let mut stmt = tx.prepare(
259                "INSERT INTO assignment_pool_ipv4 (name, description, pool_visibility, ipv4_prefix, ipv4_prefix_len, assignment_space_id) 
260                VALUES (?, ?, ?, ?, ?, ?)"
261            )?;
262            stmt.execute(rusqlite::params![
263                pool.name, pool.description, pool.pool_visibility, pool.ipv4_prefix, pool.ipv4_prefix_len, pool.assignment_space_id
264            ])?;
265        }
266        
267        tx.commit()?;
268        
269        let id = conn.last_insert_rowid();
270        Ok(id as i32)
271    }
272
273    fn update_pool(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
274        let conn = self.db.get_conn()?;
275        let mut stmt = conn.prepare("UPDATE assignment_pool_ipv4 SET name = ?, description = ? WHERE id = ?")?;
276        stmt.execute(rusqlite::params![name, description, id])?;
277        Ok(())
278    }
279
280    fn delete_pool(&self, pool_id: i32) -> Result<(), Error> {
281        let conn = self.db.get_conn()?;
282        let mut stmt = conn.prepare("DELETE FROM assignment_pool_ipv4 WHERE id = ?")?;
283        stmt.execute(rusqlite::params![pool_id])?;
284        Ok(())
285    }
286
287    fn get_assignment(&self, assignment_id: i32) -> Result<crate::ipv4::AssignmentIpv4, Error> {
288        let conn = self.db.get_conn()?;
289        let mut stmt = conn.prepare("SELECT id, name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility FROM assignment_ipv4 WHERE id = ?")?;
290        let mut rows = stmt.query(rusqlite::params![assignment_id])?;
291        let row = rows.next()?;
292        let assignment = match row {
293            Some(row) => {
294                let assignment = crate::ipv4::AssignmentIpv4 {
295                    id: row.get(0)?,
296                    name: row.get(1)?,
297                    description: row.get(2)?,
298                    ipv4_prefix: row.get(3)?,
299                    ipv4_prefix_len: row.get(4)?,
300                    assignment_pool_id: row.get(5)?,
301                    assignment_visibility: row.get(6)?,
302                };
303                Some(assignment)
304            },
305            None => None,
306        };
307        let assignment = if let Some(assignment) = assignment {
308            assignment
309        } else {
310            return Err(Error::new(ErrorKind::NotFound, "Assignment not found".to_string()));
311        };
312        Ok(assignment)
313    }
314
315    fn get_assignments(&self, pool_id: i32) -> Result<Vec<crate::ipv4::AssignmentIpv4>, Error> {
316        let conn = self.db.get_conn()?;
317        let mut stmt = conn.prepare("SELECT id, name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility FROM assignment_ipv4 WHERE assignment_pool_id = ? ORDER BY ipv4_prefix ASC")?;
318        let mut rows = stmt.query(rusqlite::params![pool_id])?;
319        let mut assignments = Vec::new();
320        while let Some(row) = rows.next()? {
321            let assignment = crate::ipv4::AssignmentIpv4 {
322                id: row.get(0)?,
323                name: row.get(1)?,
324                description: row.get(2)?,
325                ipv4_prefix: row.get(3)?,
326                ipv4_prefix_len: row.get(4)?,
327                assignment_pool_id: row.get(5)?,
328                assignment_visibility: row.get(6)?,
329            };
330            assignments.push(assignment);
331        }
332        Ok(assignments)
333    }
334
335    fn create_assignment(&self, assignment: &crate::ipv4::AssignmentIpv4) -> Result<i32, Error> {
336        use crate::ipv4::ipv4_network_address;
337        use crate::ipv4::ipv4_broadcast_address;
338
339        let mut conn = self.db.get_conn()?;
340        let tx = conn.transaction()?;
341        {
342            let assignment_network = ipv4_network_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
343            let assignment_broadcast = ipv4_broadcast_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
344
345            let mut stmt = tx.prepare(
346            "SELECT ipv4_prefix, ipv4_prefix_len FROM assignment_pool_ipv4 WHERE id = ?"
347            )?;
348            let mut rows = stmt.query(rusqlite::params![assignment.assignment_pool_id])?;
349            let row = rows.next()?;
350            let (pool_network, pool_broadcast) = match row {
351                Some(row) => {
352                    let pool_prefix = row.get(0)?;
353                    let pool_prefix_len: u8 = row.get(1)?;
354                    let pool_network = ipv4_network_address(pool_prefix, (pool_prefix_len & 255) as u8);
355                    let pool_broadcast = ipv4_broadcast_address(pool_prefix, (pool_prefix_len & 255) as u8);
356                    (pool_network, pool_broadcast)
357                },
358                None => return Err(Error::new(ErrorKind::NotFound, "Parent pool not found".to_string())),
359            };
360
361            if assignment_network < pool_network || assignment_broadcast > pool_broadcast {
362            return Err(Error::new(ErrorKind::InvalidInput, "Assignment is not contained within the parent pool".to_string()));
363            }
364        }
365
366        {
367            let ipv4_network = ipv4_network_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
368            let ipv4_broadcast = ipv4_broadcast_address(assignment.ipv4_prefix, (assignment.ipv4_prefix_len & 255) as u8);
369            let mut stmt = tx.prepare(
370                "SELECT COUNT(*) FROM assignment_ipv4 
371                WHERE ipv4_prefix >= ? AND ipv4_prefix <= ?"
372            )?;
373            let count: i32 = stmt.query_row(
374                rusqlite::params![
375                    ipv4_network, ipv4_broadcast,
376                ],
377                |row| row.get(0)
378            )?;
379
380            if count > 0 {
381                return Err(Error::new(ErrorKind::InvalidInput, "overlapping assingment exists".to_string()));
382            }
383        }
384
385        for i in 0..assignment.ipv4_prefix_len {
386            let ipv4_network = ipv4_network_address(assignment.ipv4_prefix, (i & 255) as u8);
387            let mut stmt = tx.prepare(
388                "SELECT COUNT(*) FROM assignment_ipv4 
389                WHERE ipv4_prefix = ? AND ipv4_prefix_len = ?"
390            )?;
391            let count: i32 = stmt.query_row(
392                rusqlite::params![
393                    ipv4_network, i,
394                ],
395                |row| row.get(0)
396            )?;
397
398            if count > 0 {
399                return Err(Error::new(ErrorKind::InvalidInput, "Overlapping assignment exists".to_string()));
400            }
401        }
402
403        {
404            let mut stmt = tx.prepare(
405                "INSERT INTO assignment_ipv4 (name, description, ipv4_prefix, ipv4_prefix_len, assignment_pool_id, assignment_visibility) 
406                VALUES (?, ?, ?, ?, ?, ?)"
407            )?;
408            stmt.execute(rusqlite::params![
409                assignment.name, assignment.description, assignment.ipv4_prefix, assignment.ipv4_prefix_len, assignment.assignment_pool_id, assignment.assignment_visibility
410            ])?;
411        }
412
413        tx.commit()?;
414
415        let id = conn.last_insert_rowid();
416        Ok(id as i32)
417    }
418
419    fn update_assignment(&self, id: i32, name: &str, description: &str) -> Result<(), Error> {
420        let conn = self.db.get_conn()?;
421        let mut stmt = conn.prepare("UPDATE assignment_ipv4 SET name = ?, description = ? WHERE id = ?")?;
422        stmt.execute(rusqlite::params![name, description, id])?;
423        Ok(())
424    }
425
426    fn delete_assignment(&self, assignment_id: i32) -> Result<(), Error> {
427        let conn = self.db.get_conn()?;
428        let mut stmt = conn.prepare("DELETE FROM assignment_ipv4 WHERE id = ?")?;
429        stmt.execute(rusqlite::params![assignment_id])?;
430        Ok(())
431    }
432}
433