Skip to content

Commit 2a6b963

Browse files
committed
fix: sqlite pragma_table_info error
1 parent 16ee017 commit 2a6b963

File tree

2 files changed

+38
-25
lines changed

2 files changed

+38
-25
lines changed

src-tauri/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ futures-util = "0.3"
2727
rust_decimal = { version = "1", features = ["db-tokio-postgres"] }
2828
#clickhouse-rs = "1.1.0-alpha.1"
2929
clickhouse-rs = { git = "https://github.com/mel-mel-king/clickhouse-rs.git", branch = "decimal128" }
30-
rusqlite = { version = "0.31.0", features = ["bundled", "column_decltype"] }
30+
rusqlite = { version = "0.31.0", features = ["bundled", "column_decltype", "modern_sqlite"] }
3131
mysql = { version = "24.0.0" }
3232
tokio-postgres = { version = "0.7.10", features = ["with-serde_json-1", "array-impls", "with-chrono-0_4"] }
3333
tauri = { version = "^2.0.0-beta", features = [
@@ -54,7 +54,7 @@ async-trait = "^0.1"
5454
time = "0.3.34"
5555
uuid = { version = "1.7.0", features = ["v4"] }
5656
tokio = { version = "1.36.0", features = ["macros", "test-util"] }
57-
sqlparser = {version = "0.43", features = ["json_example"] }
57+
sqlparser = { version = "0.43", features = ["json_example"] }
5858

5959
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
6060
tauri-plugin-updater = "2.0.0-beta"

src-tauri/src/dialect/sqlite.rs

+36-23
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use arrow::datatypes::{DataType, Field, Schema};
77
use async_trait::async_trait;
88
use futures_util::StreamExt;
99
use rusqlite::types::Value;
10+
use rusqlite::Column;
1011

1112
use crate::api::RawArrowData;
1213
use crate::api::{serialize_preview, ArrowData};
@@ -58,7 +59,7 @@ impl Connection for SqliteDialect {
5859
}
5960

6061
async fn show_column(&self, schema: Option<&str>, table: &str) -> anyhow::Result<RawArrowData> {
61-
let sql = format!("PRAGMA table_info({table})");
62+
let sql = format!("select * from pragma_table_info('{table}')");
6263
self.query(&sql, 0, 0).await
6364
}
6465
}
@@ -76,6 +77,7 @@ impl SqliteDialect {
7677
Ok(rusqlite::Connection::open(&self.path)?)
7778
}
7879

80+
#[allow(clippy::unused_async)]
7981
async fn _query(&self, sql: &str, _limit: usize, _offset: usize) -> anyhow::Result<RawArrowData> {
8082
let conn = self.connect()?;
8183
let mut stmt = conn.prepare(sql)?;
@@ -88,23 +90,7 @@ impl SqliteDialect {
8890
name: col.name().to_string(),
8991
r#type: col.decl_type().unwrap_or_default().to_string(),
9092
});
91-
let typ = if let Some(decl_type) = col.decl_type() {
92-
match decl_type {
93-
"INTEGER" => DataType::Int64,
94-
"REAL" => DataType::Float64,
95-
"BOOLEAN" => DataType::Boolean,
96-
"DATE" => DataType::Utf8,
97-
"DATETIME" => DataType::Utf8,
98-
"TIME" => DataType::Utf8,
99-
decl_type if decl_type.starts_with("NUMERIC") => DataType::Utf8,
100-
decl_type if decl_type.starts_with("NVARCHAR") => DataType::Utf8,
101-
"BLOB" => DataType::Binary,
102-
"NULL" => DataType::Null,
103-
_ => DataType::Utf8,
104-
}
105-
} else {
106-
DataType::Null
107-
};
93+
let typ = Self::arrow_type(&col);
10894
let field = Field::new(col.name(), typ, true);
10995
fields.push(field);
11096
println!("{:?} {:?}", col.name(), col.decl_type())
@@ -136,6 +122,28 @@ impl SqliteDialect {
136122
titles: Some(titles),
137123
})
138124
}
125+
126+
fn arrow_type(col: &Column) -> DataType {
127+
if let Some(decl_type) = col.decl_type() {
128+
match decl_type {
129+
"INTEGER" => DataType::Int64,
130+
"REAL" => DataType::Float64,
131+
"BOOLEAN" => DataType::Boolean,
132+
"DATE" => DataType::Utf8,
133+
"DATETIME" => DataType::Utf8,
134+
"TIME" => DataType::Utf8,
135+
decl_type if decl_type.starts_with("NUMERIC") => DataType::Utf8,
136+
decl_type if decl_type.starts_with("NVARCHAR") => DataType::Utf8,
137+
"BLOB" => DataType::Binary,
138+
"NULL" => DataType::Null,
139+
_ => DataType::Utf8,
140+
}
141+
} else {
142+
DataType::Utf8
143+
}
144+
}
145+
146+
#[allow(clippy::unused_async)]
139147
pub(crate) async fn _table_row_count(&self, table: &str, cond: &str) -> anyhow::Result<usize> {
140148
let conn = self.connect()?;
141149
let sql = self._table_count_sql(table, cond);
@@ -205,6 +213,8 @@ impl SqliteDialect {
205213
titles: None,
206214
})
207215
}
216+
217+
#[allow(clippy::unused_async)]
208218
async fn get_tables(&self) -> anyhow::Result<Vec<Table>> {
209219
let conn = self.connect()?;
210220
let sql = r#"
@@ -232,14 +242,14 @@ impl SqliteDialect {
232242
pub fn convert_arrow(value: &Value, typ: &str) -> ArrayRef {
233243
match value {
234244
Value::Integer(i) => {
235-
if typ.starts_with("NUMERIC") {
245+
if typ.starts_with("NUMERIC") || typ.is_empty() {
236246
Arc::new(StringArray::from(vec![i.to_string()])) as ArrayRef
237247
} else {
238248
Arc::new(Int64Array::from(vec![(*i)])) as ArrayRef
239249
}
240250
}
241251
Value::Real(f) => {
242-
if typ.starts_with("NUMERIC") {
252+
if typ.starts_with("NUMERIC") || typ.is_empty() {
243253
Arc::new(StringArray::from(vec![f.to_string()])) as ArrayRef
244254
} else {
245255
Arc::new(Float64Array::from(vec![(*f)])) as ArrayRef
@@ -292,17 +302,20 @@ pub fn convert_to_strings(values: &[Value]) -> Vec<Option<String>> {
292302

293303
#[allow(dead_code)]
294304
pub fn convert_to_i64s(values: &[Value]) -> Vec<Option<i64>> {
295-
values.iter().map(|v| convert_to_i64(v)).collect()
305+
values.iter().map(convert_to_i64).collect()
296306
}
297307

298308
#[allow(dead_code)]
299309
pub fn convert_to_f64s(values: &[Value]) -> Vec<Option<f64>> {
300-
values.iter().map(|v| convert_to_f64(v)).collect()
310+
values.iter().map(convert_to_f64).collect()
301311
}
302312

303313
#[tokio::test]
304314
async fn test_tables() {
305-
let _ = SqliteDialect {
315+
use arrow::util::pretty::print_batches;
316+
let d = SqliteDialect {
306317
path: String::from(r""),
307318
};
319+
let res = d.query("", 0, 0).await.unwrap();
320+
let _ = print_batches(&[res.batch]);
308321
}

0 commit comments

Comments
 (0)