datasources_postgres/
lib.rs1mod alter_table_statement_renderer;
2mod bind;
3mod command;
4mod connection;
5mod converters;
6mod create_table_statement_renderer;
7mod create_trigger_statement_renderer;
8mod drop_routine_statement_renderer;
9mod driver;
10mod identity_insert_statement_renderer;
11mod default_value_converter;
12mod default_value_options;
13mod sql_generate;
14mod type_map;
15mod pg_value;
16mod reader;
17mod select_inserted_id_statement_text_renderer;
18mod sql_seed_statement_renderer;
19mod statement_renderer;
20mod stored_procedure_statement_renderer;
21mod transaction;
22
23pub use driver::PostgresDriver;
24
25#[cfg(test)]
26#[path = "../tests/isolate.rs"]
27mod isolate;
28#[cfg(test)]
29#[path = "../tests/contacts.rs"]
30mod contacts;
31#[cfg(test)]
32#[path = "../tests/integration.rs"]
33mod integration;
34#[cfg(test)]
35#[path = "../tests/repository_spec.rs"]
36mod repository_spec;
37#[cfg(test)]
38#[path = "../tests/generate_sql.rs"]
39mod generate_sql;
40#[cfg(test)]
41#[path = "../tests/generate_sql_casing.rs"]
42mod generate_sql_casing;
43#[cfg(test)]
44#[path = "../tests/generate_sql_mapping.rs"]
45mod generate_sql_mapping;
46
47#[cfg(test)]
48mod tests {
49 use crate::bind::{param_type, to_postgres};
50 use crate::connection::isolation_sql;
51 use crate::converters::BinaryConverter;
52 use tokio_postgres::types::Type;
53 use crate::command::PostgresCommand;
54 use crate::connection::PostgresConnection;
55 use crate::transaction::PostgresTransaction;
56 use datasources::{
57 Row, create, downcast_connection, register, reset, Command, Connection,
58 Driver, IsolationLevel, Transaction, TypeConverter, Value,
59 };
60 use std::collections::HashMap;
61 use std::sync::Arc;
62
63 struct With(Option<String>);
64
65 impl Driver for With {
66 fn connection(&self, _: Option<&HashMap<String, String>>) -> Arc<dyn Connection> {
67 Arc::new(PostgresConnection::new(self.0.clone(), None))
68 }
69
70 fn command(&self, connection: Arc<dyn Connection>) -> Arc<dyn Command> {
71 connection.create_command()
72 }
73
74 fn transaction(
75 &self,
76 connection: Arc<dyn Connection>,
77 isolation: IsolationLevel,
78 ) -> Arc<dyn Transaction> {
79 let conn = downcast_connection::<PostgresConnection>(connection).expect("postgres");
80 Arc::new(PostgresTransaction::new(conn.share(), isolation))
81 }
82
83 fn row_type_converters(
84 &self,
85 ) -> HashMap<
86 String,
87 Box<
88 dyn datasources::TypeConverter<datasources::Value, datasources::Value>
89 + Send
90 + Sync,
91 >,
92 > {
93 crate::converters::row_type_converters()
94 }
95 }
96
97 #[tokio::test]
98 async fn postgres_command_and_repository() {
99 let (sql, values) = to_postgres(
100 "SELECT * FROM t WHERE id = $id AND n = $id",
101 &HashMap::from([("id".into(), Value::Int(1))]),
102 );
103 assert_eq!(sql, "SELECT * FROM t WHERE id = $1 AND n = $1");
104 assert_eq!(values, vec![Value::Int(1)]);
105 let (seed, _) = to_postgres(
106 "INSERT INTO \"contact_sources\" (\"name\") VALUES ('Manual')",
107 &HashMap::new(),
108 );
109 assert_eq!(seed, "INSERT INTO \"contact_sources\" (\"name\") VALUES ('Manual')");
110 let (legacy, _) = to_postgres("SELECT * FROM OldContactsTbl", &HashMap::new());
111 assert_eq!(legacy, "SELECT * FROM \"OldContactsTbl\"");
112 let (_, missing) = to_postgres("SELECT $missing", &HashMap::new());
113 assert_eq!(missing, vec![Value::Null]);
114 let stamp = Value::from("2020-01-02T03:04:05.000Z");
115 assert_eq!(param_type(&stamp).oid(), 0);
116 assert_eq!(
117 param_type(&Value::DateTime(
118 chrono::DateTime::parse_from_rfc3339("2020-01-02T03:04:05.000Z")
119 .unwrap()
120 .with_timezone(&chrono::Utc)
121 )),
122 Type::TIMESTAMPTZ
123 );
124 assert_eq!(param_type(&Value::from("ada")).oid(), 0);
125 assert_eq!(
126 param_type(&Value::from("550e8400-e29b-41d4-a716-446655440000")).oid(),
127 0
128 );
129 assert!(matches!(
130 BinaryConverter.convert(&Value::from("AQ==")).unwrap(),
131 Value::Binary(_)
132 ));
133 assert_eq!(param_type(&Value::from("AA==")).oid(), 0);
134 assert_eq!(param_type(&Value::Binary(vec![0])), Type::BYTEA);
135 assert_eq!(param_type(&Value::Int(1)), Type::INT4);
136 assert_eq!(param_type(&Value::Int(i64::MAX)), Type::INT8);
137 assert_eq!(
138 isolation_sql(IsolationLevel::ReadUncommitted),
139 "READ UNCOMMITTED"
140 );
141 assert_eq!(
142 isolation_sql(IsolationLevel::ReadCommitted),
143 "READ COMMITTED"
144 );
145 assert_eq!(
146 isolation_sql(IsolationLevel::RepeatableRead),
147 "REPEATABLE READ"
148 );
149 assert_eq!(isolation_sql(IsolationLevel::Serializable), "SERIALIZABLE");
150 let conn = Arc::new(PostgresConnection::new(
151 Some("postgres://db/app".into()),
152 Some("s".into()),
153 ));
154 assert_eq!(conn.schema.as_deref(), Some("s"));
155 let command = PostgresCommand::new(conn.clone());
156 command
157 .execute_native(&datasources::Native::new(""), None)
158 .await
159 .unwrap();
160 command
161 .execute_reader_native(&datasources::Native::new(""), None)
162 .await
163 .unwrap();
164 assert!(conn.start_transaction(None).await.is_err());
165 conn.close().await.unwrap();
166 assert!(conn.ensure_open().is_err());
167 let defaulted = PostgresConnection::new(None, None);
168 assert_eq!(defaulted.url, "");
169 let options = HashMap::from([(
170 "DATASOURCE_URL".into(),
171 "postgres://db/app?schema=s".into(),
172 )]);
173 let from = downcast_connection::<PostgresConnection>(PostgresConnection::from_options(
174 Some(&options),
175 ))
176 .expect("postgres");
177 assert_eq!(from.url, "postgres://db/app?schema=s");
178 assert_eq!(from.schema.as_deref(), Some("s"));
179 assert_eq!(
180 crate::connection::connect_url("postgres://db/app?schema=s"),
181 "postgres://db/app"
182 );
183 assert_eq!(
184 crate::connection::connect_url(
185 "postgres://ds:ds@127.0.0.1:15432/datasources?schema=ds_x"
186 ),
187 "postgres://ds:ds@127.0.0.1:15432/datasources"
188 );
189 reset();
190 register("postgres", Arc::new(With(Some("postgres://db/app".into()))));
191 let ds = create(Some(&HashMap::from([(
192 "PROVIDER".into(),
193 "postgres".into(),
194 )])))
195 .unwrap();
196 assert_eq!(ds.provider(), "postgres");
197 assert!(ds.create_command(None).await.is_err());
198 ds.create_repository::<Row>(None, None);
199 let closed = Arc::new(PostgresConnection::new(None, None));
200 assert!(PostgresCommand::new(closed)
201 .execute_native(&datasources::Native::new("x"), None)
202 .await
203 .is_err());
204 }
205}