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;
13mod sqlite_value;
14mod statement_iterator;
15mod stmt;
16
17pub(in crate::sqlite) use self::bind_collector::SqliteBindCollector;
18pub use self::bind_collector::SqliteBindValue;
19pub use self::serialized_database::SerializedDatabase;
20pub use self::sqlite_value::SqliteValue;
21
22use std::os::raw as libc;
23
24use self::raw::RawConnection;
25use self::statement_iterator::*;
26use self::stmt::{Statement, StatementUse};
27use super::SqliteAggregateFunction;
28use crate::connection::instrumentation::{DynInstrumentation, StrQueryHelper};
29use crate::connection::statement_cache::StatementCache;
30use crate::connection::*;
31use crate::deserialize::{FromSqlRow, StaticallySizedRow};
32use crate::expression::QueryMetadata;
33use crate::query_builder::*;
34use crate::result::*;
35use crate::serialize::ToSql;
36use crate::sql_types::{HasSqlType, TypeMetadata};
37use crate::sqlite::Sqlite;
38
39#[allow(missing_debug_implementations)]
162#[cfg(feature = "sqlite")]
163pub struct SqliteConnection {
164 statement_cache: StatementCache<Sqlite, Statement>,
168 raw_connection: RawConnection,
169 transaction_state: AnsiTransactionManager,
170 metadata_lookup: (),
173 instrumentation: DynInstrumentation,
174 serialized_data: Vec<u8>,
183}
184
185#[allow(unsafe_code)]
189unsafe impl Send for SqliteConnection {}
190
191impl SimpleConnection for SqliteConnection {
192 fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
193 self.instrumentation
194 .on_connection_event(InstrumentationEvent::StartQuery {
195 query: &StrQueryHelper::new(query),
196 });
197 let resp = self.raw_connection.exec(query);
198 self.instrumentation
199 .on_connection_event(InstrumentationEvent::FinishQuery {
200 query: &StrQueryHelper::new(query),
201 error: resp.as_ref().err(),
202 });
203 resp
204 }
205}
206
207impl ConnectionSealed for SqliteConnection {}
208
209impl Connection for SqliteConnection {
210 type Backend = Sqlite;
211 type TransactionManager = AnsiTransactionManager;
212
213 fn establish(database_url: &str) -> ConnectionResult<Self> {
229 let mut instrumentation = DynInstrumentation::default_instrumentation();
230 instrumentation.on_connection_event(InstrumentationEvent::StartEstablishConnection {
231 url: database_url,
232 });
233
234 let establish_result = Self::establish_inner(database_url);
235 instrumentation.on_connection_event(InstrumentationEvent::FinishEstablishConnection {
236 url: database_url,
237 error: establish_result.as_ref().err(),
238 });
239 let mut conn = establish_result?;
240 conn.instrumentation = instrumentation;
241 Ok(conn)
242 }
243
244 fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
245 where
246 T: QueryFragment<Self::Backend> + QueryId,
247 {
248 let statement_use = self.prepared_query(source)?;
249 statement_use.run().and_then(|_| {
250 self.raw_connection
251 .rows_affected_by_last_query()
252 .map_err(Error::DeserializationError)
253 })
254 }
255
256 fn transaction_state(&mut self) -> &mut AnsiTransactionManager
257 where
258 Self: Sized,
259 {
260 &mut self.transaction_state
261 }
262
263 fn instrumentation(&mut self) -> &mut dyn Instrumentation {
264 &mut *self.instrumentation
265 }
266
267 fn set_instrumentation(&mut self, instrumentation: impl Instrumentation) {
268 self.instrumentation = instrumentation.into();
269 }
270
271 fn set_prepared_statement_cache_size(&mut self, size: CacheSize) {
272 self.statement_cache.set_cache_size(size);
273 }
274}
275
276impl LoadConnection<DefaultLoadingMode> for SqliteConnection {
277 type Cursor<'conn, 'query> = StatementIterator<'conn, 'query>;
278 type Row<'conn, 'query> = self::row::SqliteRow<'conn, 'query>;
279
280 fn load<'conn, 'query, T>(
281 &'conn mut self,
282 source: T,
283 ) -> QueryResult<Self::Cursor<'conn, 'query>>
284 where
285 T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
286 Self::Backend: QueryMetadata<T::SqlType>,
287 {
288 let statement = self.prepared_query(source)?;
289
290 Ok(StatementIterator::new(statement))
291 }
292}
293
294impl WithMetadataLookup for SqliteConnection {
295 fn metadata_lookup(&mut self) -> &mut <Sqlite as TypeMetadata>::MetadataLookup {
296 &mut self.metadata_lookup
297 }
298}
299
300#[cfg(feature = "r2d2")]
301impl crate::r2d2::R2D2Connection for crate::sqlite::SqliteConnection {
302 fn ping(&mut self) -> QueryResult<()> {
303 use crate::RunQueryDsl;
304
305 crate::r2d2::CheckConnectionQuery.execute(self).map(|_| ())
306 }
307
308 fn is_broken(&mut self) -> bool {
309 AnsiTransactionManager::is_broken_transaction_manager(self)
310 }
311}
312
313impl MultiConnectionHelper for SqliteConnection {
314 fn to_any<'a>(
315 lookup: &mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup,
316 ) -> &mut (dyn std::any::Any + 'a) {
317 lookup
318 }
319
320 fn from_any(
321 lookup: &mut dyn std::any::Any,
322 ) -> Option<&mut <Self::Backend as crate::sql_types::TypeMetadata>::MetadataLookup> {
323 lookup.downcast_mut()
324 }
325}
326
327impl SqliteConnection {
328 pub fn immediate_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
350 where
351 F: FnOnce(&mut Self) -> Result<T, E>,
352 E: From<Error>,
353 {
354 self.transaction_sql(f, "BEGIN IMMEDIATE")
355 }
356
357 pub fn exclusive_transaction<T, E, F>(&mut self, f: F) -> Result<T, E>
379 where
380 F: FnOnce(&mut Self) -> Result<T, E>,
381 E: From<Error>,
382 {
383 self.transaction_sql(f, "BEGIN EXCLUSIVE")
384 }
385
386 fn transaction_sql<T, E, F>(&mut self, f: F, sql: &str) -> Result<T, E>
387 where
388 F: FnOnce(&mut Self) -> Result<T, E>,
389 E: From<Error>,
390 {
391 AnsiTransactionManager::begin_transaction_sql(&mut *self, sql)?;
392 match f(&mut *self) {
393 Ok(value) => {
394 AnsiTransactionManager::commit_transaction(&mut *self)?;
395 Ok(value)
396 }
397 Err(e) => {
398 AnsiTransactionManager::rollback_transaction(&mut *self)?;
399 Err(e)
400 }
401 }
402 }
403
404 fn prepared_query<'conn, 'query, T>(
405 &'conn mut self,
406 source: T,
407 ) -> QueryResult<StatementUse<'conn, 'query>>
408 where
409 T: QueryFragment<Sqlite> + QueryId + 'query,
410 {
411 self.instrumentation
412 .on_connection_event(InstrumentationEvent::StartQuery {
413 query: &crate::debug_query(&source),
414 });
415 let raw_connection = &self.raw_connection;
416 let cache = &mut self.statement_cache;
417 let statement = match cache.cached_statement(
418 &source,
419 &Sqlite,
420 &[],
421 raw_connection,
422 Statement::prepare,
423 &mut *self.instrumentation,
424 ) {
425 Ok(statement) => statement,
426 Err(e) => {
427 self.instrumentation
428 .on_connection_event(InstrumentationEvent::FinishQuery {
429 query: &crate::debug_query(&source),
430 error: Some(&e),
431 });
432
433 return Err(e);
434 }
435 };
436
437 StatementUse::bind(statement, source, &mut *self.instrumentation)
438 }
439
440 #[doc(hidden)]
441 pub fn register_sql_function<ArgsSqlType, RetSqlType, Args, Ret, F>(
442 &mut self,
443 fn_name: &str,
444 deterministic: bool,
445 mut f: F,
446 ) -> QueryResult<()>
447 where
448 F: FnMut(Args) -> Ret + std::panic::UnwindSafe + Send + 'static,
449 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
450 Ret: ToSql<RetSqlType, Sqlite>,
451 Sqlite: HasSqlType<RetSqlType>,
452 {
453 functions::register(
454 &self.raw_connection,
455 fn_name,
456 deterministic,
457 move |_, args| f(args),
458 )
459 }
460
461 #[doc(hidden)]
462 pub fn register_noarg_sql_function<RetSqlType, Ret, F>(
463 &self,
464 fn_name: &str,
465 deterministic: bool,
466 f: F,
467 ) -> QueryResult<()>
468 where
469 F: FnMut() -> Ret + std::panic::UnwindSafe + Send + 'static,
470 Ret: ToSql<RetSqlType, Sqlite>,
471 Sqlite: HasSqlType<RetSqlType>,
472 {
473 functions::register_noargs(&self.raw_connection, fn_name, deterministic, f)
474 }
475
476 #[doc(hidden)]
477 pub fn register_aggregate_function<ArgsSqlType, RetSqlType, Args, Ret, A>(
478 &mut self,
479 fn_name: &str,
480 ) -> QueryResult<()>
481 where
482 A: SqliteAggregateFunction<Args, Output = Ret> + 'static + Send + std::panic::UnwindSafe,
483 Args: FromSqlRow<ArgsSqlType, Sqlite> + StaticallySizedRow<ArgsSqlType, Sqlite>,
484 Ret: ToSql<RetSqlType, Sqlite>,
485 Sqlite: HasSqlType<RetSqlType>,
486 {
487 functions::register_aggregate::<_, _, _, _, A>(&self.raw_connection, fn_name)
488 }
489
490 pub fn register_collation<F>(&mut self, collation_name: &str, collation: F) -> QueryResult<()>
526 where
527 F: Fn(&str, &str) -> std::cmp::Ordering + Send + 'static + std::panic::UnwindSafe,
528 {
529 self.raw_connection
530 .register_collation_function(collation_name, collation)
531 }
532
533 pub fn serialize_database_to_buffer(&mut self) -> SerializedDatabase {
542 self.raw_connection.serialize()
543 }
544
545 pub fn deserialize_readonly_database_from_buffer(&mut self, data: &[u8]) -> QueryResult<()> {
582 self.serialized_data = data.to_vec();
585 self.raw_connection.deserialize(&self.serialized_data)
586 }
587
588 fn register_diesel_sql_functions(&self) -> QueryResult<()> {
589 use crate::sql_types::{Integer, Text};
590
591 functions::register::<Text, Integer, _, _, _>(
592 &self.raw_connection,
593 "diesel_manage_updated_at",
594 false,
595 |conn, table_name: String| {
596 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!(
597 include_str!("diesel_manage_updated_at.sql"),
598 table_name = table_name
599 ))
600 .expect("Failed to create trigger");
601 0 },
603 )
604 }
605
606 fn establish_inner(database_url: &str) -> Result<SqliteConnection, ConnectionError> {
607 use crate::result::ConnectionError::CouldntSetupConfiguration;
608 let raw_connection = RawConnection::establish(database_url)?;
609 let conn = Self {
610 statement_cache: StatementCache::new(),
611 raw_connection,
612 transaction_state: AnsiTransactionManager::default(),
613 metadata_lookup: (),
614 instrumentation: DynInstrumentation::none(),
615 serialized_data: Vec::new(),
616 };
617 conn.register_diesel_sql_functions()
618 .map_err(CouldntSetupConfiguration)?;
619 Ok(conn)
620 }
621}
622
623fn error_message(err_code: libc::c_int) -> &'static str {
624 ffi::code_to_str(err_code)
625}
626
627#[cfg(test)]
628mod tests {
629 use super::*;
630 use crate::dsl::sql;
631 use crate::prelude::*;
632 use crate::sql_types::{Integer, Text};
633
634 fn connection() -> SqliteConnection {
635 SqliteConnection::establish(":memory:").unwrap()
636 }
637
638 #[declare_sql_function]
639 extern "SQL" {
640 fn fun_case(x: Text) -> Text;
641 fn my_add(x: Integer, y: Integer) -> Integer;
642 fn answer() -> Integer;
643 fn add_counter(x: Integer) -> Integer;
644
645 #[aggregate]
646 fn my_sum(expr: Integer) -> Integer;
647 #[aggregate]
648 fn range_max(expr1: Integer, expr2: Integer, expr3: Integer) -> Nullable<Integer>;
649 }
650
651 #[diesel_test_helper::test]
652 fn database_serializes_and_deserializes_successfully() {
653 let expected_users = vec![
654 (
655 1,
656 "John Doe".to_string(),
657 "john.doe@example.com".to_string(),
658 ),
659 (
660 2,
661 "Jane Doe".to_string(),
662 "jane.doe@example.com".to_string(),
663 ),
664 ];
665
666 let conn1 = &mut connection();
667 let _ =
668 crate::sql_query("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)")
669 .execute(conn1);
670 let _ = crate::sql_query("INSERT INTO users (name, email) VALUES ('John Doe', 'john.doe@example.com'), ('Jane Doe', 'jane.doe@example.com')")
671 .execute(conn1);
672
673 let serialized_database = conn1.serialize_database_to_buffer();
674
675 let conn2 = &mut connection();
676 conn2
677 .deserialize_readonly_database_from_buffer(serialized_database.as_slice())
678 .unwrap();
679
680 let query = sql::<(Integer, Text, Text)>("SELECT id, name, email FROM users ORDER BY id");
681 let actual_users = query.load::<(i32, String, String)>(conn2).unwrap();
682
683 assert_eq!(expected_users, actual_users);
684 std::mem::drop(serialized_database);
688 let query = sql::<(Integer, Text, Text)>("SELECT id, name, email FROM users ORDER BY id");
689 let actual_users = query.load::<(i32, String, String)>(conn2).unwrap();
690
691 assert_eq!(expected_users, actual_users);
692 }
693
694 #[diesel_test_helper::test]
695 fn register_custom_function() {
696 let connection = &mut connection();
697 fun_case_utils::register_impl(connection, |x: String| {
698 x.chars()
699 .enumerate()
700 .map(|(i, c)| {
701 if i % 2 == 0 {
702 c.to_lowercase().to_string()
703 } else {
704 c.to_uppercase().to_string()
705 }
706 })
707 .collect::<String>()
708 })
709 .unwrap();
710
711 let mapped_string = crate::select(fun_case("foobar"))
712 .get_result::<String>(connection)
713 .unwrap();
714 assert_eq!("fOoBaR", mapped_string);
715 }
716
717 #[diesel_test_helper::test]
718 fn register_multiarg_function() {
719 let connection = &mut connection();
720 my_add_utils::register_impl(connection, |x: i32, y: i32| x + y).unwrap();
721
722 let added = crate::select(my_add(1, 2)).get_result::<i32>(connection);
723 assert_eq!(Ok(3), added);
724 }
725
726 #[diesel_test_helper::test]
727 fn register_noarg_function() {
728 let connection = &mut connection();
729 answer_utils::register_impl(connection, || 42).unwrap();
730
731 let answer = crate::select(answer()).get_result::<i32>(connection);
732 assert_eq!(Ok(42), answer);
733 }
734
735 #[diesel_test_helper::test]
736 fn register_nondeterministic_noarg_function() {
737 let connection = &mut connection();
738 answer_utils::register_nondeterministic_impl(connection, || 42).unwrap();
739
740 let answer = crate::select(answer()).get_result::<i32>(connection);
741 assert_eq!(Ok(42), answer);
742 }
743
744 #[diesel_test_helper::test]
745 fn register_nondeterministic_function() {
746 let connection = &mut connection();
747 let mut y = 0;
748 add_counter_utils::register_nondeterministic_impl(connection, move |x: i32| {
749 y += 1;
750 x + y
751 })
752 .unwrap();
753
754 let added = crate::select((add_counter(1), add_counter(1), add_counter(1)))
755 .get_result::<(i32, i32, i32)>(connection);
756 assert_eq!(Ok((2, 3, 4)), added);
757 }
758
759 #[derive(Default)]
760 struct MySum {
761 sum: i32,
762 }
763
764 impl SqliteAggregateFunction<i32> for MySum {
765 type Output = i32;
766
767 fn step(&mut self, expr: i32) {
768 self.sum += expr;
769 }
770
771 fn finalize(aggregator: Option<Self>) -> Self::Output {
772 aggregator.map(|a| a.sum).unwrap_or_default()
773 }
774 }
775
776 table! {
777 my_sum_example {
778 id -> Integer,
779 value -> Integer,
780 }
781 }
782
783 #[diesel_test_helper::test]
784 fn register_aggregate_function() {
785 use self::my_sum_example::dsl::*;
786
787 let connection = &mut connection();
788 crate::sql_query(
789 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
790 )
791 .execute(connection)
792 .unwrap();
793 crate::sql_query("INSERT INTO my_sum_example (value) VALUES (1), (2), (3)")
794 .execute(connection)
795 .unwrap();
796
797 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
798
799 let result = my_sum_example
800 .select(my_sum(value))
801 .get_result::<i32>(connection);
802 assert_eq!(Ok(6), result);
803 }
804
805 #[diesel_test_helper::test]
806 fn register_aggregate_function_returns_finalize_default_on_empty_set() {
807 use self::my_sum_example::dsl::*;
808
809 let connection = &mut connection();
810 crate::sql_query(
811 "CREATE TABLE my_sum_example (id integer primary key autoincrement, value integer)",
812 )
813 .execute(connection)
814 .unwrap();
815
816 my_sum_utils::register_impl::<MySum, _>(connection).unwrap();
817
818 let result = my_sum_example
819 .select(my_sum(value))
820 .get_result::<i32>(connection);
821 assert_eq!(Ok(0), result);
822 }
823
824 #[derive(Default)]
825 struct RangeMax<T> {
826 max_value: Option<T>,
827 }
828
829 impl<T: Default + Ord + Copy + Clone> SqliteAggregateFunction<(T, T, T)> for RangeMax<T> {
830 type Output = Option<T>;
831
832 fn step(&mut self, (x0, x1, x2): (T, T, T)) {
833 let max = if x0 >= x1 && x0 >= x2 {
834 x0
835 } else if x1 >= x0 && x1 >= x2 {
836 x1
837 } else {
838 x2
839 };
840
841 self.max_value = match self.max_value {
842 Some(current_max_value) if max > current_max_value => Some(max),
843 None => Some(max),
844 _ => self.max_value,
845 };
846 }
847
848 fn finalize(aggregator: Option<Self>) -> Self::Output {
849 aggregator?.max_value
850 }
851 }
852
853 table! {
854 range_max_example {
855 id -> Integer,
856 value1 -> Integer,
857 value2 -> Integer,
858 value3 -> Integer,
859 }
860 }
861
862 #[diesel_test_helper::test]
863 fn register_aggregate_multiarg_function() {
864 use self::range_max_example::dsl::*;
865
866 let connection = &mut connection();
867 crate::sql_query(
868 r#"CREATE TABLE range_max_example (
869 id integer primary key autoincrement,
870 value1 integer,
871 value2 integer,
872 value3 integer
873 )"#,
874 )
875 .execute(connection)
876 .unwrap();
877 crate::sql_query(
878 "INSERT INTO range_max_example (value1, value2, value3) VALUES (3, 2, 1), (2, 2, 2)",
879 )
880 .execute(connection)
881 .unwrap();
882
883 range_max_utils::register_impl::<RangeMax<i32>, _, _, _>(connection).unwrap();
884 let result = range_max_example
885 .select(range_max(value1, value2, value3))
886 .get_result::<Option<i32>>(connection)
887 .unwrap();
888 assert_eq!(Some(3), result);
889 }
890
891 table! {
892 my_collation_example {
893 id -> Integer,
894 value -> Text,
895 }
896 }
897
898 #[diesel_test_helper::test]
899 fn register_collation_function() {
900 use self::my_collation_example::dsl::*;
901
902 let connection = &mut connection();
903
904 connection
905 .register_collation("RUSTNOCASE", |rhs, lhs| {
906 rhs.to_lowercase().cmp(&lhs.to_lowercase())
907 })
908 .unwrap();
909
910 crate::sql_query(
911 "CREATE TABLE my_collation_example (id integer primary key autoincrement, value text collate RUSTNOCASE)",
912 ).execute(connection)
913 .unwrap();
914 crate::sql_query(
915 "INSERT INTO my_collation_example (value) VALUES ('foo'), ('FOo'), ('f00')",
916 )
917 .execute(connection)
918 .unwrap();
919
920 let result = my_collation_example
921 .filter(value.eq("foo"))
922 .select(value)
923 .load::<String>(connection);
924 assert_eq!(
925 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
926 result.as_ref().map(|vec| vec.as_ref())
927 );
928
929 let result = my_collation_example
930 .filter(value.eq("FOO"))
931 .select(value)
932 .load::<String>(connection);
933 assert_eq!(
934 Ok(&["foo".to_owned(), "FOo".to_owned()][..]),
935 result.as_ref().map(|vec| vec.as_ref())
936 );
937
938 let result = my_collation_example
939 .filter(value.eq("f00"))
940 .select(value)
941 .load::<String>(connection);
942 assert_eq!(
943 Ok(&["f00".to_owned()][..]),
944 result.as_ref().map(|vec| vec.as_ref())
945 );
946
947 let result = my_collation_example
948 .filter(value.eq("F00"))
949 .select(value)
950 .load::<String>(connection);
951 assert_eq!(
952 Ok(&["f00".to_owned()][..]),
953 result.as_ref().map(|vec| vec.as_ref())
954 );
955
956 let result = my_collation_example
957 .filter(value.eq("oof"))
958 .select(value)
959 .load::<String>(connection);
960 assert_eq!(Ok(&[][..]), result.as_ref().map(|vec| vec.as_ref()));
961 }
962
963 #[diesel_test_helper::test]
965 fn test_correct_serialization_of_owned_strings() {
966 use crate::prelude::*;
967
968 #[derive(Debug, crate::expression::AsExpression)]
969 #[diesel(sql_type = diesel::sql_types::Text)]
970 struct CustomWrapper(String);
971
972 impl crate::serialize::ToSql<Text, Sqlite> for CustomWrapper {
973 fn to_sql<'b>(
974 &'b self,
975 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
976 ) -> crate::serialize::Result {
977 out.set_value(self.0.to_string());
978 Ok(crate::serialize::IsNull::No)
979 }
980 }
981
982 let connection = &mut connection();
983
984 let res = crate::select(
985 CustomWrapper("".into())
986 .into_sql::<crate::sql_types::Text>()
987 .nullable(),
988 )
989 .get_result::<Option<String>>(connection)
990 .unwrap();
991 assert_eq!(res, Some(String::new()));
992 }
993
994 #[diesel_test_helper::test]
995 fn test_correct_serialization_of_owned_bytes() {
996 use crate::prelude::*;
997
998 #[derive(Debug, crate::expression::AsExpression)]
999 #[diesel(sql_type = diesel::sql_types::Binary)]
1000 struct CustomWrapper(Vec<u8>);
1001
1002 impl crate::serialize::ToSql<crate::sql_types::Binary, Sqlite> for CustomWrapper {
1003 fn to_sql<'b>(
1004 &'b self,
1005 out: &mut crate::serialize::Output<'b, '_, Sqlite>,
1006 ) -> crate::serialize::Result {
1007 out.set_value(self.0.clone());
1008 Ok(crate::serialize::IsNull::No)
1009 }
1010 }
1011
1012 let connection = &mut connection();
1013
1014 let res = crate::select(
1015 CustomWrapper(Vec::new())
1016 .into_sql::<crate::sql_types::Binary>()
1017 .nullable(),
1018 )
1019 .get_result::<Option<Vec<u8>>>(connection)
1020 .unwrap();
1021 assert_eq!(res, Some(Vec::new()));
1022 }
1023
1024 #[diesel_test_helper::test]
1025 fn correctly_handle_empty_query() {
1026 let check_empty_query_error = |r: crate::QueryResult<usize>| {
1027 assert!(r.is_err());
1028 let err = r.unwrap_err();
1029 assert!(
1030 matches!(err, crate::result::Error::QueryBuilderError(ref b) if b.is::<crate::result::EmptyQuery>()),
1031 "Expected a query builder error, but got {err}"
1032 );
1033 };
1034 let connection = &mut SqliteConnection::establish(":memory:").unwrap();
1035 check_empty_query_error(crate::sql_query("").execute(connection));
1036 check_empty_query_error(crate::sql_query(" ").execute(connection));
1037 check_empty_query_error(crate::sql_query("\n\t").execute(connection));
1038 check_empty_query_error(crate::sql_query("-- SELECT 1;").execute(connection));
1039 }
1040
1041 #[diesel_test_helper::test]
1042 fn aggregate_function_works_with_aligned_data() {
1043 #[derive(Debug, Default)]
1044 #[repr(align(64))]
1045 struct OverAligned;
1046
1047 impl SqliteAggregateFunction<i32> for OverAligned {
1048 type Output = i64;
1049
1050 fn step(&mut self, _value: i32) {
1051 let need = core::mem::align_of::<Self>();
1052 let got = core::mem::align_of_val(self);
1053 assert_eq!(need, got);
1054 }
1055
1056 fn finalize(_agg: Option<Self>) -> i64 {
1057 0
1058 }
1059 }
1060 #[declare_sql_function]
1061 extern "SQL" {
1062 #[aggregate]
1063 fn over_aligned_sum(x: Integer) -> diesel::sql_types::BigInt;
1064 }
1065
1066 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1067 over_aligned_sum_utils::register_impl::<OverAligned, _>(&mut conn).unwrap();
1068
1069 diesel::select(over_aligned_sum(1))
1070 .execute(&mut conn)
1071 .unwrap();
1072 }
1073
1074 #[diesel_test_helper::test]
1075 fn sum_twice() {
1076 #[derive(Default)]
1077 struct Sum(i32);
1078
1079 impl SqliteAggregateFunction<i32> for Sum {
1080 type Output = i32;
1081
1082 fn step(&mut self, value: i32) {
1083 self.0 += value;
1084 }
1085
1086 fn finalize(agg: Option<Self>) -> i32 {
1087 agg.map(|s| s.0).unwrap_or_default()
1088 }
1089 }
1090
1091 #[declare_sql_function]
1092 extern "SQL" {
1093 #[aggregate]
1094 fn my_sum(x: Integer) -> Integer;
1095 }
1096
1097 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1098 my_sum_utils::register_impl::<Sum, _>(&mut conn).unwrap();
1099
1100 conn.batch_execute(
1101 "
1102 CREATE TABLE test(key1 INTEGER, key2 INTEGER);
1103 INSERT INTO test(key1, key2) VALUES (1, 2), (2, 4), (3, 6);
1104",
1105 )
1106 .unwrap();
1107
1108 table! {
1109 test (key1, key2) {
1110 key1 -> Integer,
1111 key2 -> Integer,
1112 }
1113 }
1114
1115 let (first_res, second_res) = test::table
1116 .select((my_sum(test::key1), my_sum(test::key2)))
1117 .get_result::<(i32, i32)>(&mut conn)
1118 .unwrap();
1119
1120 assert_eq!(first_res, 6);
1121 assert_eq!(second_res, 12);
1122
1123 conn.batch_execute("DELETE FROM test").unwrap();
1124 let (first_res, second_res) = test::table
1125 .select((my_sum(test::key1), my_sum(test::key2)))
1126 .get_result::<(i32, i32)>(&mut conn)
1127 .unwrap();
1128
1129 assert_eq!(first_res, 0);
1130 assert_eq!(second_res, 0);
1131 }
1132
1133 #[diesel_test_helper::test]
1134 fn test_injection() {
1135 diesel::table! {
1136 #[sql_name = "quote'table"]
1137 quote_table (id) {
1138 id -> Nullable<Integer>,
1139 name -> Nullable<Text>,
1140 }
1141 }
1142
1143 let mut conn = SqliteConnection::establish(":memory:").unwrap();
1144
1145 conn.batch_execute("CREATE TABLE \"quote'table\" (id INTEGER PRIMARY KEY, name TEXT);")
1146 .unwrap();
1147
1148 diesel::insert_into(quote_table::table)
1149 .values((quote_table::id.eq(1), quote_table::name.eq("Jane")))
1150 .execute(&mut conn)
1151 .unwrap();
1152
1153 let data = quote_table::table
1154 .load::<(Option<i32>, Option<String>)>(&mut conn)
1155 .unwrap();
1156 assert_eq!(data, [(Some(1), Some("Jane".to_owned()))]);
1157 }
1158}