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