1#![forbid(unsafe_code, clippy::unwrap_used)]
2#![allow(clippy::needless_return)]
3#![warn(clippy::await_holding_lock, clippy::inefficient_to_string)]
4
5pub mod error;
6pub mod file;
7pub mod json_schema;
8pub mod metadata;
9pub mod registry;
10pub mod sqlite;
11
12pub use error::Error;
13pub use file::{FileUpload, FileUploadInput, FileUploads};
14pub use sqlite::QualifiedName;
15
16pub struct QualifiedNameEscaped(String);
17
18impl QualifiedNameEscaped {
19 pub fn new(name: &QualifiedName) -> Self {
20 return Self(name.escaped_string());
21 }
22}
23
24impl From<QualifiedName> for QualifiedNameEscaped {
25 fn from(name: QualifiedName) -> Self {
26 return Self::new(&name);
27 }
28}
29
30impl From<&QualifiedName> for QualifiedNameEscaped {
31 fn from(name: &QualifiedName) -> Self {
32 return Self::new(name);
33 }
34}
35
36impl std::fmt::Display for QualifiedNameEscaped {
37 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38 return self.0.fmt(f);
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn test_qualified_name() {
48 assert!(QualifiedName::parse(r#"test"; DROP TABLE students;""#).is_err());
49
50 let simple = QualifiedName::parse("test").unwrap();
51 assert_eq!(
52 simple,
53 QualifiedName {
54 name: "test".to_string(),
55 database_schema: None,
56 }
57 );
58 assert_eq!(QualifiedNameEscaped::new(&simple).0, r#""test""#);
59
60 let composite = QualifiedName::parse("db.test.bar").unwrap();
61 assert_eq!(
62 composite,
63 QualifiedName {
64 name: "test.bar".to_string(),
65 database_schema: Some("db".to_string()),
66 }
67 );
68 assert_eq!(
69 QualifiedNameEscaped::new(&composite).0,
70 r#""db"."test.bar""#
71 );
72
73 let unescape = QualifiedName::parse("[db].'test'").unwrap();
74 assert_eq!(
75 unescape,
76 QualifiedName {
77 name: "test".to_string(),
78 database_schema: Some("db".to_string()),
79 }
80 );
81 }
82}