stmt.rs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. use rusqlite::{self, CachedStatement};
  2. use crate::common::SqliteConnectionManager;
  3. use crate::pool::WrappedResource;
  4. pub type Value = rusqlite::types::Value;
  5. /// The Column type
  6. pub type Column = rusqlite::types::Value;
  7. /// Expected Sql response
  8. #[derive(Debug, Clone, Copy, Default)]
  9. pub enum ExpectedSqlResponse {
  10. SingleRow,
  11. #[default]
  12. ManyRows,
  13. AffectedRows,
  14. Pluck,
  15. }
  16. /// Sql message
  17. #[derive(Default, Debug)]
  18. pub struct Statement {
  19. pub sql: String,
  20. pub args: Vec<(String, Value)>,
  21. pub expected_response: ExpectedSqlResponse,
  22. }
  23. impl Statement {
  24. pub fn new<T: ToString>(sql: T) -> Self {
  25. Self {
  26. sql: sql.to_string(),
  27. ..Default::default()
  28. }
  29. }
  30. #[inline]
  31. pub fn bind<C: ToString, V: Into<Value>>(mut self, name: C, value: V) -> Self {
  32. self.args.push((name.to_string(), value.into()));
  33. self
  34. }
  35. /// Binds a single variable with a vector.
  36. ///
  37. /// This will rewrite the function from `:foo` (where value is vec![1, 2, 3]) to `:foo0, :foo1,
  38. /// :foo2` and binds each value from the value vector accordingly.
  39. #[inline]
  40. pub fn bind_vec<C: ToString, V: Into<Value>>(mut self, name: C, value: Vec<V>) -> Self {
  41. let mut new_sql = String::with_capacity(self.sql.len());
  42. let target = name.to_string();
  43. let mut i = 0;
  44. let placeholders = value
  45. .into_iter()
  46. .enumerate()
  47. .map(|(key, value)| {
  48. let key = format!("{target}{key}");
  49. self.args.push((key.clone(), value.into()));
  50. key
  51. })
  52. .collect::<Vec<_>>()
  53. .join(",");
  54. while let Some(pos) = self.sql[i..].find(&target) {
  55. let abs_pos = i + pos;
  56. let after = abs_pos + target.len();
  57. let is_word_boundary = self.sql[after..]
  58. .chars()
  59. .next()
  60. .map_or(true, |c| !c.is_alphanumeric() && c != '_');
  61. if is_word_boundary {
  62. new_sql.push_str(&self.sql[i..abs_pos]);
  63. new_sql.push_str(&placeholders);
  64. i = after;
  65. } else {
  66. new_sql.push_str(&self.sql[i..=abs_pos]);
  67. i = abs_pos + 1;
  68. }
  69. }
  70. new_sql.push_str(&self.sql[i..]);
  71. self.sql = new_sql;
  72. self
  73. }
  74. fn get_stmt(
  75. self,
  76. conn: &WrappedResource<SqliteConnectionManager>,
  77. ) -> rusqlite::Result<CachedStatement<'_>> {
  78. let mut stmt = conn.prepare_cached(&self.sql)?;
  79. for (name, value) in self.args {
  80. let index = stmt
  81. .parameter_index(&name)
  82. .map_err(|_| rusqlite::Error::InvalidColumnName(name.clone()))?
  83. .ok_or(rusqlite::Error::InvalidColumnName(name))?;
  84. stmt.raw_bind_parameter(index, value)?;
  85. }
  86. Ok(stmt)
  87. }
  88. ///
  89. /// Executes a query and returns the affected rows
  90. pub fn plunk(
  91. self,
  92. conn: &WrappedResource<SqliteConnectionManager>,
  93. ) -> rusqlite::Result<Option<Value>> {
  94. let mut stmt = self.get_stmt(conn)?;
  95. let mut rows = stmt.raw_query();
  96. rows.next()?.map(|row| row.get(0)).transpose()
  97. }
  98. /// Executes a query and returns the affected rows
  99. pub fn execute(
  100. self,
  101. conn: &WrappedResource<SqliteConnectionManager>,
  102. ) -> rusqlite::Result<usize> {
  103. self.get_stmt(conn)?.raw_execute()
  104. }
  105. /// Runs the query and returns the first row or None
  106. pub fn fetch_one(
  107. self,
  108. conn: &WrappedResource<SqliteConnectionManager>,
  109. ) -> rusqlite::Result<Option<Vec<Column>>> {
  110. let mut stmt = self.get_stmt(conn)?;
  111. let columns = stmt.column_count();
  112. let mut rows = stmt.raw_query();
  113. rows.next()?
  114. .map(|row| {
  115. (0..columns)
  116. .map(|i| row.get(i))
  117. .collect::<Result<Vec<_>, _>>()
  118. })
  119. .transpose()
  120. }
  121. /// Runs the query and returns the first row or None
  122. pub fn fetch_all(
  123. self,
  124. conn: &WrappedResource<SqliteConnectionManager>,
  125. ) -> rusqlite::Result<Vec<Vec<Column>>> {
  126. let mut stmt = self.get_stmt(conn)?;
  127. let columns = stmt.column_count();
  128. let mut rows = stmt.raw_query();
  129. let mut results = vec![];
  130. while let Some(row) = rows.next()? {
  131. results.push(
  132. (0..columns)
  133. .map(|i| row.get(i))
  134. .collect::<Result<Vec<_>, _>>()?,
  135. );
  136. }
  137. Ok(results)
  138. }
  139. }