-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.rs
More file actions
153 lines (131 loc) · 4.25 KB
/
utils.rs
File metadata and controls
153 lines (131 loc) · 4.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use std::{collections::HashMap, ffi::c_int, sync::OnceLock};
use regex::Regex;
use tokio::runtime::{self, Runtime};
use crate::{
sqlite::{push_error, SQLite3, SqliteError, Value, SQLITE_ERROR},
transport::{QueryResult, RemoteSQLiteResult, RemoteSqliteResponse},
};
static RUNTIME: OnceLock<Runtime> = OnceLock::new();
pub fn get_tokio() -> &'static Runtime {
RUNTIME.get_or_init(|| {
runtime::Builder::new_multi_thread()
.worker_threads(num_cpus::get())
.enable_all()
.build()
.expect("Failed to create Tokio runtime")
})
}
// Function to count parameters in the SQL string
pub fn count_parameters(sql: &str) -> c_int {
let re = Regex::new(
r"(?x)
(?:
\? # anonymous
\d* # or numbered
|
[:@$] # named parameters
[a-zA-Z_]\w*
)
",
)
.unwrap();
re.find_iter(&sql).count() as c_int
}
pub fn execute_async_task<F, R>(task: F) -> c_int
where
F: std::future::Future<Output = Result<R, SqliteError>>,
R: Into<c_int>,
{
let runtime = get_tokio();
match runtime.block_on(task) {
Ok(result) => result.into(),
Err(err) => {
unsafe { push_error((format!("{}", err), err.code)) };
SQLITE_ERROR
}
}
}
#[inline]
pub fn sql_is_begin_transaction(sql: &String) -> bool {
sql.starts_with("BEGIN")
}
#[inline]
pub fn sql_is_pragma(sql: &String) -> bool {
sql.starts_with("PRAGMA")
}
#[inline]
pub fn sql_is_rollback(sql: &String) -> bool {
sql.starts_with("ROLLBACK")
}
#[inline]
pub fn sql_is_commit(sql: &String) -> bool {
sql.starts_with("COMMIT")
}
#[inline]
pub fn is_aligned<T>(ptr: *const T) -> bool {
!ptr.is_null() && (ptr as usize) % std::mem::align_of::<T>() == 0
}
pub fn convert_params_to_json(params: &HashMap<i32, Value>) -> Vec<serde_json::Value> {
let mut index_value_pairs: Vec<_> = params.iter().collect();
// Sort by parameter index
index_value_pairs.sort_by_key(|&(k, _)| *k);
// Map sorted values to JSON
index_value_pairs
.into_iter()
.map(|(_, value)| match value {
Value::Integer(i) => serde_json::json!({
"type": "integer",
"value": *i.to_string()
}),
Value::Real(f) => serde_json::json!({
"type": "float",
"value": f
}),
Value::Text(s) => serde_json::json!({
"type": "text",
"value": s
}),
Value::Null => serde_json::json!({
"type": "null",
"value": null
}),
})
.collect()
}
pub fn get_execution_result<'a>(
db: &SQLite3,
result: &'a RemoteSqliteResponse,
) -> Result<&'a QueryResult, SqliteError> {
let mut baton = db.transaction_baton.lock().unwrap();
if let Some(new_baton) = &result.baton {
baton.replace(new_baton.into());
}
let first_execution_result = match result.results.get(0) {
Some(inner) => match &inner.response {
RemoteSQLiteResult::Error { message, code } => {
return Err(SqliteError::new(
format!("Remote SQLite error (code {}): {}", code, message),
Some(SQLITE_ERROR),
));
}
RemoteSQLiteResult::Execute { result } => Ok(result),
RemoteSQLiteResult::Close => Err::<&'a QueryResult, SqliteError>(SqliteError::new(
"Remote SQLite closed the connection unexpectedly",
None,
)),
},
None => Err::<&'a QueryResult, SqliteError>(SqliteError::new(
"No results returned from remote SQLite",
None,
)),
}?;
if let Some(last_insert_rowid) = &first_execution_result.last_insert_rowid {
let mut last_insert_rowid_lock = db.last_insert_rowid.lock().unwrap();
*last_insert_rowid_lock = Some(last_insert_rowid.parse::<i64>().unwrap_or(0));
}
if let Some(rows_written) = &first_execution_result.rows_written {
let mut rows_written_lock = db.rows_written.lock().unwrap();
*rows_written_lock = Some(*rows_written);
}
Ok(first_execution_result)
}