1use error_context::prelude::*;
341use lazy_static::lazy_static;
342use odbc::{DiagnosticRecord, DriverInfo, Environment, Version3};
343use regex::Regex;
344use std::error::Error;
345use std::fmt;
346use std::sync::atomic;
347use std::sync::atomic::AtomicBool;
348
349pub use odbc::{SqlDate, SqlSsTime2, SqlTime, SqlTimestamp};
351pub use odbc::{Executed, Prepared};
353
354mod query;
355pub use query::*;
356mod result_set;
357pub use result_set::*;
358mod row;
359pub use row::*;
360mod value;
361pub use value::*;
362mod value_row;
363pub use value_row::*;
364mod stats;
365#[cfg(feature = "statistics")]
366pub use stats::statistics;
367
368pub mod odbc_type;
369pub mod thread_local;
370
371pub use odbc_type::StringUtf16;
372
373#[derive(Debug)]
375pub struct OdbcError(Option<DiagnosticRecord>, &'static str);
376
377impl fmt::Display for OdbcError {
378 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
379 write!(f, "ODBC call failed while {}", self.1)
380 }
381}
382
383fn to_dyn(diag: &Option<DiagnosticRecord>) -> Option<&(dyn Error + 'static)> {
384 diag.as_ref().map(|e| e as &(dyn Error + 'static))
385}
386
387impl Error for OdbcError {
388 fn source(&self) -> Option<&(dyn Error + 'static)> {
389 to_dyn(&self.0)
390 }
391}
392
393impl From<ErrorContext<Option<DiagnosticRecord>, &'static str>> for OdbcError {
394 fn from(err: ErrorContext<Option<DiagnosticRecord>, &'static str>) -> OdbcError {
395 OdbcError(err.error, err.context)
396 }
397}
398
399impl From<ErrorContext<DiagnosticRecord, &'static str>> for OdbcError {
400 fn from(err: ErrorContext<DiagnosticRecord, &'static str>) -> OdbcError {
401 OdbcError(Some(err.error), err.context)
402 }
403}
404
405pub struct Odbc {
410 environment: Environment<Version3>,
411}
412
413unsafe impl Sync for Odbc {}
418
419lazy_static! {
420 static ref ODBC: Odbc = Odbc::new().expect("Failed to initialize ODBC environment");
421}
422
423static ODBC_INIT: AtomicBool = AtomicBool::new(false);
425
426impl fmt::Debug for Odbc {
427 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
428 fmt.debug_struct("Odbc").field("version", &3).finish()
429 }
430}
431
432impl Odbc {
433 fn new() -> Result<Odbc, OdbcError> {
434 if ODBC_INIT.compare_exchange(false, true, atomic::Ordering::SeqCst, atomic::Ordering::SeqCst).is_err() {
435 panic!("ODBC environment already initialised");
436 }
437
438 odbc::create_environment_v3()
439 .wrap_error_while("creating v3 environment")
440 .map_err(Into::into)
441 .map(|environment| Odbc { environment })
442 }
443
444 pub fn initialize() {
449 lazy_static::initialize(&ODBC);
450 }
451
452 pub fn list_drivers() -> Result<Vec<DriverInfo>, OdbcError> {
455 let mut odbc = Odbc::new()?;
457 let ret = odbc
458 .environment
459 .drivers()
460 .wrap_error_while("listing drivers")
461 .map_err(Into::into);
462
463 drop(odbc);
465 ODBC_INIT.store(false, atomic::Ordering::SeqCst);
466
467 ret
468 }
469
470 pub fn connect(connection_string: &str) -> Result<Connection, OdbcError> {
473 Connection::new(&ODBC, connection_string)
474 }
475
476 pub unsafe fn connect_concurrent(connection_string: &str) -> Result<Connection, OdbcError> {
479 Connection::new_concurrent(&ODBC, connection_string)
480 }
481
482 pub fn connect_with_settings(
485 connection_string: &str,
486 settings: Settings,
487 ) -> Result<Connection, OdbcError> {
488 Connection::with_settings(&ODBC, connection_string, settings)
489 }
490
491 pub unsafe fn connect_with_settings_concurrent(
494 connection_string: &str,
495 settings: Settings,
496 ) -> Result<Connection, OdbcError> {
497 Connection::with_settings_concurrent(&ODBC, connection_string, settings)
498 }
499}
500
501#[derive(Debug)]
503pub struct SplitQueriesError;
504
505impl fmt::Display for SplitQueriesError {
506 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
507 write!(f, "failed to split queries")
508 }
509}
510
511impl Error for SplitQueriesError {}
512
513pub fn split_queries(queries: &str) -> impl Iterator<Item = Result<&str, SplitQueriesError>> {
517 lazy_static! {
518 static ref RE: Regex = Regex::new(r#"(?:[\t \n]|--.*\n|!.*\n)*((?:[^;"']+(?:'(?:[^'\\]*(?:\\.)?)*')?(?:"(?:[^"\\]*(?:\\.)?)*")?)*;) *"#).unwrap();
520 }
521 RE.captures_iter(queries)
522 .map(|c| c.get(1).ok_or(SplitQueriesError))
523 .map(|r| r.map(|m| m.as_str()))
524}
525
526#[cfg(test)]
527pub mod tests {
528 use super::*;
529 #[allow(unused_imports)]
530 use assert_matches::assert_matches;
531
532 #[cfg(any(
534 feature = "test-sql-server",
535 feature = "test-hive",
536 feature = "test-monetdb"
537 ))]
538 const LONG_STRING: &'static str = "Lórem ipsum dołor sit amet, cońsectetur adipiścing elit. Fusce risus ipsum, ultricies ac odio ut, vestibulum hendrerit leo. Nunc cursus dapibus mattis. Donec quis est arcu. Sed a tortor sit amet erat euismod pulvinar. Etiam eu erat eget turpis semper finibus. Etiam lobortis egestas diam a consequat. Morbi iaculis lorem sed erat iaculis vehicula. Praesent at porttitor eros. Quisque tincidunt congue ornare. Donec sed nulla a ex sollicitudin lacinia. Fusce ut fermentum tellus, id pretium libero. Donec dapibus faucibus sapien at semper. In id felis sollicitudin, luctus doloź sit amet orci aliquam.";
539
540 #[cfg(feature = "test-sql-server")]
541 pub fn sql_server_connection_string() -> String {
542 std::env::var("SQL_SERVER_ODBC_CONNECTION").expect("SQL_SERVER_ODBC_CONNECTION not set")
543 }
544
545 #[cfg(feature = "test-sql-server")]
546 pub fn connect_sql_server() -> Connection {
547 Odbc::connect(sql_server_connection_string().as_str()).expect("connect to SQL Server")
548 }
549
550 #[cfg(feature = "test-sql-server")]
551 pub fn connect_sql_server_with_settings(settings: Settings) -> Connection {
552 Odbc::connect_with_settings(sql_server_connection_string().as_str(), settings)
553 .expect("connect to SQL ServerMonetDB")
554 }
555
556 #[cfg(feature = "test-hive")]
557 pub fn hive_connection_string() -> String {
558 std::env::var("HIVE_ODBC_CONNECTION").expect("HIVE_ODBC_CONNECTION not set")
559 }
560
561 #[cfg(feature = "test-hive")]
562 pub fn connect_hive() -> Connection {
563 unsafe {
564 Odbc::connect_concurrent(hive_connection_string().as_str()).expect("connect to Hive")
565 }
566 }
567
568 #[cfg(feature = "test-hive")]
569 pub fn connect_hive_with_settings(settings: Settings) -> Connection {
570 unsafe {
571 Odbc::connect_with_settings_concurrent(hive_connection_string().as_str(), settings)
572 .expect("connect to Hive")
573 }
574 }
575
576 #[cfg(feature = "test-monetdb")]
577 pub fn monetdb_connection_string() -> String {
578 std::env::var("MONETDB_ODBC_CONNECTION").expect("MONETDB_ODBC_CONNECTION not set")
579 }
580
581 #[cfg(feature = "test-monetdb")]
582 pub fn connect_monetdb() -> Connection {
583 unsafe {
584 Odbc::connect_concurrent(monetdb_connection_string().as_str()).expect("connect to MonetDB")
585 }
586 }
587
588 #[cfg(feature = "test-monetdb")]
589 pub fn connect_monetdb_with_settings(settings: Settings) -> Connection {
590 unsafe {
591 Odbc::connect_with_settings_concurrent(monetdb_connection_string().as_str(), settings)
592 .expect("connect to MonetDB")
593 }
594 }
595
596 #[cfg(feature = "test-hive")]
597 #[test]
598 fn test_hive_multiple_rows() {
599 let mut hive = connect_hive();
600
601 let data = hive
602 .handle()
603 .query::<ValueRow>("SELECT explode(x) AS n FROM (SELECT array(42, 24) AS x) d;")
604 .expect("failed to run query")
605 .collect::<Result<Vec<_>, _>>()
606 .expect("fetch data");
607
608 assert_matches!(data[0][0], Some(Value::Integer(number)) => assert_eq!(number, 42));
609 assert_matches!(data[1][0], Some(Value::Integer(number)) => assert_eq!(number, 24));
610 }
611
612 #[cfg(feature = "test-hive")]
613 #[test]
614 fn test_hive_multiple_columns() {
615 let mut hive = connect_hive();
616
617 let data = hive
618 .handle()
619 .query::<ValueRow>("SELECT 42, 24;")
620 .expect("failed to run query")
621 .collect::<Result<Vec<_>, _>>()
622 .expect("fetch data");
623
624 assert_matches!(data[0][0], Some(Value::Integer(number)) => assert_eq!(number, 42));
625 assert_matches!(data[0][1], Some(Value::Integer(number)) => assert_eq!(number, 24));
626 }
627
628 #[cfg(feature = "test-hive")]
629 #[test]
630 fn test_hive_types_integer() {
631 let mut hive = connect_hive();
632
633 let data = hive.handle()
634 .query::<ValueRow>("SELECT cast(127 AS TINYINT), cast(32767 AS SMALLINT), cast(2147483647 AS INTEGER), cast(9223372036854775807 AS BIGINT);")
635 .expect("failed to run query")
636 .collect::<Result<Vec<_>, _>>()
637 .expect("fetch data");
638
639 assert_matches!(data[0][0], Some(Value::Tinyint(number)) => assert_eq!(number, 127));
640 assert_matches!(data[0][1], Some(Value::Smallint(number)) => assert_eq!(number, 32767));
641 assert_matches!(data[0][2], Some(Value::Integer(number)) => assert_eq!(number, 2147483647));
642 assert_matches!(data[0][3], Some(Value::Bigint(number)) => assert_eq!(number, 9223372036854775807));
643 }
644
645 #[cfg(feature = "test-hive")]
646 #[test]
647 fn test_hive_types_boolean() {
648 let mut hive = connect_hive();
649
650 let data = hive
651 .handle()
652 .query::<ValueRow>("SELECT true, false, CAST(NULL AS BOOLEAN)")
653 .expect("failed to run query")
654 .collect::<Result<Vec<_>, _>>()
655 .expect("fetch data");
656
657 assert_matches!(data[0][0], Some(Value::Bit(true)));
658 assert_matches!(data[0][1], Some(Value::Bit(false)));
659 assert!(data[0][2].is_none());
660 }
661
662 #[cfg(feature = "test-hive")]
663 #[test]
664 fn test_hive_types_string() {
665 let mut hive = connect_hive();
666
667 let data = hive
668 .handle()
669 .query::<ValueRow>("SELECT cast('foo' AS STRING), cast('bar' AS VARCHAR);")
670 .expect("failed to run query")
671 .collect::<Result<Vec<_>, _>>()
672 .expect("fetch data");
673
674 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, "foo"));
675 assert_matches!(data[0][1], Some(Value::String(ref string)) => assert_eq!(string, "bar"));
676 }
677
678 #[cfg(feature = "test-sql-server")]
679 #[test]
680 fn test_sql_server_types_string() {
681 let mut connection = connect_sql_server();
682
683 let data = connection.handle()
684 .query::<ValueRow>("SELECT 'foo', cast('bar' AS NVARCHAR), cast('baz' AS TEXT), cast('quix' AS NTEXT);")
685 .expect("failed to run query")
686 .collect::<Result<Vec<_>, _>>()
687 .expect("fetch data");
688
689 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, "foo"));
690 assert_matches!(data[0][1], Some(Value::String(ref string)) => assert_eq!(string, "bar"));
691 assert_matches!(data[0][2], Some(Value::String(ref string)) => assert_eq!(string, "baz"));
692 assert_matches!(data[0][3], Some(Value::String(ref string)) => assert_eq!(string, "quix"));
693 }
694
695 #[cfg(feature = "test-sql-server")]
696 #[test]
697 fn test_sql_server_types_string_empty() {
698 let mut connection = connect_sql_server();
699
700 let data = connection
701 .handle()
702 .query::<ValueRow>(
703 "SELECT '', cast('' AS NVARCHAR), cast('' AS TEXT), cast('' AS NTEXT);",
704 )
705 .expect("failed to run query")
706 .collect::<Result<Vec<_>, _>>()
707 .expect("fetch data");
708
709 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, ""));
710 assert_matches!(data[0][1], Some(Value::String(ref string)) => assert_eq!(string, ""));
711 assert_matches!(data[0][2], Some(Value::String(ref string)) => assert_eq!(string, ""));
712 assert_matches!(data[0][3], Some(Value::String(ref string)) => assert_eq!(string, ""));
713 }
714
715 #[cfg(feature = "test-monetdb")]
716 #[test]
717 fn test_moentdb_string_empty() {
718 let mut monetdb = crate::tests::connect_monetdb();
719
720 let data = monetdb
721 .handle()
722 .query::<ValueRow>("SELECT ''")
723 .expect("failed to run query")
724 .collect::<Result<Vec<_>, _>>()
725 .expect("fetch data");
726
727 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, ""));
728 }
729
730 #[cfg(feature = "test-monetdb")]
731 #[test]
732 fn test_moentdb_json() {
733 let mut monetdb = crate::tests::connect_monetdb();
734
735 let data = monetdb
736 .handle()
737 .query::<ValueRow>("SELECT CAST('[\"foo\"]' AS JSON)")
738 .expect("failed to run query")
739 .collect::<Result<Vec<_>, _>>()
740 .expect("fetch data");
741
742 #[cfg(feature = "serde_json")]
743 {
744 assert_matches!(data[0][0], Some(Value::Json(serde_json::Value::Array(ref arr))) => assert_eq!(arr, &[serde_json::Value::String("foo".to_owned())]));
745 }
746 #[cfg(not(feature = "serde_json"))]
747 {
748 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, "[\"foo\"]"));
749 }
750 }
751
752 #[cfg(feature = "test-hive")]
753 #[test]
754 fn test_hive_types_float() {
755 let mut hive = connect_hive();
756
757 let data = hive
758 .handle()
759 .query::<ValueRow>("SELECT cast(1.5 AS FLOAT), cast(2.5 AS DOUBLE);")
760 .expect("failed to run query")
761 .collect::<Result<Vec<_>, _>>()
762 .expect("fetch data");
763
764 assert_matches!(data[0][0], Some(Value::Float(number)) => assert!(number > 1.0 && number < 2.0));
765 assert_matches!(data[0][1], Some(Value::Double(number)) => assert!(number > 2.0 && number < 3.0));
766 }
767
768 #[cfg(all(feature = "test-monetdb", feature = "rust_decimal"))]
769 #[test]
770 fn test_moentdb_types_decimal() {
771 let mut monetdb = crate::tests::connect_monetdb();
772
773 let data = monetdb
774 .handle()
775 .query::<ValueRow>("SELECT 10.9231213232423424324")
776 .expect("failed to run query")
777 .collect::<Result<Vec<_>, _>>()
778 .expect("fetch data");
779
780 assert_matches!(data[0][0], Some(Value::Decimal(ref dec)) => assert_eq!(dec.to_string(), "10.9231213232423424324"));
781 }
782
783 #[cfg(all(feature = "test-sql-server", feature = "rust_decimal"))]
784 #[test]
785 fn test_sql_server_types_decimal() {
786 let mut connection = connect_sql_server();
787
788 let data = connection
789 .handle()
790 .query::<ValueRow>("SELECT 10.9231213232423424324")
791 .expect("failed to run query")
792 .collect::<Result<Vec<_>, _>>()
793 .expect("fetch data");
794
795 assert_matches!(data[0][0], Some(Value::Decimal(ref dec)) => assert_eq!(dec.to_string(), "10.9231213232423424324"));
796 }
797
798 #[cfg(feature = "test-hive")]
799 #[test]
800 fn test_hive_types_null() {
801 let mut hive = connect_hive();
802
803 let data = hive
804 .handle()
805 .query::<ValueRow>("SELECT cast(NULL AS FLOAT), cast(NULL AS DOUBLE);")
806 .expect("failed to run query")
807 .collect::<Result<Vec<_>, _>>()
808 .expect("fetch data");
809
810 assert!(data[0][0].is_none());
811 assert!(data[0][1].is_none());
812 }
813
814 #[cfg(feature = "test-sql-server")]
815 #[test]
816 fn test_sql_server_tables() {
817 let mut connection = connect_sql_server();
818
819 let data = connection
820 .handle()
821 .tables::<ValueRow>("master", Some("sys"), None, Some("view"))
822 .expect("failed to run query")
823 .collect::<Result<Vec<_>, _>>()
824 .expect("fetch data");
825
826 assert!(data.len() > 0);
827 }
828
829 #[cfg(feature = "chrono")]
830 #[cfg(feature = "test-sql-server")]
831 #[test]
832 fn test_sql_server_date() {
833 let mut connection = connect_sql_server();
834
835 let data = connection
836 .handle()
837 .query::<ValueRow>("SELECT cast('2018-08-24' AS DATE) AS date")
838 .expect("failed to run query")
839 .collect::<Result<Vec<_>, _>>()
840 .expect("fetch data");
841
842 assert_matches!(&data[0][0], Some(date @ Value::Date(_)) => assert_eq!(&date.to_naive_date().unwrap().to_string(), "2018-08-24"));
843 }
844
845 #[cfg(feature = "chrono")]
846 #[cfg(feature = "test-sql-server")]
847 #[test]
848 fn test_sql_server_time() {
849 let mut connection = connect_sql_server();
850
851 let data = connection
852 .handle()
853 .query::<ValueRow>("SELECT cast('10:22:33.7654321' AS TIME) AS date")
854 .expect("failed to run query")
855 .collect::<Result<Vec<_>, _>>()
856 .expect("fetch data");
857
858 assert_matches!(&data[0][0], Some(time @ Value::Time(_)) => assert_eq!(&time.to_naive_time().unwrap().to_string(), "10:22:33.765432100"));
859 }
860
861 #[cfg(feature = "test-sql-server")]
862 #[test]
863 fn test_sql_server_affected_rows_query() {
864 let mut connection = connect_sql_server();
865
866 let mut db = connection.handle();
867
868 let data = db
869 .query::<ValueRow>("SELECT 1 UNION SELECT 2")
870 .expect("failed to run query");
871
872 assert!(data.affected_rows().unwrap().is_none());
873 data.close().ok();
874
875 let data = db
876 .query::<ValueRow>(
877 "SELECT foo INTO #bar FROM (SELECT 1 as foo UNION SELECT 2 as foo) a",
878 )
879 .expect("failed to run insert query");
880
881 assert_eq!(data.affected_rows().unwrap().unwrap(), 2);
882 }
883
884 #[cfg(feature = "test-sql-server")]
885 #[test]
886 fn test_sql_server_affected_rows_prepared() {
887 let mut connection = connect_sql_server();
888
889 let mut db = connection.handle();
890
891 let data = db
892 .query::<ValueRow>("SELECT 1 UNION SELECT 2")
893 .expect("failed to run query");
894
895 assert!(data.affected_rows().unwrap().is_none());
896 data.close().ok();
897
898 let statement = db
899 .prepare("SELECT foo INTO #bar FROM (SELECT 1 as foo UNION SELECT 2 as foo) a")
900 .expect("prepare statement");
901
902 let _data = db
903 .execute::<ValueRow>(statement)
904 .expect("failed to run insert query");
905
906 }
909
910 #[cfg(feature = "test-sql-server")]
911 #[test]
912 fn test_sql_server_query_with_parameters() {
913 let mut connection = connect_sql_server();
914
915 let val = 42;
916
917 let value: Value = connection
918 .handle()
919 .query_with_parameters("SELECT ? AS val;", |q| q.bind(&val))
920 .expect("failed to run query")
921 .single()
922 .expect("fetch data");
923
924 assert_eq!(value.to_i32().unwrap(), 42);
925 }
926
927 #[cfg(feature = "test-sql-server")]
928 #[test]
929 fn test_sql_server_query_with_many_parameters() {
930 let mut connection = connect_sql_server();
931
932 let val = [42, 24, 32, 666];
933
934 let data: Vec<ValueRow> = connection
935 .handle()
936 .query_with_parameters("SELECT ?, ?, ?, ? AS val;", |q| {
937 val.iter().fold(Ok(q), |q, v| q.and_then(|q| q.bind(v)))
938 })
939 .expect("failed to run query")
940 .collect::<Result<_, _>>()
941 .expect("fetch data");
942
943 assert_matches!(data[0][0], Some(Value::Integer(ref number)) => assert_eq!(*number, 42));
944 assert_matches!(data[0][1], Some(Value::Integer(ref number)) => assert_eq!(*number, 24));
945 assert_matches!(data[0][2], Some(Value::Integer(ref number)) => assert_eq!(*number, 32));
946 assert_matches!(data[0][3], Some(Value::Integer(ref number)) => assert_eq!(*number, 666));
947 }
948
949 #[cfg(feature = "test-sql-server")]
950 #[test]
951 fn test_sql_server_query_with_many_parameters_prepared() {
952 let mut connection = connect_sql_server();
953
954 let val = [42, 24, 32, 666];
955
956 let mut handle = connection.handle();
957
958 let statement = handle
959 .prepare("SELECT ?, ?, ?, ? AS val;")
960 .expect("prepare statement");
961
962 let data: Vec<ValueRow> = handle
963 .execute_with_parameters(statement, |q| {
964 val.iter().fold(Ok(q), |q, v| q.and_then(|q| q.bind(v)))
965 })
966 .expect("failed to run query")
967 .collect::<Result<_, _>>()
968 .expect("fetch data");
969
970 assert_matches!(data[0][0], Some(Value::Integer(ref number)) => assert_eq!(*number, 42));
971 assert_matches!(data[0][1], Some(Value::Integer(ref number)) => assert_eq!(*number, 24));
972 assert_matches!(data[0][2], Some(Value::Integer(ref number)) => assert_eq!(*number, 32));
973 assert_matches!(data[0][3], Some(Value::Integer(ref number)) => assert_eq!(*number, 666));
974 }
975
976 #[cfg(feature = "test-sql-server")]
977 #[test]
978 fn test_sql_server_prepared_columns() {
979 let mut connection = connect_sql_server();
980
981 let statement = connection
982 .handle()
983 .prepare("SELECT ?, ?, ?, ? AS val;")
984 .expect("prepare statement");
985
986 assert_eq!(statement.columns().unwrap(), 4);
987 }
988
989 #[cfg(feature = "test-sql-server")]
990 #[test]
991 fn test_sql_server_prepared_schema() {
992 let mut connection = connect_sql_server();
993
994 let statement = connection
995 .handle()
996 .prepare("SELECT ?, CAST(? as INTEGER) as foo, ?, ? AS val;")
997 .expect("prepare statement");
998
999 let schema = statement.schema().unwrap();
1000 assert_eq!(schema.len(), 4);
1001 assert_eq!(schema[1].nullable, true);
1002 assert_eq!(schema[1].datum_type, DatumType::Integer);
1003 }
1004
1005 #[cfg(feature = "test-hive")]
1006 #[test]
1007 fn test_hive_empty_data_set() {
1008 let mut hive = connect_hive();
1009
1010 let data = hive
1011 .handle()
1012 .query::<ValueRow>("USE default;")
1013 .expect("failed to run query")
1014 .collect::<Result<Vec<_>, _>>()
1015 .expect("fetch data");
1016
1017 assert!(data.is_empty());
1018 }
1019
1020 #[cfg(feature = "test-hive")]
1021 #[test]
1022 fn test_hive_long_string_fetch_utf_8() {
1023 let mut hive = connect_hive();
1024
1025 let data = hive
1026 .handle()
1027 .query::<ValueRow>(&format!("SELECT '{}'", LONG_STRING))
1028 .expect("failed to run query")
1029 .collect::<Result<Vec<_>, _>>()
1030 .expect("fetch data");
1031
1032 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1033 }
1034
1035 #[cfg(feature = "test-monetdb")]
1036 #[test]
1037 fn test_moentdb_long_string_fetch_utf_8() {
1038 let mut monetdb = crate::tests::connect_monetdb();
1039
1040 let data = monetdb
1041 .handle()
1042 .query::<ValueRow>(&format!("SELECT '{}'", LONG_STRING))
1043 .expect("failed to run query")
1044 .collect::<Result<Vec<_>, _>>()
1045 .expect("fetch data");
1046
1047 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1048 }
1049
1050 #[cfg(feature = "test-sql-server")]
1051 #[test]
1052 fn test_sql_server_long_string_fetch_utf_16_bind() {
1053 let mut connection = connect_sql_server_with_settings(Settings {
1054 utf_16_strings: true,
1055 });
1056
1057 let utf_16_string = LONG_STRING.encode_utf16().collect::<Vec<u16>>();
1058
1059 let mut handle = connection.handle();
1060
1061 let statement = handle
1062 .prepare("SELECT ? AS val;")
1063 .expect("prepare statement");
1064
1065 let data: Vec<ValueRow> = handle
1066 .execute_with_parameters(statement, |q| q.bind(&utf_16_string))
1067 .expect("failed to run query")
1068 .collect::<Result<Vec<_>, _>>()
1069 .expect("fetch data");
1070
1071 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1072 }
1073
1074 #[cfg(feature = "test-sql-server")]
1075 #[test]
1076 fn test_sql_server_long_string_fetch_utf_16_bind_string_utf_16() {
1077 let mut connection = connect_sql_server_with_settings(Settings {
1078 utf_16_strings: true,
1079 });
1080
1081 let utf_16_string = StringUtf16::from(LONG_STRING);
1082
1083 let mut handle = connection.handle();
1084
1085 let statement = handle
1086 .prepare("SELECT ? AS val;")
1087 .expect("prepare statement");
1088
1089 let data: Vec<ValueRow> = handle
1090 .execute_with_parameters(statement, |q| q.bind(&utf_16_string))
1091 .expect("failed to run query")
1092 .collect::<Result<Vec<_>, _>>()
1093 .expect("fetch data");
1094
1095 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1096 }
1097
1098 #[cfg(feature = "test-hive")]
1099 #[test]
1100 fn test_hive_long_string_fetch_utf_16() {
1101 let mut hive = connect_hive_with_settings(Settings {
1102 utf_16_strings: true,
1103 });
1104
1105 let data = hive
1106 .handle()
1107 .query::<ValueRow>(&format!("SELECT '{}'", LONG_STRING))
1108 .expect("failed to run query")
1109 .collect::<Result<Vec<_>, _>>()
1110 .expect("fetch data");
1111
1112 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1113 }
1114
1115 #[cfg(feature = "test-monetdb")]
1116 #[test]
1117 fn test_moentdb_long_string_fetch_utf_16() {
1118 let mut monetdb = connect_monetdb_with_settings(Settings {
1119 utf_16_strings: true,
1120 });
1121
1122 let data = monetdb
1123 .handle()
1124 .query::<ValueRow>(&format!("SELECT '{}'", LONG_STRING))
1125 .expect("failed to run query")
1126 .collect::<Result<Vec<_>, _>>()
1127 .expect("fetch data");
1128
1129 assert_matches!(data[0][0], Some(Value::String(ref string)) => assert_eq!(string, LONG_STRING));
1130 }
1131
1132 #[test]
1133 fn test_split_queries() {
1134 let queries = split_queries(
1135 r#"-- Foo
1136---
1137CREATE DATABASE IF NOT EXISTS daily_reports;
1138USE daily_reports;
1139
1140SELECT *;"#,
1141 )
1142 .collect::<Result<Vec<_>, _>>()
1143 .expect("failed to parse");
1144 assert_eq!(
1145 queries,
1146 [
1147 "CREATE DATABASE IF NOT EXISTS daily_reports;",
1148 "USE daily_reports;",
1149 "SELECT *;"
1150 ]
1151 );
1152 }
1153
1154 #[test]
1155 fn test_split_queries_end_white() {
1156 let queries = split_queries(
1157 r#"USE daily_reports;
1158SELECT *;
1159
1160"#,
1161 )
1162 .collect::<Result<Vec<_>, _>>()
1163 .expect("failed to parse");
1164 assert_eq!(queries, ["USE daily_reports;", "SELECT *;"]);
1165 }
1166
1167 #[test]
1168 fn test_split_queries_simple() {
1169 let queries = split_queries("SELECT 42;\nSELECT 24;\nSELECT 'foo';")
1170 .collect::<Result<Vec<_>, _>>()
1171 .expect("failed to parse");
1172 assert_eq!(queries, ["SELECT 42;", "SELECT 24;", "SELECT 'foo';"]);
1173 }
1174
1175 #[test]
1176 fn test_split_queries_semicolon() {
1177 let queries = split_queries("SELECT 'foo; bar';\nSELECT 1;")
1178 .collect::<Result<Vec<_>, _>>()
1179 .expect("failed to parse");
1180 assert_eq!(queries, [r#"SELECT 'foo; bar';"#, "SELECT 1;"]);
1181 }
1182
1183 #[test]
1184 fn test_split_queries_semicolon2() {
1185 let queries = split_queries(r#"foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad; foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad; select foo; foo "bar" baz 'quix; but' foo "bar" baz "quix; but" fsad; foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad; select foo;"#).collect::<Result<Vec<_>, _>>().expect("failed to parse");
1186 assert_eq!(
1187 queries,
1188 [
1189 r#"foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad;"#,
1190 r#"foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad;"#,
1191 r#"select foo;"#,
1192 r#"foo "bar" baz 'quix; but' foo "bar" baz "quix; but" fsad;"#,
1193 r#"foo "bar" baz "quix; but" foo "bar" baz "quix; but" fsad;"#,
1194 r#"select foo;"#,
1195 ]
1196 );
1197 }
1198
1199 #[test]
1200 fn test_split_queries_escaped_quote() {
1201 let queries = split_queries("SELECT 'foo; b\\'ar';\nSELECT 1;")
1202 .collect::<Result<Vec<_>, _>>()
1203 .expect("failed to parse");
1204 assert_eq!(queries, [r#"SELECT 'foo; b\'ar';"#, "SELECT 1;"]);
1205 }
1206
1207 #[test]
1208 fn test_split_queries_escaped_quote2() {
1209 let queries = split_queries("SELECT 'foo; b\\'ar';\nSELECT 'foo\\'bar';")
1210 .collect::<Result<Vec<_>, _>>()
1211 .expect("failed to parse");
1212 assert_eq!(
1213 queries,
1214 [r#"SELECT 'foo; b\'ar';"#, r#"SELECT 'foo\'bar';"#]
1215 );
1216 }
1217
1218 #[test]
1219 fn test_split_queries_escaped_doublequote() {
1220 let queries = split_queries(r#"SELECT "foo; b\"ar";SELECT "foo\"bar";"#)
1221 .collect::<Result<Vec<_>, _>>()
1222 .expect("failed to parse");
1223 assert_eq!(
1224 queries,
1225 [r#"SELECT "foo; b\"ar";"#, r#"SELECT "foo\"bar";"#]
1226 );
1227 }
1228
1229 #[test]
1230 fn test_split_queries_comments() {
1231 let queries =
1232 split_queries("SELECT 1;\n-- SELECT x;\n---- SELECT x;\nSELECT 2;\nSELECT 3;")
1233 .collect::<Result<Vec<_>, _>>()
1234 .expect("failed to parse");
1235 assert_eq!(queries, ["SELECT 1;", "SELECT 2;", "SELECT 3;"]);
1236 }
1237
1238 #[test]
1239 fn test_split_queries_comments2() {
1240 let queries = split_queries("-- TODO: add last_search_or_brochure_logentry_id\n-- TODO: DISTRIBUTE BY analytics_record_id SORT BY analytics_record_id ASC;\n-- TODO: check previous day for landing logentry detail\nSELECT '1' LEFT JOIN source_wcc.domain d ON regexp_extract(d.domain, '.*\\\\.([^\\.]+)$', 1) = c.domain AND d.snapshot_day = c.index;").collect::<Result<Vec<_>, _>>().expect("failed to parse");
1241 assert_eq!(queries, [r#"SELECT '1' LEFT JOIN source_wcc.domain d ON regexp_extract(d.domain, '.*\\.([^\.]+)$', 1) = c.domain AND d.snapshot_day = c.index;"#]);
1242 }
1243
1244 #[test]
1245 fn test_split_queries_control() {
1246 let queries = split_queries(
1247 "!outputformat vertical\nSELECT 1;\n-- SELECT x;\n---- SELECT x;\nSELECT 2;\nSELECT 3;",
1248 )
1249 .collect::<Result<Vec<_>, _>>()
1250 .expect("failed to parse");
1251 assert_eq!(queries, ["SELECT 1;", "SELECT 2;", "SELECT 3;"]);
1252 }
1253
1254 #[test]
1255 fn test_split_queries_white() {
1256 let queries = split_queries(" \n SELECT 1;\n \nSELECT 2;\n \nSELECT 3;\n\n ")
1257 .collect::<Result<Vec<_>, _>>()
1258 .expect("failed to parse");
1259 assert_eq!(queries, ["SELECT 1;", "SELECT 2;", "SELECT 3;"]);
1260 }
1261
1262 #[test]
1263 fn test_split_queries_white2() {
1264 let queries = split_queries("SELECT 1; \t \nSELECT 2; \n \nSELECT 3; ")
1265 .collect::<Result<Vec<_>, _>>()
1266 .expect("failed to parse");
1267 assert_eq!(queries, ["SELECT 1;", "SELECT 2;", "SELECT 3;"]);
1268 }
1269
1270 #[test]
1271 fn test_split_queries_white_comment() {
1272 let queries = split_queries("SELECT 1; \t \nSELECT 2; -- foo bar\n \nSELECT 3; ")
1273 .collect::<Result<Vec<_>, _>>()
1274 .expect("failed to parse");
1275 assert_eq!(queries, ["SELECT 1;", "SELECT 2;", "SELECT 3;"]);
1276 }
1277
1278 #[cfg(feature = "test-sql-server")]
1279 #[test]
1280 fn test_sql_server_debug() {
1281 let mut connection = connect_sql_server_with_settings(Settings {
1282 utf_16_strings: true,
1283 });
1284
1285 assert_eq!(
1286 format!("{:?}", connection),
1287 "Connection { settings: Settings { utf_16_strings: true } }"
1288 );
1289
1290 let utf_16_string = LONG_STRING.encode_utf16().collect::<Vec<u16>>();
1291
1292 let mut handle = connection.handle();
1293 assert_eq!(
1294 format!("{:?}", handle),
1295 "Handle { connection: Connection { settings: Settings { utf_16_strings: true } }, configuration: DefaultConfiguration }"
1296 );
1297
1298 let statement = handle
1299 .prepare("SELECT ? AS foo, ? AS bar, ? AS baz;")
1300 .expect("prepare statement");
1301
1302 assert_eq!(format!("{:?}", statement), "PreparedStatement { odbc_schema: [ColumnDescriptor { name: \"foo\", data_type: SQL_VARCHAR, column_size: Some(4000), decimal_digits: None, nullable: Some(true) }, ColumnDescriptor { name: \"bar\", data_type: SQL_VARCHAR, column_size: Some(4000), decimal_digits: None, nullable: Some(true) }, ColumnDescriptor { name: \"baz\", data_type: SQL_VARCHAR, column_size: Some(4000), decimal_digits: None, nullable: Some(true) }] }");
1303
1304 let result_set = handle
1305 .execute_with_parameters::<ValueRow, _>(statement, |q| {
1306 let q = q.bind(&utf_16_string)?;
1307 assert_eq!(format!("{:?}", q), "Binder { index: 1 }");
1308 q.bind(&12)?.bind(&true)
1309 })
1310 .expect("failed to run query");
1311
1312 assert_eq!(format!("{:?}", result_set), "ResultSet { schema: [ColumnType { datum_type: String, odbc_type: SQL_EXT_WVARCHAR, nullable: true, name: \"foo\" }, ColumnType { datum_type: Integer, odbc_type: SQL_INTEGER, nullable: true, name: \"bar\" }, ColumnType { datum_type: Bit, odbc_type: SQL_EXT_BIT, nullable: true, name: \"baz\" }], columns: 3, settings: Settings { utf_16_strings: true }, configuration: DefaultConfiguration }");
1313 }
1314}