common.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. use std::path::PathBuf;
  2. use std::sync::atomic::AtomicBool;
  3. use std::sync::Arc;
  4. use std::time::Duration;
  5. use cdk_sql_common::pool::{self, DatabasePool};
  6. use cdk_sql_common::value::Value;
  7. use rusqlite::Connection;
  8. use crate::async_sqlite;
  9. /// The config need to create a new SQLite connection
  10. #[derive(Clone, Debug)]
  11. pub struct Config {
  12. path: Option<String>,
  13. password: Option<String>,
  14. }
  15. impl pool::DatabaseConfig for Config {
  16. fn default_timeout(&self) -> Duration {
  17. Duration::from_secs(5)
  18. }
  19. fn max_size(&self) -> usize {
  20. if self.password.is_none() {
  21. 1
  22. } else {
  23. 20
  24. }
  25. }
  26. }
  27. /// Sqlite connection manager
  28. #[derive(Debug)]
  29. pub struct SqliteConnectionManager;
  30. impl DatabasePool for SqliteConnectionManager {
  31. type Config = Config;
  32. type Connection = async_sqlite::AsyncSqlite;
  33. type Error = rusqlite::Error;
  34. fn new_resource(
  35. config: &Self::Config,
  36. _stale: Arc<AtomicBool>,
  37. _timeout: Duration,
  38. ) -> Result<Self::Connection, pool::Error<Self::Error>> {
  39. let conn = if let Some(path) = config.path.as_ref() {
  40. Connection::open(path)?
  41. } else {
  42. Connection::open_in_memory()?
  43. };
  44. if let Some(password) = config.password.as_ref() {
  45. conn.execute_batch(&format!("pragma key = '{password}';"))?;
  46. }
  47. conn.execute_batch(
  48. r#"
  49. pragma busy_timeout = 10000;
  50. pragma journal_mode = WAL;
  51. pragma synchronous = normal;
  52. pragma temp_store = memory;
  53. pragma mmap_size = 30000000000;
  54. pragma cache = shared;
  55. "#,
  56. )?;
  57. conn.busy_timeout(Duration::from_secs(10))?;
  58. Ok(async_sqlite::AsyncSqlite::new(conn))
  59. }
  60. }
  61. impl From<PathBuf> for Config {
  62. fn from(path: PathBuf) -> Self {
  63. path.to_str().unwrap_or_default().into()
  64. }
  65. }
  66. impl From<(PathBuf, String)> for Config {
  67. fn from((path, password): (PathBuf, String)) -> Self {
  68. (path.to_str().unwrap_or_default(), password.as_str()).into()
  69. }
  70. }
  71. impl From<&PathBuf> for Config {
  72. fn from(path: &PathBuf) -> Self {
  73. path.to_str().unwrap_or_default().into()
  74. }
  75. }
  76. impl From<&str> for Config {
  77. fn from(path: &str) -> Self {
  78. if path.contains(":memory:") {
  79. Config {
  80. path: None,
  81. password: None,
  82. }
  83. } else {
  84. Config {
  85. path: Some(path.to_owned()),
  86. password: None,
  87. }
  88. }
  89. }
  90. }
  91. impl From<(&str, &str)> for Config {
  92. fn from((path, pass): (&str, &str)) -> Self {
  93. if path.contains(":memory:") {
  94. Config {
  95. path: None,
  96. password: Some(pass.to_owned()),
  97. }
  98. } else {
  99. Config {
  100. path: Some(path.to_owned()),
  101. password: Some(pass.to_owned()),
  102. }
  103. }
  104. }
  105. }
  106. /// Convert cdk_sql_common::value::Value to rusqlite Value
  107. #[inline(always)]
  108. pub fn to_sqlite(v: Value) -> rusqlite::types::Value {
  109. match v {
  110. Value::Blob(blob) => rusqlite::types::Value::Blob(blob),
  111. Value::Integer(i) => rusqlite::types::Value::Integer(i),
  112. Value::Null => rusqlite::types::Value::Null,
  113. Value::Text(t) => rusqlite::types::Value::Text(t),
  114. Value::Real(r) => rusqlite::types::Value::Real(r),
  115. }
  116. }
  117. /// Convert from rusqlite Valute to cdk_sql_common::value::Value
  118. #[inline(always)]
  119. pub fn from_sqlite(v: rusqlite::types::Value) -> Value {
  120. match v {
  121. rusqlite::types::Value::Blob(blob) => Value::Blob(blob),
  122. rusqlite::types::Value::Integer(i) => Value::Integer(i),
  123. rusqlite::types::Value::Null => Value::Null,
  124. rusqlite::types::Value::Text(t) => Value::Text(t),
  125. rusqlite::types::Value::Real(r) => Value::Real(r),
  126. }
  127. }