1#[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
2extern crate libsqlite3_sys as ffi;
3
4#[cfg(all(target_family = "wasm", target_os = "unknown"))]
5use sqlite_wasm_rs as ffi;
6
7mod bind_collector;
8mod functions;
9mod owned_row;
10mod raw;
11mod row;
12mod serialized_database;
13pub(in crate::sqlite) mod sqlite_blob;
14mod sqlite_value;
15mod statement_iterator;
16mod stmt;
17
18pub(in crate::sqlite) use self::bind_collector::SqliteBindCollector;
19pub use self::bind_collector::SqliteBindValue;
20pub use self::serialized_database::SerializedDatabase;
21pub use self::sqlite_value::SqliteValue;
22
23use self::raw::RawConnection;
24use self::statement_iterator::*;
25use self::stmt::{Statement, StatementUse};
26use super::SqliteAggregateFunction;
27use crate::connection::instrumentation::{DynInstrumentation, StrQueryHelper};
28use crate::connection::statement_cache::StatementCache;
29use crate::connection::*;
30use crate::deserialize::{FromSqlRow, StaticallySizedRow};
31use crate::expression::QueryMetadata;
32use crate::query_builder::*;
33use crate::result::*;
34use crate::serialize::ToSql;
35use crate::sql_types::{HasSqlType, TypeMetadata};
36use crate::sqlite::Sqlite;
37use alloc::string::String;
38use core::ffi as libc;
39use core::num::NonZeroI64;
40
41#[allow(missing_debug_implementations)]
164#[cfg(feature = "__sqlite-shared")]
165pub struct SqliteConnection {
166 statement_cache: StatementCache<Sqlite, Statement>,
170 raw_connection: RawConnection,
171 transaction_state: AnsiTransactionManager,
172 metadata_lookup: (),
175 instrumentation: DynInstrumentation,
176}
177
178#[allow(unsafe_code)]
182unsafe impl Send for SqliteConnection {}
183
184impl SimpleConnection for SqliteConnection {
185 fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
186 self.instrumentation
187 .on_connection_event(InstrumentationEvent::StartQuery {
188 query: &StrQueryHelper::new(query),
189 });
190 let resp = self.raw_connection.exec(query);
191 self.instrumentation
192 .on_connection_event(InstrumentationEvent::FinishQuery {
193 query: &StrQueryHelper::new(query),
194 error: resp.as_ref().err(),
195 });
196 resp
197 }
198}
199
200impl ConnectionSealed for SqliteConnection {}
201
202impl Connection for SqliteConnection {
203 type Backend = Sqlite;
204 type TransactionManager = AnsiTransactionManager;
205
206 fn establish(database_url: &str) -> ConnectionResult<Self> {
222 let mut instrumentation = DynInstrumentation::default_instrumentation();
223 instrumentation.on_connection_event(InstrumentationEvent::StartEstablishConnection {
224 url: database_url,
225 });
226
227 let establish_result = Self::establish_inner(database_url);
228 instrumentation.on_connection_event(InstrumentationEvent::FinishEstablishConnection {
229 url: database_url,
230 error: establish_result.as_ref().err(),
231 });
232 let mut conn = establish_result?;
233 conn.instrumentation = instrumentation;
234 Ok(conn)
235 }
236
237 fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
238 where
239 T: QueryFragment<Self::Backend> + QueryId,
240 {
241 let statement_use = self.prepared_query(source)?;
242 statement_use.run().and_then(|_| {
243 self.raw_connection
244 .rows_affected_by_last_query()
245 .map_err(Error::DeserializationError)
246 })
247 }
248
249 fn transaction_state(&mut self) -> &mut AnsiTransactionManager
250 where
251 Self: Sized,
252 {
253 &mut self.transaction_state
254 }
255
256 fn instrumentation(&mut self) -> &mut dyn Instrumentation {
257 &mut *self.instrumentation
258 }
259
260 fn set_instrumentation(&mut self, instrumentation: impl Instrumentation) {
261 self.instrumentation = instrumentation.into();
262 }
263
264 fn set_prepared_statement_cache_size(&mut self, size: CacheSize) {
265 self.statement_cache.set_cache_size(size);
266 }
267}
268
269impl LoadConnection<DefaultLoadingMode> for SqliteConnection {
270 type Cursor<'conn, 'query> = StatementIterator<'conn, 'query>;
271 type Row<'conn, 'query> = self::row::SqliteRow<'conn, 'query>;
272
273 fn load<'conn, 'query, T>(
274 &'conn mut self,
275 source: T,
276 ) -> QueryResult<Self::Cursor<'conn, 'query>>
277 where
278 T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
279 Self::Backend: QueryMetadata<T::SqlType>,
280 {
281 let statement = self.prepared_query(source)?;
282
283 Ok(StatementIterator::new(statement))
284 }
285}
286
287impl WithMetadataLookup for SqliteConnection {
288 fn metadata_lookup(&mut self) -> &mut <Sqlite as TypeMetadata>::MetadataLookup {
289 &mut self.metadata_lookup
290 }
291}
292
293#[cfg(feature = "r2d2")]
294impl crate::r2d2::R2D2Connection for crate::sqlite::SqliteConnection {
295 fn ping(&mut self) -> QueryResult<()> {
296 use crate::RunQueryDsl;
297
298 crate::r2d2::CheckConnectionQuery.execute(self).map(|_| ())
299 }
300
301 fn is_broken(&mut self) -> bool {
302 AnsiTransactionManager::is_broken_transaction_manager(self)
303 }
304}
305
306impl MultiConnectionHelper for SqliteConnection {
307 fn to_any<'a>(
308 lookup: &mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup,
309 ) -> &mut (dyn core::any::Any + 'a) {
310 lookup
311 }
312
313 fn from_any(
314 lookup: &mut dyn core::any::Any,
315 ) -> Option<&mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup> {
316 lookup.downcast_mut()
317 }
318}
319
320impl SqliteConnection {
321 pub fn immediate_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
343 where
344 F: FnOnce(&mut Self) -> Result<T, E>,
345 E: From<Error>,
346 {
347 self.transaction_sql(f, "BEGIN IMMEDIATE")
348 }
349
350 pub fn exclusive_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
372 where
373 F: FnOnce(&mut Self) -> Result<T, E>,
374 E: From<Error>,
375 {
376 self.transaction_sql(f, "BEGIN EXCLUSIVE")
377 }
378
379 pub fn last_insert_rowid(&self) -> Option<NonZeroI64> {
415 NonZeroI64::new(self.raw_connection.last_insert_rowid())
416 }
417
418 pub fn get_read_only_blob<'conn, 'query, U>(
447 &'conn self,
448 blob_column: U,
449 row_id: i64,
450 ) -> Result<sqlite_blob::SqliteReadOnlyBlob<'conn>, Error>
451 where
452 'query: 'conn,
453 U: crate::Column,
454 U::Table: nodes::StaticQueryFragment,
455 <U::Table as nodes::StaticQueryFragment>::Component: HasDatabaseAndTableName,
456 {
457 use crate::query_builder::nodes::StaticQueryFragment;
458 let _ = blob_column;
460
461 let database_name = U::Table::STATIC_COMPONENT.database_name().unwrap_or("main");
462 let column_name = U::NAME;
463 let table_name = U::Table::STATIC_COMPONENT.table_name();
464
465 self.raw_connection
466 .blob_open(database_name, table_name, column_name, row_id)
467 }
468
469 fn transaction_sql<T, E, F>(&mut self, f: F, sql: &str) -> Result<T, E>
470 where
471 F: FnOnce(&mut Self) -> Result<T, E>,
472 E: From<Error>,
473 {
474 AnsiTransactionManager::begin_transaction_sql(&mut *self, sql)?;
475 match f(&mut *self) {
476 Ok(value) => {
477 AnsiTransactionManager::commit_transaction(&mut *self)?;
478 Ok(value)
479 }
480 Err(e) => {
481 AnsiTransactionManager::rollback_transaction(&mut *self)?;
482 Err(e)
483 }
484 }
485 }
486
487 fn prepared_query<'conn, 'query, T>(
488 &'conn mut self,
489 source: T,
490 ) -> QueryResult<StatementUse<'conn, 'query>>
491 where
492 T: QueryFragment<Sqlite> + QueryId + 'query,
493 {
494 self.instrumentation
495 .on_connection_event(InstrumentationEvent::StartQuery {
496 query: &crate::debug_query(&source),
497 });
498 let raw_connection = &self.raw_connection;
499 let cache = &mut self.statement_cache;
500 let statement = match cache.cached_statement(
501 &source,
502 &Sqlite,
503 &[],
504 raw_connection,
505 Statement::prepare,
506 &mut *self.instrumentation,
507 ) {
508 Ok(statement) => statement,
509 Err(e) => {
510 self.instrumentation
511 .on_connection_event(InstrumentationEvent::FinishQuery {
512 query: &crate::debug_query(&source),
513 error: Some(&e),
514 });
515
516 return Err(e);
517 }
518 };
519
520 StatementUse::bind(statement, source, &mut *self.instrumentation)
521 }
522
523 #[doc(hidden)]
524 pub fn register_sql_function<ArgsSqlType, RetSqlType, Args, Ret, F>(
525 &mut self,
526 fn_name: &str,
527 deterministic: bool,
528 mut f: F,
529 ) -> QueryResult<()>
530 where
531 F: FnMut(Args) -> Ret + core::panic::UnwindSafe + Send + 'static,
532 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
533 Ret: ToSql<RetSqlType, Sqlite>,
534 Sqlite: HasSqlType<RetSqlType>,
535 {
536 functions::register(
537 &self.raw_connection,
538 fn_name,
539 deterministic,
540 move |_, args| f(args),
541 )
542 }
543
544 #[doc(hidden)]
545 pub fn register_noarg_sql_function<RetSqlType, Ret, F>(
546 &self,
547 fn_name: &str,
548 deterministic: bool,
549 f: F,
550 ) -> QueryResult<()>
551 where
552 F: FnMut() -> Ret + core::panic::UnwindSafe + Send + 'static,
553 Ret: ToSql<RetSqlType, Sqlite>,
554 Sqlite: HasSqlType<RetSqlType>,
555 {
556 functions::register_noargs(&self.raw_connection, fn_name, deterministic, f)
557 }
558
559 #[doc(hidden)]
560 pub fn register_aggregate_function<ArgsSqlType, RetSqlType, Args, Ret, A>(
561 &mut self,
562 fn_name: &str,
563 ) -> QueryResult<()>
564 where
565 A: SqliteAggregateFunction<Args, Output = Ret> + 'static + Send + core::panic::UnwindSafe,
566 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
567 Ret: ToSql<RetSqlType, Sqlite>,
568 Sqlite: HasSqlType<RetSqlType>,
569 {
570 functions::register_aggregate::<_, _, _, _, A>(&self.raw_connection, fn_name)
571 }
572
573 pub fn register_collation<F>(&mut self, collation_name: &str, collation: F) -> QueryResult<()>
609 where
610 F: Fn(&str, &str) -> core::cmp::Ordering + Send + 'static + core::panic::UnwindSafe,
611 {
612 self.raw_connection
613 .register_collation_function(collation_name, collation)
614 }
615
616 pub fn serialize_database_to_buffer(&mut self) -> SerializedDatabase {
625 self.raw_connection.serialize()
626 }
627
628 pub fn deserialize_readonly_database_from_buffer(&mut self, data: &[u8]) -> QueryResult<()> {
665 self.raw_connection.deserialize(data)
666 }
667
668 #[allow(unsafe_code)]
755 pub unsafe fn with_raw_connection<R, F>(&mut self, f: F) -> R
756 where
757 F: FnOnce(*mut ffi::sqlite3) -> R,
758 {
759 f(self.raw_connection.internal_connection.as_ptr())
760 }
761
762 fn register_diesel_sql_functions(&self) -> QueryResult<()> {
763 use crate::sql_types::{Integer, Text};
764
765 functions::register::<Text, Integer, _, _, _>(
766 &self.raw_connection,
767 "diesel_manage_updated_at",
768 false,
769 |conn, table_name: String| {
770 conn.exec(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CREATE TRIGGER __diesel_manage_updated_at_{0}\nAFTER UPDATE ON {0}\nFOR EACH ROW WHEN\n old.updated_at IS NULL AND\n new.updated_at IS NULL OR\n old.updated_at == new.updated_at\nBEGIN\n UPDATE {0}\n SET updated_at = CURRENT_TIMESTAMP\n WHERE ROWID = new.ROWID;\nEND\n",
table_name))
})alloc::format!(
771 include_str!("diesel_manage_updated_at.sql"),
772 table_name = table_name
773 ))
774 .expect("Failed to create trigger");
775 0 },
777 )
778 }
779
780 fn establish_inner(database_url: &str) -> Result<SqliteConnection, ConnectionError> {
781 use crate::result::ConnectionError::CouldntSetupConfiguration;
782 let raw_connection = RawConnection::establish(database_url)?;
783 let conn = Self {
784 statement_cache: StatementCache::new(),
785 raw_connection,
786 transaction_state: AnsiTransactionManager::default(),
787 metadata_lookup: (),
788 instrumentation: DynInstrumentation::none(),
789 };
790 conn.register_diesel_sql_functions()
791 .map_err(CouldntSetupConfiguration)?;
792 Ok(conn)
793 }
794}
795
796fn error_message(err_code: libc::c_int) -> &'static str {
797 ffi::code_to_str(err_code)
798}
799
800mod private {
801 #[doc(hidden)]
802 pub trait HasDatabaseAndTableName {
803 fn database_name(&self) -> Option<&'static str>;
804 fn table_name(&self) -> &'static str;
805 }
806
807 impl HasDatabaseAndTableName for crate::query_builder::nodes::Identifier<'static> {
808 fn database_name(&self) -> Option<&'static str> {
809 None
810 }
811
812 fn table_name(&self) -> &'static str {
813 self.0
814 }
815 }
816
817 impl<M> HasDatabaseAndTableName
818 for crate::query_builder::nodes::InfixNode<
819 crate::query_builder::nodes::Identifier<'static>,
820 crate::query_builder::nodes::Identifier<'static>,
821 M,
822 >
823 {
824 fn database_name(&self) -> Option<&'static str> {
825 Some(self.lhs.0)
826 }
827
828 fn table_name(&self) -> &'static str {
829 self.rhs.0
830 }
831 }
832}
833pub(crate) use self::private::HasDatabaseAndTableName;
834
835#[cfg(test)]
836mod tests {
837 use super::*;
838 use crate::dsl::sql;
839 use crate::prelude::*;
840 use crate::sql_types::{Integer, Text};
841
842 fn connection() -> SqliteConnection {
843 SqliteConnection::establish(":memory:").unwrap()
844 }
845
846 #[diesel_test_helper::test]
847 #[allow(unsafe_code)]
848 fn with_raw_connection_can_return_values() {
849 let connection = &mut connection();
850
851 let autocommit_status = unsafe {
853 connection.with_raw_connection(|raw_conn| ffi::sqlite3_get_autocommit(raw_conn))
854 };
855
856 assert_ne!(autocommit_status, 0, "Expected autocommit to be enabled");
858 }
859
860 #[diesel_test_helper::test]
861 #[allow(unsafe_code)]
862 fn with_raw_connection_works_after_diesel_operations() {
863 let connection = &mut connection();
864
865 crate::sql_query("CREATE TABLE test_table (id INTEGER PRIMARY KEY, value TEXT)")
867 .execute(connection)
868 .unwrap();
869 crate::sql_query("INSERT INTO test_table (value) VALUES ('hello')")
870 .execute(connection)
871 .unwrap();
872
873 let last_rowid = unsafe {
875 connection.with_raw_connection(|raw_conn| ffi::sqlite3_last_insert_rowid(raw_conn))
876 };
877
878 assert_eq!(last_rowid, 1, "Last insert rowid should be 1");
879
880 let count: i64 = sql::<crate::sql_types::BigInt>("SELECT COUNT(*) FROM test_table")
882 .get_result(connection)
883 .unwrap();
884 assert_eq!(count, 1);
885 }
886
887 #[diesel_test_helper::test]
888 #[allow(unsafe_code)]
889 fn with_raw_connection_can_execute_raw_sql() {
890 let connection = &mut connection();
891
892 crate::sql_query("CREATE TABLE raw_test (id INTEGER PRIMARY KEY, name TEXT)")
894 .execute(connection)
895 .unwrap();
896
897 let result = unsafe {
900 connection.with_raw_connection(|raw_conn| {
901 let sql = c"INSERT INTO raw_test (name) VALUES ('from_raw')";
902 let mut err_msg: *mut libc::c_char = core::ptr::null_mut();
903 let rc = ffi::sqlite3_exec(
904 raw_conn,
905 sql.as_ptr(),
906 None,
907 core::ptr::null_mut(),
908 &mut err_msg,
909 );
910 if rc != ffi::SQLITE_OK && !err_msg.is_null() {
911 ffi::sqlite3_free(err_msg as *mut libc::c_void);
912 }
913 rc
914 })
915 };
916
917 assert_eq!(result, ffi::SQLITE_OK, "Raw SQL execution should succeed");
918
919 let count: i64 = sql::<crate::sql_types::BigInt>("SELECT COUNT(*) FROM raw_test")
921 .get_result(connection)
922 .unwrap();
923 assert_eq!(count, 1);
924
925 let name: String = sql::<Text>("SELECT name FROM raw_test WHERE id = 1")
926 .get_result(connection)
927 .unwrap();
928 assert_eq!(name, "from_raw");
929 }
930
931 #[diesel_test_helper::test]
932 #[allow(unsafe_code)]
933 fn with_raw_connection_works_within_transaction() {
934 let connection = &mut connection();
935
936 crate::sql_query("CREATE TABLE txn_test (id INTEGER PRIMARY KEY, value INTEGER)")
937 .execute(connection)
938 .unwrap();
939
940 connection
941 .transaction::<_, crate::result::Error, _>(|conn| {
942 crate::sql_query("INSERT INTO txn_test (value) VALUES (42)")
943 .execute(conn)
944 .unwrap();
945
946 let autocommit = unsafe {
948 conn.with_raw_connection(|raw_conn| ffi::sqlite3_get_autocommit(raw_conn))
949 };
950
951 assert_eq!(
953 autocommit, 0,
954 "Autocommit should be disabled inside transaction"
955 );
956
957 Ok(())
958 })
959 .unwrap();
960
961 let autocommit = unsafe {
963 connection.with_raw_connection(|raw_conn| ffi::sqlite3_get_autocommit(raw_conn))
964 };
965 assert_ne!(
966 autocommit, 0,
967 "Autocommit should be enabled after transaction"
968 );
969 }
970
971 #[diesel_test_helper::test]
972 #[allow(unsafe_code)]
973 fn with_raw_connection_can_read_database_filename() {
974 let connection = &mut connection();
975
976 let filename = unsafe {
978 connection.with_raw_connection(|raw_conn| {
979 let db_name = c"main";
980 let filename_ptr = ffi::sqlite3_db_filename(raw_conn, db_name.as_ptr());
981 if filename_ptr.is_null() {
982 None
983 } else {
984 let cstr = core::ffi::CStr::from_ptr(filename_ptr);
986 Some(cstr.to_string_lossy().into_owned())
987 }
988 })
989 };
990
991 assert_eq!(
994 filename,
995 Some(String::new()),
996 "In-memory database filename should be an empty string"
997 );
998 }
999
1000 #[diesel_test_helper::test]
1001 #[allow(unsafe_code)]
1002 fn with_raw_connection_changes_count() {
1003 let connection = &mut connection();
1004
1005 crate::sql_query("CREATE TABLE changes_test (id INTEGER PRIMARY KEY, value INTEGER)")
1006 .execute(connection)
1007 .unwrap();
1008
1009 crate::sql_query("INSERT INTO changes_test (value) VALUES (1), (2), (3)")
1010 .execute(connection)
1011 .unwrap();
1012
1013 let changes = unsafe {
1015 connection.with_raw_connection(|raw_conn| {
1016 let sql = c"UPDATE changes_test SET value = value + 10";
1017 let mut err_msg: *mut libc::c_char = core::ptr::null_mut();
1018 let rc = ffi::sqlite3_exec(
1019 raw_conn,
1020 sql.as_ptr(),
1021 None,
1022 core::ptr::null_mut(),
1023 &mut err_msg,
1024 );
1025 if rc != ffi::SQLITE_OK && !err_msg.is_null() {
1026 ffi::sqlite3_free(err_msg as *mut libc::c_void);
1027 return -1;
1028 }
1029 ffi::sqlite3_changes(raw_conn)
1030 })
1031 };
1032
1033 assert_eq!(changes, 3, "Should have updated 3 rows");
1034
1035 let values: Vec<i32> = sql::<Integer>("SELECT value FROM changes_test ORDER BY id")
1037 .load(connection)
1038 .unwrap();
1039 assert_eq!(values, vec![11, 12, 13]);
1040 }
1041
1042 #[diesel_test_helper::test]
1044 #[allow(unsafe_code)]
1045 #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
1046 fn with_raw_connection_recovers_after_panic() {
1047 let connection = &mut connection();
1048
1049 crate::sql_query("CREATE TABLE panic_test (id INTEGER PRIMARY KEY, value TEXT)")
1050 .execute(connection)
1051 .unwrap();
1052
1053 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe {
1055 connection.with_raw_connection(|_raw_conn| {
1056 panic!("intentional panic inside with_raw_connection");
1057 })
1058 }));
1059 assert!(result.is_err(), "Should have caught the panic");
1060
1061 crate::sql_query("INSERT INTO panic_test (value) VALUES ('after_panic')")
1063 .execute(connection)
1064 .unwrap();
1065
1066 let count: i64 = sql::<crate::sql_types::BigInt>("SELECT COUNT(*) FROM panic_test")
1067 .get_result(connection)
1068 .unwrap();
1069 assert_eq!(count, 1, "Connection should work after panic in callback");
1070 }
1071
1072 #[diesel_test_helper::test]
1074 #[allow(unsafe_code)]
1075 #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
1076 fn with_raw_connection_can_read_file_database_filename() {
1077 let dir = std::env::temp_dir().join("diesel_test_filename.db");
1078 let db_path = dir.to_str().unwrap();
1079
1080 let _ = std::fs::remove_file(db_path);
1082
1083 let connection = &mut SqliteConnection::establish(db_path).unwrap();
1084
1085 let filename = unsafe {
1087 connection.with_raw_connection(|raw_conn| {
1088 let db_name = c"main";
1089 let filename_ptr = ffi::sqlite3_db_filename(raw_conn, db_name.as_ptr());
1090 if filename_ptr.is_null() {
1091 None
1092 } else {
1093 let cstr = core::ffi::CStr::from_ptr(filename_ptr);
1094 Some(cstr.to_string_lossy().into_owned())
1095 }
1096 })
1097 };
1098
1099 let filename = filename.expect("File-based database should have a filename");
1100 assert!(
1101 filename.contains("diesel_test_filename.db"),
1102 "Filename should contain the database name, got: {filename}"
1103 );
1104
1105 let _ = std::fs::remove_file(db_path);
1107 }
1108
1109 #[declare_sql_function]
1110 extern "SQL" {
1111 fn fun_case(x: Text) -> Text;
1112 fn my_add(x: Integer, y: Integer) -> Integer;
1113 fn answer() -> Integer;
1114 fn add_counter(x: Integer) -> Integer;
1115
1116 #[aggregate]
1117 fn my_sum(expr: Integer) -> Integer;
1118 #[aggregate]
1119 fn range_max(expr1: Integer, expr2: Integer, expr3: Integer) -> Nullable<Integer>;
1120 }
1121
1122 #[diesel_test_helper::test]
1123 fn database_serializes_and_deserializes_successfully() {
1124 let expected_users = vec![
1125 (
1126 1,
1127 "John Doe".to_string(),
1128 "john.doe@example.com".to_string(),
1129 ),
1130 (
1131 2,
1132 "Jane Doe".to_string(),
1133 "jane.doe@example.com".to_string(),
1134 ),
1135 ];
1136
1137 let conn1 = &mut connection();
1138 let _ =
1139 crate::sql_query("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
1140 .execute(conn1);
1141 let _ = crate::sql_query("INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com'), ('Jane Doe', 'jane.doe@example.com')")
1142 .execute(conn1);
1143
1144 let serialized_database = conn1.serialize_database_to_buffer();
1145
1146 let conn2 = &mut connection();
1147 conn2
1148 .deserialize_readonly_database_from_buffer(serialized_database.as_slice())
1149 .unwrap();
1150
1151 let query = sql::<(Integer, Text, Text)>("SELECT id, name, email FROM users ORDER BY id");
1152 let actual_users = query.load::<(i32, String, String)>(conn2).unwrap();
1153
1154 assert_eq!(expected_users, actual_users);
1155 }
1156
1157 #[diesel_test_helper::test]
1158 fn register_custom_function() {
1159 let connection = &mut connection();
1160 fun_case_utils::register_impl(connection, |x: String| {
1161 x.chars()
1162 .enumerate()
1163 .map(|(i, c)| {
1164 if i % 2 == 0 {
1165 c.to_lowercase().to_string()
1166 } else {
1167 c.to_uppercase().to_string()
1168 }
1169 })
1170 .collect::<String>()
1171 })
1172 .unwrap();
1173
1174 let mapped_string = crate::select(fun_case("foobar"))
1175 .get_result::<String>(connection)
1176 .unwrap();
1177 assert_eq!("fOoBaR", mapped_string);
1178 }
1179
1180 #[diesel_test_helper::test]
1181 fn register_multiarg_function() {
1182 let connection = &mut connection();
1183 my_add_utils::register_impl(connection, |x: i32, y: i32| x + y).unwrap();
1184
1185 let added = crate::select(my_add(1, 2)).get_result::<i32>(connection);
1186 assert_eq!(Ok(3), added);
1187 }
1188
1189 #[diesel_test_helper::test]
1190 fn register_noarg_function() {
1191 let connection = &mut connection();
1192 answer_utils::register_impl(connection, || 42).unwrap();
1193
1194 let answer = crate::select(answer()).get_result::<i32>(connection);
1195 assert_eq!(Ok(42), answer);
1196 }
1197
1198 #[diesel_test_helper::test]
1199 fn register_nondeterministic_noarg_function() {
1200 let connection = &mut connection();
1201 answer_utils::register_nondeterministic_impl(connection, || 42).unwrap();
1202
1203 let answer = crate::select(answer()).get_result::<i32>(connection);
1204 assert_eq!(Ok(42), answer);
1205 }
1206
1207 #[diesel_test_helper::test]
1208 fn register_nondeterministic_function() {
1209 let connection = &mut connection();
1210 let mut y = 0;
1211 add_counter_utils::register_nondeterministic_impl(connection, move |x: i32| {
1212 y += 1;
1213 x + y
1214 })
1215 .unwrap();
1216
1217 let added = crate::select((add_counter(1), add_counter(1), add_counter(1)))
1218 .get_result::<(i32, i32, i32)>(connection);
1219 assert_eq!(Ok((2, 3, 4)), added);
1220 }
1221
1222 #[derive(Default)]
1223 struct MySum {
1224 sum: i32,
1225 }
1226
1227 impl SqliteAggregateFunction<i32> for MySum {
1228 type Output = i32;
1229
1230 fn step(&mut self, expr: i32) {
1231 self.sum += expr;
1232 }
1233
1234 fn finalize(aggregator: Option<Self>) -> Self::Output {
1235 aggregator.map(|a| a.sum).unwrap_or_default()
1236 }
1237 }
1238
1239 table! {
1240 my_sum_example {
1241 id -> Integer,
1242 value -> Integer,
1243 }
1244 }
1245
1246 #[diesel_test_helper::test]
1247 fn register_aggregate_function() {
1248 use self::my_sum_example::dsl::*;
1249
1250 let connection = &mut connection();
1251 crate::sql_query(
1252 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
1253 )
1254 .execute(connection)
1255 .unwrap();
1256 crate::sql_query("INSERT INTO my_sum_example (value) VALUES (1), (2), (3)")
1257 .execute(connection)
1258 .unwrap();
1259
1260 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
1261
1262 let result = my_sum_example
1263 .select(my_sum(value))
1264 .get_result::<i32>(connection);
1265 assert_eq!(Ok(6), result);
1266 }
1267
1268 #[diesel_test_helper::test]
1269 fn register_aggregate_function_returns_finalize_default_on_empty_set() {
1270 use self::my_sum_example::dsl::*;
1271
1272 let connection = &mut connection();
1273 crate::sql_query(
1274 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
1275 )
1276 .execute(connection)
1277 .unwrap();
1278
1279 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
1280
1281 let result = my_sum_example
1282 .select(my_sum(value))
1283 .get_result::<i32>(connection);
1284 assert_eq!(Ok(0), result);
1285 }
1286
1287 #[derive(Default)]
1288 struct RangeMax<T> {
1289 max_value: Option<T>,
1290 }
1291
1292 impl<T: Default + Ord + Copy + Clone> SqliteAggregateFunction<(T, T, T)> for RangeMax<T> {
1293 type Output = Option<T>;
1294
1295 fn step(&mut self, (x0, x1, x2): (T, T, T)) {
1296 let max = if x0 >= x1 && x0 >= x2 {
1297 x0
1298 } else if x1 >= x0 && x1 >= x2 {
1299 x1
1300 } else {
1301 x2
1302 };
1303
1304 self.max_value = match self.max_value {
1305 Some(current_max_value) if max > current_max_value => Some(max),
1306 None => Some(max),
1307 _ => self.max_value,
1308 };
1309 }
1310
1311 fn finalize(aggregator: Option<Self>) -> Self::Output {
1312 aggregator?.max_value
1313 }
1314 }
1315
1316 table! {
1317 range_max_example {
1318 id -> Integer,
1319 value1 -> Integer,
1320 value2 -> Integer,
1321 value3 -> Integer,
1322 }
1323 }
1324
1325 #[diesel_test_helper::test]
1326 fn register_aggregate_multiarg_function() {
1327 use self::range_max_example::dsl::*;
1328
1329 let connection = &mut connection();
1330 crate::sql_query(
1331 r#"CREATE TABLE range_max_example (
1332 id integer primary key autoincrement,
1333 value1 integer,
1334 value2 integer,
1335 value3 integer
1336 )"#,
1337 )
1338 .execute(connection)
1339 .unwrap();
1340 crate::sql_query(
1341 "INSERT INTO range_max_example (value1, value2, value3) VALUES (3, 2, 1), (2, 2, 2)",
1342 )
1343 .execute(connection)
1344 .unwrap();
1345
1346 range_max_utils::register_impl::<RangeMax<i32>, _, _, _>(connection).unwrap();
1347 let result = range_max_example
1348 .select(range_max(value1, value2, value3))
1349 .get_result::<Option<i32>>(connection)
1350 .unwrap();
1351 assert_eq!(Some(3), result);
1352 }
1353
1354 table! {
1355 my_collation_example {
1356 id -> Integer,
1357 value -> Text,
1358 }
1359 }
1360
1361 #[diesel_test_helper::test]
1362 fn register_collation_function() {
1363 use self::my_collation_example::dsl::*;
1364
1365 let connection = &mut connection();
1366
1367 connection
1368 .register_collation("RUSTNOCASE", |rhs, lhs| {
1369 rhs.to_lowercase().cmp(&lhs.to_lowercase())
1370 })
1371 .unwrap();
1372
1373 crate::sql_query(
1374 "CREATE TABLE my_collation_example (id integer primary key autoincrement, value text collate RUSTNOCASE)",
1375 ).execute(connection)
1376 .unwrap();
1377 crate::sql_query(
1378 "INSERT INTO my_collation_example (value) VALUES ('foo'), ('FOo'), ('f00')",
1379 )
1380 .execute(connection)
1381 .unwrap();
1382
1383 let result = my_collation_example
1384 .filter(value.eq("foo"))
1385 .select(value)
1386 .load::<String>(connection);
1387 assert_eq!(
1388 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
1389 result.as_ref().map(|vec| vec.as_ref())
1390 );
1391
1392 let result = my_collation_example
1393 .filter(value.eq("FOO"))
1394 .select(value)
1395 .load::<String>(connection);
1396 assert_eq!(
1397 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
1398 result.as_ref().map(|vec| vec.as_ref())
1399 );
1400
1401 let result = my_collation_example
1402 .filter(value.eq("f00"))
1403 .select(value)
1404 .load::<String>(connection);
1405 assert_eq!(
1406 Ok(&["f00".to_owned()][..]),
1407 result.as_ref().map(|vec| vec.as_ref())
1408 );
1409
1410 let result = my_collation_example
1411 .filter(value.eq("F00"))
1412 .select(value)
1413 .load::<String>(connection);
1414 assert_eq!(
1415 Ok(&["f00".to_owned()][..]),
1416 result.as_ref().map(|vec| vec.as_ref())
1417 );
1418
1419 let result = my_collation_example
1420 .filter(value.eq("oof"))
1421 .select(value)
1422 .load::<String>(connection);
1423 assert_eq!(Ok(&[][..]), result.as_ref().map(|vec| vec.as_ref()));
1424 }
1425
1426 #[diesel_test_helper::test]
1428 fn test_correct_serialization_of_owned_strings() {
1429 use crate::prelude::*;
1430
1431 #[derive(Debug, crate::expression::AsExpression)]
1432 #[diesel(sql_type = diesel::sql_types::Text)]
1433 struct CustomWrapper(String);
1434
1435 impl crate::serialize::ToSql<Text, Sqlite> for CustomWrapper {
1436 fn to_sql<'b>(
1437 &'b self,
1438 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
1439 ) -> crate::serialize::Result {
1440 out.set_value(self.0.to_string());
1441 Ok(crate::serialize::IsNull::No)
1442 }
1443 }
1444
1445 let connection = &mut connection();
1446
1447 let res = crate::select(
1448 CustomWrapper("".into())
1449 .into_sql::<crate::sql_types::Text>()
1450 .nullable(),
1451 )
1452 .get_result::<Option<String>>(connection)
1453 .unwrap();
1454 assert_eq!(res, Some(String::new()));
1455 }
1456
1457 #[diesel_test_helper::test]
1458 fn test_correct_serialization_of_owned_bytes() {
1459 use crate::prelude::*;
1460
1461 #[derive(Debug, crate::expression::AsExpression)]
1462 #[diesel(sql_type = diesel::sql_types::Binary)]
1463 struct CustomWrapper(Vec<u8>);
1464
1465 impl crate::serialize::ToSql<crate::sql_types::Binary, Sqlite> for CustomWrapper {
1466 fn to_sql<'b>(
1467 &'b self,
1468 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
1469 ) -> crate::serialize::Result {
1470 out.set_value(self.0.clone());
1471 Ok(crate::serialize::IsNull::No)
1472 }
1473 }
1474
1475 let connection = &mut connection();
1476
1477 let res = crate::select(
1478 CustomWrapper(Vec::new())
1479 .into_sql::<crate::sql_types::Binary>()
1480 .nullable(),
1481 )
1482 .get_result::<Option<Vec<u8>>>(connection)
1483 .unwrap();
1484 assert_eq!(res, Some(Vec::new()));
1485 }
1486
1487 #[diesel_test_helper::test]
1488 fn correctly_handle_empty_query() {
1489 let check_empty_query_error = |r: crate::QueryResult<usize>| {
1490 assert!(r.is_err());
1491 let err = r.unwrap_err();
1492 assert!(
1493 matches!(err, crate::result::Error::QueryBuilderError(ref b) if b.is::<crate::result::EmptyQuery>()),
1494 "Expected a query builder error, but got {err}"
1495 );
1496 };
1497 let connection = &mut SqliteConnection::establish(":memory:").unwrap();
1498 check_empty_query_error(crate::sql_query("").execute(connection));
1499 check_empty_query_error(crate::sql_query(" ").execute(connection));
1500 check_empty_query_error(crate::sql_query("\n\t").execute(connection));
1501 check_empty_query_error(crate::sql_query("-- SELECT 1;").execute(connection));
1502 }
1503
1504 #[diesel_test_helper::test]
1505 fn last_insert_rowid_returns_none_on_fresh_connection() {
1506 let conn = &mut connection();
1507 assert_eq!(conn.last_insert_rowid(), None);
1508 }
1509
1510 #[diesel_test_helper::test]
1511 fn last_insert_rowid_returns_rowid_after_insert() {
1512 let conn = &mut connection();
1513 crate::sql_query("CREATE TABLE li_test (id INTEGER PRIMARY KEY, val TEXT NOT NULL)")
1514 .execute(conn)
1515 .unwrap();
1516
1517 crate::sql_query("INSERT INTO li_test (val) VALUES ('a')")
1518 .execute(conn)
1519 .unwrap();
1520 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(1));
1521
1522 crate::sql_query("INSERT INTO li_test (val) VALUES ('b')")
1523 .execute(conn)
1524 .unwrap();
1525 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(2));
1526 }
1527
1528 #[diesel_test_helper::test]
1529 fn last_insert_rowid_unchanged_after_failed_insert() {
1530 let conn = &mut connection();
1531 crate::sql_query(
1532 "CREATE TABLE li_test2 (id INTEGER PRIMARY KEY, val TEXT NOT NULL UNIQUE)",
1533 )
1534 .execute(conn)
1535 .unwrap();
1536
1537 crate::sql_query("INSERT INTO li_test2 (val) VALUES ('a')")
1538 .execute(conn)
1539 .unwrap();
1540 let rowid = conn.last_insert_rowid();
1541 assert_eq!(rowid, NonZeroI64::new(1));
1542
1543 let result = crate::sql_query("INSERT INTO li_test2 (val) VALUES ('a')").execute(conn);
1545 assert!(result.is_err());
1546
1547 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(1));
1549 }
1550
1551 #[diesel_test_helper::test]
1552 fn last_insert_rowid_with_explicit_rowid() {
1553 let conn = &mut connection();
1554 crate::sql_query("CREATE TABLE li_test3 (id INTEGER PRIMARY KEY, val TEXT NOT NULL)")
1555 .execute(conn)
1556 .unwrap();
1557
1558 crate::sql_query("INSERT INTO li_test3 (id, val) VALUES (42, 'a')")
1559 .execute(conn)
1560 .unwrap();
1561 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(42));
1562 }
1563
1564 #[diesel_test_helper::test]
1565 fn last_insert_rowid_unchanged_after_delete_and_update() {
1566 let conn = &mut connection();
1567 crate::sql_query("CREATE TABLE li_test4 (id INTEGER PRIMARY KEY, val TEXT NOT NULL)")
1568 .execute(conn)
1569 .unwrap();
1570
1571 crate::sql_query("INSERT INTO li_test4 (val) VALUES ('a')")
1572 .execute(conn)
1573 .unwrap();
1574 let rowid = conn.last_insert_rowid();
1575 assert_eq!(rowid, NonZeroI64::new(1));
1576
1577 crate::sql_query("UPDATE li_test4 SET val = 'b' WHERE id = 1")
1578 .execute(conn)
1579 .unwrap();
1580 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(1));
1581
1582 crate::sql_query("DELETE FROM li_test4 WHERE id = 1")
1583 .execute(conn)
1584 .unwrap();
1585 assert_eq!(conn.last_insert_rowid(), NonZeroI64::new(1));
1586 }
1587
1588 #[diesel_test_helper::test]
1589 fn read_bytes_from_blob() {
1590 table! {
1591 blobs {
1592 id -> Integer,
1593 data -> Blob,
1594 data2 -> Blob,
1595 }
1596 }
1597
1598 use std::io::Read;
1599
1600 let conn = &mut connection();
1601
1602 let _ =
1603 crate::sql_query("CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB, data2 BLOB)")
1604 .execute(conn);
1605
1606 let _ = crate::sql_query(
1607 "INSERT INTO blobs (data, data2) VALUES ('abc', 'def'), ('123', '456')",
1608 )
1609 .execute(conn);
1610
1611 let mut data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1612 let mut buf = vec![];
1613 data.read_to_end(&mut buf).unwrap();
1614
1615 assert_eq!(buf, b"abc");
1616
1617 let mut data2 = conn.get_read_only_blob(blobs::data2, 1).unwrap();
1618 let mut buf = vec![];
1619 data2.read_to_end(&mut buf).unwrap();
1620
1621 assert_eq!(buf, b"def");
1622 }
1623
1624 #[diesel_test_helper::test]
1625 fn read_seek_bytes() {
1626 table! {
1627 blobs {
1628 id -> Integer,
1629 data -> Blob,
1630 }
1631 }
1632
1633 use std::io::Read;
1634 use std::io::Seek;
1635 use std::io::SeekFrom;
1636
1637 let conn = &mut connection();
1638
1639 let _ = crate::sql_query("CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB)")
1640 .execute(conn);
1641
1642 let _ = crate::sql_query("INSERT INTO blobs (data) VALUES ('abcdefghi')").execute(conn);
1643
1644 let mut data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1645
1646 let mut buf = [0; 1];
1647 assert_eq!(data.read(&mut buf).unwrap(), 1);
1648 assert_eq!(&buf, b"a");
1649
1650 assert_eq!(data.seek(SeekFrom::Current(1)).unwrap(), 2);
1652
1653 let mut buf = [0; 1];
1654 assert_eq!(data.read(&mut buf).unwrap(), 1);
1655 assert_eq!(&buf, b"c");
1656
1657 assert_eq!(data.seek(SeekFrom::Start(0)).unwrap(), 0);
1659
1660 let mut buf = [0; 1];
1661 assert_eq!(data.read(&mut buf).unwrap(), 1);
1662 assert_eq!(&buf, b"a");
1663
1664 assert_eq!(data.seek(SeekFrom::Current(-10)).unwrap(), 0);
1666
1667 let mut buf = [0; 1];
1668 assert_eq!(data.read(&mut buf).unwrap(), 1);
1669 assert_eq!(&buf, b"a");
1670
1671 data.seek(SeekFrom::Current(100)).unwrap();
1673
1674 let mut buf = [0; 1];
1676 assert_eq!(data.read(&mut buf).unwrap(), 0);
1677 }
1678
1679 #[diesel_test_helper::test]
1680 fn use_conn_after_blob_drop() {
1681 table! {
1682 blobs {
1683 id -> Integer,
1684 data -> Blob,
1685 }
1686 }
1687
1688 let conn = &mut connection();
1689
1690 let _ = crate::sql_query("CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB)")
1691 .execute(conn);
1692
1693 let _ = crate::sql_query("INSERT INTO blobs (data) VALUES ('abc')").execute(conn);
1694
1695 let data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1696 drop(data);
1697
1698 let _ = crate::sql_query("INSERT INTO blobs (data) VALUES ('def')").execute(conn);
1699 }
1700
1701 #[diesel_test_helper::test]
1702 fn blob_transaction() {
1703 table! {
1704 blobs {
1705 id -> Integer,
1706 data -> Blob,
1707 }
1708 }
1709
1710 use std::io::Read;
1711
1712 let conn = &mut connection();
1713
1714 let _ = crate::sql_query("CREATE TABLE blobs (id INTEGER PRIMARY KEY, data BLOB)")
1715 .execute(conn);
1716
1717 let _ = crate::sql_query("INSERT INTO blobs (data) VALUES ('abc')").execute(conn);
1718
1719 {
1720 let mut data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1721 let mut buf = vec![];
1722 data.read_to_end(&mut buf).unwrap();
1723 assert_eq!(buf, b"abc");
1724 }
1725
1726 let res = conn.exclusive_transaction(|conn| {
1727 crate::sql_query("UPDATE blobs SET data = 'def' WHERE id = 1").execute(conn)?;
1728
1729 let mut data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1730 let mut buf = vec![];
1731 data.read_to_end(&mut buf).unwrap();
1732 assert_eq!(buf, b"def");
1733
1734 Result::<(), _>::Err(Error::RollbackTransaction)
1735 });
1736
1737 assert_eq!(res.unwrap_err(), Error::RollbackTransaction);
1738
1739 let mut data = conn.get_read_only_blob(blobs::data, 1).unwrap();
1740 let mut buf = vec![];
1741 data.read_to_end(&mut buf).unwrap();
1742 assert_eq!(buf, b"abc");
1743 }
1744
1745 #[diesel_test_helper::test]
1746 fn aggregate_function_works_with_aligned_data() {
1747 #[derive(Debug, Default)]
1748 #[repr(align(64))]
1749 struct OverAligned;
1750
1751 impl SqliteAggregateFunction<i32> for OverAligned {
1752 type Output = i64;
1753
1754 fn step(&mut self, _value: i32) {
1755 let need = core::mem::align_of::<Self>();
1756 let got = core::mem::align_of_val(self);
1757 assert_eq!(need, got);
1758 }
1759
1760 fn finalize(_agg: Option<Self>) -> i64 {
1761 0
1762 }
1763 }
1764 #[declare_sql_function]
1765 extern "SQL" {
1766 #[aggregate]
1767 fn over_aligned_sum(x: Integer) -> diesel::sql_types::BigInt;
1768 }
1769
1770 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1771 over_aligned_sum_utils::register_impl::<OverAligned, _>(&mut conn).unwrap();
1772
1773 diesel::select(over_aligned_sum(1))
1774 .execute(&mut conn)
1775 .unwrap();
1776 }
1777}