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;
9#[cfg(all(test, not(all(target_family = "wasm", target_os = "unknown"))))]
10#[allow(unsafe_code)]
11mod oom_test_support;
12mod owned_row;
13mod raw;
14mod row;
15mod serialized_database;
16mod sqlite_value;
17mod statement_iterator;
18mod stmt;
19
20pub(in crate::sqlite) use self::bind_collector::SqliteBindCollector;
21pub use self::bind_collector::SqliteBindValue;
22pub use self::serialized_database::SerializedDatabase;
23pub use self::sqlite_value::SqliteValue;
24
25use std::os::raw as libc;
26
27use self::raw::RawConnection;
28use self::statement_iterator::*;
29use self::stmt::{Statement, StatementUse};
30use super::SqliteAggregateFunction;
31use crate::connection::instrumentation::{DynInstrumentation, StrQueryHelper};
32use crate::connection::statement_cache::StatementCache;
33use crate::connection::*;
34use crate::deserialize::{FromSqlRow, StaticallySizedRow};
35use crate::expression::QueryMetadata;
36use crate::query_builder::*;
37use crate::result::*;
38use crate::serialize::ToSql;
39use crate::sql_types::{HasSqlType, TypeMetadata};
40use crate::sqlite::Sqlite;
41
42#[allow(missing_debug_implementations)]
165#[cfg(feature = "sqlite")]
166pub struct SqliteConnection {
167 statement_cache: StatementCache<Sqlite, Statement>,
171 raw_connection: RawConnection,
172 transaction_state: AnsiTransactionManager,
173 metadata_lookup: (),
176 instrumentation: DynInstrumentation,
177 serialized_data: Vec<Vec<u8>>,
188}
189
190#[allow(unsafe_code)]
194unsafe impl Send for SqliteConnection {}
195
196impl SimpleConnection for SqliteConnection {
197 fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
198 self.instrumentation
199 .on_connection_event(InstrumentationEvent::StartQuery {
200 query: &StrQueryHelper::new(query),
201 });
202 let resp = self.raw_connection.exec(query);
203 self.instrumentation
204 .on_connection_event(InstrumentationEvent::FinishQuery {
205 query: &StrQueryHelper::new(query),
206 error: resp.as_ref().err(),
207 });
208 resp
209 }
210}
211
212impl ConnectionSealed for SqliteConnection {}
213
214impl Connection for SqliteConnection {
215 type Backend = Sqlite;
216 type TransactionManager = AnsiTransactionManager;
217
218 fn establish(database_url: &str) -> ConnectionResult<Self> {
234 let mut instrumentation = DynInstrumentation::default_instrumentation();
235 instrumentation.on_connection_event(InstrumentationEvent::StartEstablishConnection {
236 url: database_url,
237 });
238
239 let establish_result = Self::establish_inner(database_url);
240 instrumentation.on_connection_event(InstrumentationEvent::FinishEstablishConnection {
241 url: database_url,
242 error: establish_result.as_ref().err(),
243 });
244 let mut conn = establish_result?;
245 conn.instrumentation = instrumentation;
246 Ok(conn)
247 }
248
249 fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
250 where
251 T: QueryFragment<Self::Backend> + QueryId,
252 {
253 let statement_use = self.prepared_query(source)?;
254 statement_use.run().and_then(|_| {
255 self.raw_connection
256 .rows_affected_by_last_query()
257 .map_err(Error::DeserializationError)
258 })
259 }
260
261 fn transaction_state(&mut self) -> &mut AnsiTransactionManager
262 where
263 Self: Sized,
264 {
265 &mut self.transaction_state
266 }
267
268 fn instrumentation(&mut self) -> &mut dyn Instrumentation {
269 &mut *self.instrumentation
270 }
271
272 fn set_instrumentation(&mut self, instrumentation: impl Instrumentation) {
273 self.instrumentation = instrumentation.into();
274 }
275
276 fn set_prepared_statement_cache_size(&mut self, size: CacheSize) {
277 self.statement_cache.set_cache_size(size);
278 }
279}
280
281impl LoadConnection<DefaultLoadingMode> for SqliteConnection {
282 type Cursor<'conn, 'query> = StatementIterator<'conn, 'query>;
283 type Row<'conn, 'query> = self::row::SqliteRow<'conn, 'query>;
284
285 fn load<'conn, 'query, T>(
286 &'conn mut self,
287 source: T,
288 ) -> QueryResult<Self::Cursor<'conn, 'query>>
289 where
290 T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
291 Self::Backend: QueryMetadata<T::SqlType>,
292 {
293 let statement = self.prepared_query(source)?;
294
295 Ok(StatementIterator::new(statement))
296 }
297}
298
299impl WithMetadataLookup for SqliteConnection {
300 fn metadata_lookup(&mut self) -> &mut <Sqlite as TypeMetadata>::MetadataLookup {
301 &mut self.metadata_lookup
302 }
303}
304
305#[cfg(feature = "r2d2")]
306impl crate::r2d2::R2D2Connection for crate::sqlite::SqliteConnection {
307 fn ping(&mut self) -> QueryResult<()> {
308 use crate::RunQueryDsl;
309
310 crate::r2d2::CheckConnectionQuery.execute(self).map(|_| ())
311 }
312
313 fn is_broken(&mut self) -> bool {
314 AnsiTransactionManager::is_broken_transaction_manager(self)
315 }
316}
317
318impl MultiConnectionHelper for SqliteConnection {
319 fn to_any<'a>(
320 lookup: &mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup,
321 ) -> &mut (dyn std::any::Any + 'a) {
322 lookup
323 }
324
325 fn from_any(
326 lookup: &mut dyn std::any::Any,
327 ) -> Option<&mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup> {
328 lookup.downcast_mut()
329 }
330}
331
332impl SqliteConnection {
333 pub fn immediate_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
355 where
356 F: FnOnce(&mut Self) -> Result<T, E>,
357 E: From<Error>,
358 {
359 self.transaction_sql(f, "BEGIN IMMEDIATE")
360 }
361
362 pub fn exclusive_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
384 where
385 F: FnOnce(&mut Self) -> Result<T, E>,
386 E: From<Error>,
387 {
388 self.transaction_sql(f, "BEGIN EXCLUSIVE")
389 }
390
391 fn transaction_sql<T, E, F>(&mut self, f: F, sql: &str) -> Result<T, E>
392 where
393 F: FnOnce(&mut Self) -> Result<T, E>,
394 E: From<Error>,
395 {
396 AnsiTransactionManager::begin_transaction_sql(&mut *self, sql)?;
397 match f(&mut *self) {
398 Ok(value) => {
399 AnsiTransactionManager::commit_transaction(&mut *self)?;
400 Ok(value)
401 }
402 Err(e) => {
403 AnsiTransactionManager::rollback_transaction(&mut *self)?;
404 Err(e)
405 }
406 }
407 }
408
409 fn prepared_query<'conn, 'query, T>(
410 &'conn mut self,
411 source: T,
412 ) -> QueryResult<StatementUse<'conn, 'query>>
413 where
414 T: QueryFragment<Sqlite> + QueryId + 'query,
415 {
416 self.instrumentation
417 .on_connection_event(InstrumentationEvent::StartQuery {
418 query: &crate::debug_query(&source),
419 });
420 let raw_connection = &self.raw_connection;
421 let cache = &mut self.statement_cache;
422 let statement = match cache.cached_statement(
423 &source,
424 &Sqlite,
425 &[],
426 raw_connection,
427 Statement::prepare,
428 &mut *self.instrumentation,
429 ) {
430 Ok(statement) => statement,
431 Err(e) => {
432 self.instrumentation
433 .on_connection_event(InstrumentationEvent::FinishQuery {
434 query: &crate::debug_query(&source),
435 error: Some(&e),
436 });
437
438 return Err(e);
439 }
440 };
441
442 StatementUse::bind(statement, source, &mut *self.instrumentation)
443 }
444
445 #[doc(hidden)]
446 pub fn register_sql_function<ArgsSqlType, RetSqlType, Args, Ret, F>(
447 &mut self,
448 fn_name: &str,
449 deterministic: bool,
450 mut f: F,
451 ) -> QueryResult<()>
452 where
453 F: FnMut(Args) -> Ret + std::panic::UnwindSafe + Send + 'static,
454 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
455 Ret: ToSql<RetSqlType, Sqlite>,
456 Sqlite: HasSqlType<RetSqlType>,
457 {
458 functions::register(
459 &self.raw_connection,
460 fn_name,
461 deterministic,
462 move |_, args| f(args),
463 )
464 }
465
466 #[doc(hidden)]
467 pub fn register_noarg_sql_function<RetSqlType, Ret, F>(
468 &self,
469 fn_name: &str,
470 deterministic: bool,
471 f: F,
472 ) -> QueryResult<()>
473 where
474 F: FnMut() -> Ret + std::panic::UnwindSafe + Send + 'static,
475 Ret: ToSql<RetSqlType, Sqlite>,
476 Sqlite: HasSqlType<RetSqlType>,
477 {
478 functions::register_noargs(&self.raw_connection, fn_name, deterministic, f)
479 }
480
481 #[doc(hidden)]
482 pub fn register_aggregate_function<ArgsSqlType, RetSqlType, Args, Ret, A>(
483 &mut self,
484 fn_name: &str,
485 ) -> QueryResult<()>
486 where
487 A: SqliteAggregateFunction<Args, Output = Ret> + 'static + Send + std::panic::UnwindSafe,
488 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
489 Ret: ToSql<RetSqlType, Sqlite>,
490 Sqlite: HasSqlType<RetSqlType>,
491 {
492 functions::register_aggregate::<_, _, _, _, A>(&self.raw_connection, fn_name)
493 }
494
495 pub fn register_collation<F>(&mut self, collation_name: &str, collation: F) -> QueryResult<()>
531 where
532 F: Fn(&str, &str) -> std::cmp::Ordering + Send + 'static + std::panic::UnwindSafe,
533 {
534 self.raw_connection
535 .register_collation_function(collation_name, collation)
536 }
537
538 pub fn serialize_database_to_buffer(&mut self) -> SerializedDatabase {
549 self.raw_connection.serialize()
550 }
551
552 #[allow(unsafe_code)]
592 pub fn deserialize_readonly_database_from_buffer(&mut self, data: &[u8]) -> QueryResult<()> {
593 self.serialized_data.push(data.to_vec());
596 let last = self
597 .serialized_data
598 .last()
599 .expect("We literally pushed it above, so it's there");
600 unsafe {
601 self.raw_connection.deserialize(last)
604 }
605 }
606
607 fn register_diesel_sql_functions(&self) -> QueryResult<()> {
608 use crate::sql_types::{Integer, Text};
609
610 functions::register::<Text, Integer, _, _, _>(
614 &self.raw_connection,
615 "diesel_manage_updated_at",
616 false,
617 |conn, table_name: String| {
618 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))
})format!(
619 include_str!("diesel_manage_updated_at.sql"),
620 table_name = table_name
621 ))
622 .expect("Failed to create trigger");
623 0 },
625 )
626 }
627
628 fn establish_inner(database_url: &str) -> Result<SqliteConnection, ConnectionError> {
629 use crate::result::ConnectionError::CouldntSetupConfiguration;
630 let raw_connection = RawConnection::establish(database_url)?;
631 let conn = Self {
632 statement_cache: StatementCache::new(),
633 raw_connection,
634 transaction_state: AnsiTransactionManager::default(),
635 metadata_lookup: (),
636 instrumentation: DynInstrumentation::none(),
637 serialized_data: Vec::new(),
638 };
639 conn.register_diesel_sql_functions()
640 .map_err(CouldntSetupConfiguration)?;
641 Ok(conn)
642 }
643}
644
645fn error_message(err_code: libc::c_int) -> &'static str {
646 ffi::code_to_str(err_code)
647}
648
649#[cfg(test)]
650mod tests {
651 use super::*;
652 use crate::dsl::sql;
653 use crate::prelude::*;
654 use crate::sql_types::{Integer, Text};
655
656 fn connection() -> SqliteConnection {
657 SqliteConnection::establish(":memory:").unwrap()
658 }
659
660 #[declare_sql_function]
661 extern "SQL" {
662 fn fun_case(x: Text) -> Text;
663 fn my_add(x: Integer, y: Integer) -> Integer;
664 fn answer() -> Integer;
665 fn add_counter(x: Integer) -> Integer;
666
667 #[aggregate]
668 fn my_sum(expr: Integer) -> Integer;
669 #[aggregate]
670 fn range_max(expr1: Integer, expr2: Integer, expr3: Integer) -> Nullable<Integer>;
671 }
672
673 #[diesel_test_helper::test]
674 fn database_serializes_and_deserializes_successfully() {
675 let expected_users = vec![
676 (
677 1,
678 "John Doe".to_string(),
679 "john.doe@example.com".to_string(),
680 ),
681 (
682 2,
683 "Jane Doe".to_string(),
684 "jane.doe@example.com".to_string(),
685 ),
686 ];
687
688 let conn1 = &mut connection();
689 let _ =
690 crate::sql_query("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
691 .execute(conn1);
692 let _ = crate::sql_query("INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com'), ('Jane Doe', 'jane.doe@example.com')")
693 .execute(conn1);
694
695 for _i in 0..2 {
696 let serialized_database = conn1.serialize_database_to_buffer();
697 let conn2 = &mut connection();
698 conn2
699 .deserialize_readonly_database_from_buffer(
700 serialized_database.try_as_slice().unwrap(),
701 )
702 .unwrap();
703
704 let query =
705 sql::<(Integer, Text, Text)>("SELECT id, name, email FROM users ORDER BY id");
706 let actual_users = query.load::<(i32, String, String)>(conn2).unwrap();
707
708 assert_eq!(expected_users, actual_users);
709 std::mem::drop(serialized_database);
713 let query =
714 sql::<(Integer, Text, Text)>("SELECT id, name, email FROM users ORDER BY id");
715 let actual_users = query.load::<(i32, String, String)>(conn2).unwrap();
716
717 assert_eq!(expected_users, actual_users);
718 }
719 }
720
721 #[diesel_test_helper::test]
722 fn database_deserialize_random_bytes() {
723 let buffer = vec![0, 1, 2, 3, 4];
724 let conn = &mut SqliteConnection::establish(":memory:").unwrap();
725
726 conn.deserialize_readonly_database_from_buffer(&buffer)
727 .unwrap();
728
729 let r = sql::<Integer>("SELECT id FROM users").load::<i32>(conn);
730
731 assert!(r.is_err());
732 assert_eq!(r.unwrap_err().to_string(), "file is not a database");
733
734 let conn = &mut SqliteConnection::establish(":memory:").unwrap();
735
736 let _ =
737 crate::sql_query("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
738 .execute(conn);
739 let _ = crate::sql_query("INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com'), ('Jane Doe', 'jane.doe@example.com')")
740 .execute(conn);
741
742 let db = conn.serialize_database_to_buffer();
743 let mut bad_buffer = db[..100].to_vec();
745 bad_buffer.extend(b"whatever");
746 conn.deserialize_readonly_database_from_buffer(&bad_buffer)
747 .unwrap();
748
749 let r = sql::<Integer>("SELECT id FROM users").load::<i32>(conn);
750
751 assert!(r.is_err());
752 assert_eq!(
753 r.unwrap_err().to_string(),
754 "database disk image is malformed"
755 );
756
757 let mut size_fitting_bad_buffer = db[..100].to_vec();
759 size_fitting_bad_buffer.extend(
760 core::iter::repeat(b"abcdefghij")
761 .flatten()
762 .take(db.len() - 100),
763 );
764 let r = conn.deserialize_readonly_database_from_buffer(&size_fitting_bad_buffer);
765
766 assert!(r.is_err());
767 assert_eq!(
768 r.unwrap_err().to_string(),
769 "database disk image is malformed"
770 );
771 }
772
773 #[diesel_test_helper::test]
774 fn database_serializes_empty_deserialized_database() {
775 let conn = &mut SqliteConnection::establish(":memory:").unwrap();
776 conn.deserialize_readonly_database_from_buffer(&[]).unwrap();
777
778 let serialized = conn.serialize_database_to_buffer();
779
780 assert!(serialized.is_empty());
781 assert!(serialized.try_as_slice().unwrap().is_empty());
782 }
783
784 #[cfg(not(all(target_family = "wasm", target_os = "unknown")))]
785 #[allow(unsafe_code)]
786 mod sqlite_serialize_oom {
787 use super::super::oom_test_support::{panic_message, run_in_child, with_heap_limit};
788 use super::super::{ffi, SerializedDatabase};
789 use crate::connection::{Connection, SimpleConnection};
790 use crate::sqlite::SqliteConnection;
791
792 const MIN_DATABASE_BYTES: i64 = 1_048_576;
793
794 fn with_failing_serialize<R>(f: impl FnOnce() -> R) -> R {
797 with_heap_limit(65_536, f)
798 }
799
800 #[test]
801 fn sqlite_serialize_oom_is_contained() {
802 run_in_child(|| {
803 let mut conn = large_database();
804
805 let (baseline_size, baseline) = serialize_direct(&conn);
806 assert!(
807 baseline_size >= MIN_DATABASE_BYTES,
808 "the serialized database is smaller than 1 MiB"
809 );
810 assert!(
811 !baseline.is_null(),
812 "SQLite refused to serialize a valid database"
813 );
814 unsafe { ffi::sqlite3_free(baseline as _) };
816
817 let (reported_size, data) = with_failing_serialize(|| serialize_direct(&conn));
818 if !data.is_null() {
819 unsafe { ffi::sqlite3_free(data as _) };
821 }
822 assert!(
823 data.is_null(),
824 "SQLite did not fail the output allocation of the serialization"
825 );
826 assert!(
828 reported_size >= MIN_DATABASE_BYTES,
829 "SQLite reported a serialization size of {reported_size} with a null buffer"
830 );
831
832 let serialized: SerializedDatabase =
833 with_failing_serialize(|| conn.serialize_database_to_buffer());
834 let error = serialized
835 .try_as_slice()
836 .expect_err("the failed output allocation must surface as an error");
837 assert_eq!(error.to_string(), "out of memory");
838
839 let payload = std::panic::catch_unwind(core::panic::AssertUnwindSafe(|| {
840 core::hint::black_box(serialized[0]);
841 }))
842 .expect_err("the serialized database access did not panic");
843 let message = panic_message(&*payload);
844 assert!(
845 message.contains("Cannot access the serialized database: out of memory"),
846 "SQLite serialization allocation failure surfaced as `{message}` instead \
847 of a caught allocation panic"
848 );
849 });
850 }
851
852 fn large_database() -> SqliteConnection {
853 let mut conn = SqliteConnection::establish(":memory:").unwrap();
854 conn.batch_execute(&format!(
855 "CREATE TABLE blobs (id INTEGER PRIMARY KEY, payload BLOB);
856 INSERT INTO blobs (payload) VALUES (zeroblob({MIN_DATABASE_BYTES}));"
857 ))
858 .unwrap();
859 conn
860 }
861
862 fn serialize_direct(conn: &SqliteConnection) -> (ffi::sqlite3_int64, *mut u8) {
863 unsafe {
865 let mut size: ffi::sqlite3_int64 = 0;
866 let data = ffi::sqlite3_serialize(
867 conn.raw_connection.internal_connection.as_ptr(),
868 core::ptr::null(),
869 &mut size as *mut _,
870 0,
871 );
872 (size, data)
873 }
874 }
875 }
876
877 #[diesel_test_helper::test]
878 fn register_custom_function() {
879 let connection = &mut connection();
880 fun_case_utils::register_impl(connection, |x: String| {
881 x.chars()
882 .enumerate()
883 .map(|(i, c)| {
884 if i % 2 == 0 {
885 c.to_lowercase().to_string()
886 } else {
887 c.to_uppercase().to_string()
888 }
889 })
890 .collect::<String>()
891 })
892 .unwrap();
893
894 let mapped_string = crate::select(fun_case("foobar"))
895 .get_result::<String>(connection)
896 .unwrap();
897 assert_eq!("fOoBaR", mapped_string);
898 }
899
900 #[diesel_test_helper::test]
901 fn register_multiarg_function() {
902 let connection = &mut connection();
903 my_add_utils::register_impl(connection, |x: i32, y: i32| x + y).unwrap();
904
905 let added = crate::select(my_add(1, 2)).get_result::<i32>(connection);
906 assert_eq!(Ok(3), added);
907 }
908
909 #[diesel_test_helper::test]
910 fn register_noarg_function() {
911 let connection = &mut connection();
912 answer_utils::register_impl(connection, || 42).unwrap();
913
914 let answer = crate::select(answer()).get_result::<i32>(connection);
915 assert_eq!(Ok(42), answer);
916 }
917
918 #[diesel_test_helper::test]
919 fn register_nondeterministic_noarg_function() {
920 let connection = &mut connection();
921 answer_utils::register_nondeterministic_impl(connection, || 42).unwrap();
922
923 let answer = crate::select(answer()).get_result::<i32>(connection);
924 assert_eq!(Ok(42), answer);
925 }
926
927 #[diesel_test_helper::test]
928 fn register_nondeterministic_function() {
929 let connection = &mut connection();
930 let mut y = 0;
931 add_counter_utils::register_nondeterministic_impl(connection, move |x: i32| {
932 y += 1;
933 x + y
934 })
935 .unwrap();
936
937 let added = crate::select((add_counter(1), add_counter(1), add_counter(1)))
938 .get_result::<(i32, i32, i32)>(connection);
939 assert_eq!(Ok((2, 3, 4)), added);
940 }
941
942 #[derive(Default)]
943 struct MySum {
944 sum: i32,
945 }
946
947 impl SqliteAggregateFunction<i32> for MySum {
948 type Output = i32;
949
950 fn step(&mut self, expr: i32) {
951 self.sum += expr;
952 }
953
954 fn finalize(aggregator: Option<Self>) -> Self::Output {
955 aggregator.map(|a| a.sum).unwrap_or_default()
956 }
957 }
958
959 table! {
960 my_sum_example {
961 id -> Integer,
962 value -> Integer,
963 }
964 }
965
966 #[diesel_test_helper::test]
967 fn register_aggregate_function() {
968 use self::my_sum_example::dsl::*;
969
970 let connection = &mut connection();
971 crate::sql_query(
972 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
973 )
974 .execute(connection)
975 .unwrap();
976 crate::sql_query("INSERT INTO my_sum_example (value) VALUES (1), (2), (3)")
977 .execute(connection)
978 .unwrap();
979
980 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
981
982 let result = my_sum_example
983 .select(my_sum(value))
984 .get_result::<i32>(connection);
985 assert_eq!(Ok(6), result);
986 }
987
988 #[diesel_test_helper::test]
989 fn register_aggregate_function_returns_finalize_default_on_empty_set() {
990 use self::my_sum_example::dsl::*;
991
992 let connection = &mut connection();
993 crate::sql_query(
994 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
995 )
996 .execute(connection)
997 .unwrap();
998
999 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
1000
1001 let result = my_sum_example
1002 .select(my_sum(value))
1003 .get_result::<i32>(connection);
1004 assert_eq!(Ok(0), result);
1005 }
1006
1007 #[derive(Default)]
1008 struct RangeMax<T> {
1009 max_value: Option<T>,
1010 }
1011
1012 impl<T: Default + Ord + Copy + Clone> SqliteAggregateFunction<(T, T, T)> for RangeMax<T> {
1013 type Output = Option<T>;
1014
1015 fn step(&mut self, (x0, x1, x2): (T, T, T)) {
1016 let max = if x0 >= x1 && x0 >= x2 {
1017 x0
1018 } else if x1 >= x0 && x1 >= x2 {
1019 x1
1020 } else {
1021 x2
1022 };
1023
1024 self.max_value = match self.max_value {
1025 Some(current_max_value) if max > current_max_value => Some(max),
1026 None => Some(max),
1027 _ => self.max_value,
1028 };
1029 }
1030
1031 fn finalize(aggregator: Option<Self>) -> Self::Output {
1032 aggregator?.max_value
1033 }
1034 }
1035
1036 table! {
1037 range_max_example {
1038 id -> Integer,
1039 value1 -> Integer,
1040 value2 -> Integer,
1041 value3 -> Integer,
1042 }
1043 }
1044
1045 #[diesel_test_helper::test]
1046 fn register_aggregate_multiarg_function() {
1047 use self::range_max_example::dsl::*;
1048
1049 let connection = &mut connection();
1050 crate::sql_query(
1051 r#"CREATE TABLE range_max_example (
1052 id integer primary key autoincrement,
1053 value1 integer,
1054 value2 integer,
1055 value3 integer
1056 )"#,
1057 )
1058 .execute(connection)
1059 .unwrap();
1060 crate::sql_query(
1061 "INSERT INTO range_max_example (value1, value2, value3) VALUES (3, 2, 1), (2, 2, 2)",
1062 )
1063 .execute(connection)
1064 .unwrap();
1065
1066 range_max_utils::register_impl::<RangeMax<i32>, _, _, _>(connection).unwrap();
1067 let result = range_max_example
1068 .select(range_max(value1, value2, value3))
1069 .get_result::<Option<i32>>(connection)
1070 .unwrap();
1071 assert_eq!(Some(3), result);
1072 }
1073
1074 table! {
1075 my_collation_example {
1076 id -> Integer,
1077 value -> Text,
1078 }
1079 }
1080
1081 #[diesel_test_helper::test]
1082 fn register_collation_function() {
1083 use self::my_collation_example::dsl::*;
1084
1085 let connection = &mut connection();
1086
1087 connection
1088 .register_collation("RUSTNOCASE", |rhs, lhs| {
1089 rhs.to_lowercase().cmp(&lhs.to_lowercase())
1090 })
1091 .unwrap();
1092
1093 crate::sql_query(
1094 "CREATE TABLE my_collation_example (id integer primary key autoincrement, value text collate RUSTNOCASE)",
1095 ).execute(connection)
1096 .unwrap();
1097 crate::sql_query(
1098 "INSERT INTO my_collation_example (value) VALUES ('foo'), ('FOo'), ('f00')",
1099 )
1100 .execute(connection)
1101 .unwrap();
1102
1103 let result = my_collation_example
1104 .filter(value.eq("foo"))
1105 .select(value)
1106 .load::<String>(connection);
1107 assert_eq!(
1108 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
1109 result.as_ref().map(|vec| vec.as_ref())
1110 );
1111
1112 let result = my_collation_example
1113 .filter(value.eq("FOO"))
1114 .select(value)
1115 .load::<String>(connection);
1116 assert_eq!(
1117 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
1118 result.as_ref().map(|vec| vec.as_ref())
1119 );
1120
1121 let result = my_collation_example
1122 .filter(value.eq("f00"))
1123 .select(value)
1124 .load::<String>(connection);
1125 assert_eq!(
1126 Ok(&["f00".to_owned()][..]),
1127 result.as_ref().map(|vec| vec.as_ref())
1128 );
1129
1130 let result = my_collation_example
1131 .filter(value.eq("F00"))
1132 .select(value)
1133 .load::<String>(connection);
1134 assert_eq!(
1135 Ok(&["f00".to_owned()][..]),
1136 result.as_ref().map(|vec| vec.as_ref())
1137 );
1138
1139 let result = my_collation_example
1140 .filter(value.eq("oof"))
1141 .select(value)
1142 .load::<String>(connection);
1143 assert_eq!(Ok(&[][..]), result.as_ref().map(|vec| vec.as_ref()));
1144 }
1145
1146 #[diesel_test_helper::test]
1148 fn test_correct_serialization_of_owned_strings() {
1149 use crate::prelude::*;
1150
1151 #[derive(Debug, crate::expression::AsExpression)]
1152 #[diesel(sql_type = diesel::sql_types::Text)]
1153 struct CustomWrapper(String);
1154
1155 impl crate::serialize::ToSql<Text, Sqlite> for CustomWrapper {
1156 fn to_sql<'b>(
1157 &'b self,
1158 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
1159 ) -> crate::serialize::Result {
1160 out.set_value(self.0.to_string());
1161 Ok(crate::serialize::IsNull::No)
1162 }
1163 }
1164
1165 let connection = &mut connection();
1166
1167 let res = crate::select(
1168 CustomWrapper("".into())
1169 .into_sql::<crate::sql_types::Text>()
1170 .nullable(),
1171 )
1172 .get_result::<Option<String>>(connection)
1173 .unwrap();
1174 assert_eq!(res, Some(String::new()));
1175 }
1176
1177 #[diesel_test_helper::test]
1178 fn test_correct_serialization_of_owned_bytes() {
1179 use crate::prelude::*;
1180
1181 #[derive(Debug, crate::expression::AsExpression)]
1182 #[diesel(sql_type = diesel::sql_types::Binary)]
1183 struct CustomWrapper(Vec<u8>);
1184
1185 impl crate::serialize::ToSql<crate::sql_types::Binary, Sqlite> for CustomWrapper {
1186 fn to_sql<'b>(
1187 &'b self,
1188 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
1189 ) -> crate::serialize::Result {
1190 out.set_value(self.0.clone());
1191 Ok(crate::serialize::IsNull::No)
1192 }
1193 }
1194
1195 let connection = &mut connection();
1196
1197 let res = crate::select(
1198 CustomWrapper(Vec::new())
1199 .into_sql::<crate::sql_types::Binary>()
1200 .nullable(),
1201 )
1202 .get_result::<Option<Vec<u8>>>(connection)
1203 .unwrap();
1204 assert_eq!(res, Some(Vec::new()));
1205 }
1206
1207 #[diesel_test_helper::test]
1208 fn correctly_handle_empty_query() {
1209 let check_empty_query_error = |r: crate::QueryResult<usize>| {
1210 assert!(r.is_err());
1211 let err = r.unwrap_err();
1212 assert!(
1213 matches!(err, crate::result::Error::QueryBuilderError(ref b) if b.is::<crate::result::EmptyQuery>()),
1214 "Expected a query builder error, but got {err}"
1215 );
1216 };
1217 let connection = &mut SqliteConnection::establish(":memory:").unwrap();
1218 check_empty_query_error(crate::sql_query("").execute(connection));
1219 check_empty_query_error(crate::sql_query(" ").execute(connection));
1220 check_empty_query_error(crate::sql_query("\n\t").execute(connection));
1221 check_empty_query_error(crate::sql_query("-- SELECT 1;").execute(connection));
1222 }
1223
1224 #[diesel_test_helper::test]
1225 fn aggregate_function_works_with_aligned_data() {
1226 #[derive(Debug, Default)]
1227 #[repr(align(64))]
1228 struct OverAligned;
1229
1230 impl SqliteAggregateFunction<i32> for OverAligned {
1231 type Output = i64;
1232
1233 fn step(&mut self, _value: i32) {
1234 let need = core::mem::align_of::<Self>();
1235 let got = core::mem::align_of_val(self);
1236 assert_eq!(need, got);
1237 }
1238
1239 fn finalize(_agg: Option<Self>) -> i64 {
1240 0
1241 }
1242 }
1243 #[declare_sql_function]
1244 extern "SQL" {
1245 #[aggregate]
1246 fn over_aligned_sum(x: Integer) -> diesel::sql_types::BigInt;
1247 }
1248
1249 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1250 over_aligned_sum_utils::register_impl::<OverAligned, _>(&mut conn).unwrap();
1251
1252 diesel::select(over_aligned_sum(1))
1253 .execute(&mut conn)
1254 .unwrap();
1255 }
1256
1257 #[diesel_test_helper::test]
1258 fn sum_twice() {
1259 #[derive(Default)]
1260 struct Sum(i32);
1261
1262 impl SqliteAggregateFunction<i32> for Sum {
1263 type Output = i32;
1264
1265 fn step(&mut self, value: i32) {
1266 self.0 += value;
1267 }
1268
1269 fn finalize(agg: Option<Self>) -> i32 {
1270 agg.map(|s| s.0).unwrap_or_default()
1271 }
1272 }
1273
1274 #[declare_sql_function]
1275 extern "SQL" {
1276 #[aggregate]
1277 fn my_sum(x: Integer) -> Integer;
1278 }
1279
1280 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1281 my_sum_utils::register_impl::<Sum, _>(&mut conn).unwrap();
1282
1283 conn.batch_execute(
1284 "
1285 CREATE TABLE test(key1 INTEGER, key2 INTEGER);
1286 INSERT INTO test(key1, key2) VALUES (1, 2), (2, 4), (3, 6);
1287",
1288 )
1289 .unwrap();
1290
1291 table! {
1292 test (key1, key2) {
1293 key1 -> Integer,
1294 key2 -> Integer,
1295 }
1296 }
1297
1298 let (first_res, second_res) = test::table
1299 .select((my_sum(test::key1), my_sum(test::key2)))
1300 .get_result::<(i32, i32)>(&mut conn)
1301 .unwrap();
1302
1303 assert_eq!(first_res, 6);
1304 assert_eq!(second_res, 12);
1305
1306 conn.batch_execute("DELETE FROM test").unwrap();
1307 let (first_res, second_res) = test::table
1308 .select((my_sum(test::key1), my_sum(test::key2)))
1309 .get_result::<(i32, i32)>(&mut conn)
1310 .unwrap();
1311
1312 assert_eq!(first_res, 0);
1313 assert_eq!(second_res, 0);
1314 }
1315
1316 #[diesel_test_helper::test]
1317 fn test_injection() {
1318 diesel::table! {
1319 #[sql_name = "quote'table"]
1320 quote_table (id) {
1321 id -> Nullable<Integer>,
1322 name -> Nullable<Text>,
1323 }
1324 }
1325
1326 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1327
1328 conn.batch_execute("CREATE TABLE \"quote'table\" (id INTEGER PRIMARY KEY, name TEXT);")
1329 .unwrap();
1330
1331 diesel::insert_into(quote_table::table)
1332 .values((quote_table::id.eq(1), quote_table::name.eq("Jane")))
1333 .execute(&mut conn)
1334 .unwrap();
1335
1336 let data = quote_table::table
1337 .load::<(Option<i32>, Option<String>)>(&mut conn)
1338 .unwrap();
1339 assert_eq!(data, [(Some(1), Some("Jane".to_owned()))]);
1340 }
1341}