fix(sql): preserve file associations and list selection
This commit is contained in:
25 files changed
+558
-186
No files matched your search
@@ -394,6 +394,7 @@ const SCHEMA_STATEMENTS: &[&str] = &[
|
||||
folder_id TEXT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
database_name TEXT NOT NULL DEFAULT '',
|
||||
catalog_name TEXT,
|
||||
schema_name TEXT,
|
||||
sql_text TEXT NOT NULL DEFAULT '',
|
||||
order_index INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -555,6 +556,7 @@ fn ensure_saved_sql_columns_sync(conn: &Connection) -> Result<(), String> {
|
||||
const FOLDER_COLUMNS: &[(&str, &str)] =
|
||||
&[("parent_folder_id", "TEXT"), ("order_index", "INTEGER NOT NULL DEFAULT 0")];
|
||||
const FILE_COLUMNS: &[(&str, &str)] = &[
|
||||
("catalog_name", "TEXT"),
|
||||
("order_index", "INTEGER NOT NULL DEFAULT 0"),
|
||||
("open_count", "INTEGER NOT NULL DEFAULT 0"),
|
||||
("opened_at", "TEXT"),
|
||||
@@ -2863,14 +2865,15 @@ impl Storage {
|
||||
for file in &library.files {
|
||||
tx.execute(
|
||||
"INSERT INTO saved_sql_files \
|
||||
(id, connection_id, folder_id, name, database_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
(id, connection_id, folder_id, name, database_name, catalog_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||
params![
|
||||
file.id,
|
||||
file.connection_id,
|
||||
file.folder_id,
|
||||
file.name,
|
||||
file.database,
|
||||
file.catalog,
|
||||
file.schema,
|
||||
file.sql,
|
||||
file.order_index,
|
||||
@@ -2914,7 +2917,7 @@ impl Storage {
|
||||
|
||||
let mut file_stmt = conn
|
||||
.prepare(
|
||||
"SELECT id, connection_id, folder_id, name, database_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at \
|
||||
"SELECT id, connection_id, folder_id, name, database_name, catalog_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at \
|
||||
FROM saved_sql_files ORDER BY COALESCE(folder_id, ''), order_index, connection_id, name COLLATE NOCASE",
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
@@ -2926,14 +2929,15 @@ impl Storage {
|
||||
folder_id: row.get(2)?,
|
||||
name: row.get(3)?,
|
||||
database: row.get(4)?,
|
||||
schema: row.get(5)?,
|
||||
sql: row.get(6)?,
|
||||
catalog: row.get(5)?,
|
||||
schema: row.get(6)?,
|
||||
sql: row.get(7)?,
|
||||
sql_loaded: true,
|
||||
order_index: row.get(7)?,
|
||||
open_count: row.get(8)?,
|
||||
opened_at: row.get(9)?,
|
||||
created_at: row.get(10)?,
|
||||
updated_at: row.get(11)?,
|
||||
order_index: row.get(8)?,
|
||||
open_count: row.get(9)?,
|
||||
opened_at: row.get(10)?,
|
||||
created_at: row.get(11)?,
|
||||
updated_at: row.get(12)?,
|
||||
})
|
||||
})
|
||||
.map_err(|e| e.to_string())?
|
||||
@@ -2971,7 +2975,7 @@ impl Storage {
|
||||
|
||||
let mut file_stmt = conn
|
||||
.prepare(
|
||||
"SELECT id, connection_id, folder_id, name, database_name, schema_name, order_index, open_count, opened_at, created_at, updated_at \
|
||||
"SELECT id, connection_id, folder_id, name, database_name, catalog_name, schema_name, order_index, open_count, opened_at, created_at, updated_at \
|
||||
FROM saved_sql_files ORDER BY COALESCE(folder_id, ''), order_index, connection_id, name COLLATE NOCASE",
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
@@ -2983,14 +2987,15 @@ impl Storage {
|
||||
folder_id: row.get(2)?,
|
||||
name: row.get(3)?,
|
||||
database: row.get(4)?,
|
||||
schema: row.get(5)?,
|
||||
catalog: row.get(5)?,
|
||||
schema: row.get(6)?,
|
||||
sql: String::new(),
|
||||
sql_loaded: false,
|
||||
order_index: row.get(6)?,
|
||||
open_count: row.get(7)?,
|
||||
opened_at: row.get(8)?,
|
||||
created_at: row.get(9)?,
|
||||
updated_at: row.get(10)?,
|
||||
order_index: row.get(7)?,
|
||||
open_count: row.get(8)?,
|
||||
opened_at: row.get(9)?,
|
||||
created_at: row.get(10)?,
|
||||
updated_at: row.get(11)?,
|
||||
})
|
||||
})
|
||||
.map_err(|e| e.to_string())?
|
||||
@@ -3007,7 +3012,7 @@ impl Storage {
|
||||
self.with_conn(move |conn| {
|
||||
let mut stmt = conn
|
||||
.prepare(
|
||||
"SELECT id, connection_id, folder_id, name, database_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at \
|
||||
"SELECT id, connection_id, folder_id, name, database_name, catalog_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at \
|
||||
FROM saved_sql_files WHERE id = ?1",
|
||||
)
|
||||
.map_err(|e| e.to_string())?;
|
||||
@@ -3018,14 +3023,15 @@ impl Storage {
|
||||
folder_id: row.get(2)?,
|
||||
name: row.get(3)?,
|
||||
database: row.get(4)?,
|
||||
schema: row.get(5)?,
|
||||
sql: row.get(6)?,
|
||||
catalog: row.get(5)?,
|
||||
schema: row.get(6)?,
|
||||
sql: row.get(7)?,
|
||||
sql_loaded: true,
|
||||
order_index: row.get(7)?,
|
||||
open_count: row.get(8)?,
|
||||
opened_at: row.get(9)?,
|
||||
created_at: row.get(10)?,
|
||||
updated_at: row.get(11)?,
|
||||
order_index: row.get(8)?,
|
||||
open_count: row.get(9)?,
|
||||
opened_at: row.get(10)?,
|
||||
created_at: row.get(11)?,
|
||||
updated_at: row.get(12)?,
|
||||
})
|
||||
}) {
|
||||
Ok(file) => Ok(Some(file)),
|
||||
@@ -3099,15 +3105,16 @@ impl Storage {
|
||||
self.with_conn(move |conn| {
|
||||
conn.execute(
|
||||
"INSERT INTO saved_sql_files \
|
||||
(id, connection_id, folder_id, name, database_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) \
|
||||
(id, connection_id, folder_id, name, database_name, catalog_name, schema_name, sql_text, order_index, open_count, opened_at, created_at, updated_at) \
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) \
|
||||
ON CONFLICT(id) DO UPDATE SET \
|
||||
connection_id = excluded.connection_id, \
|
||||
folder_id = excluded.folder_id, \
|
||||
name = excluded.name, \
|
||||
database_name = excluded.database_name, \
|
||||
catalog_name = excluded.catalog_name, \
|
||||
schema_name = excluded.schema_name, \
|
||||
sql_text = CASE WHEN ?13 THEN excluded.sql_text ELSE saved_sql_files.sql_text END, \
|
||||
sql_text = CASE WHEN ?14 THEN excluded.sql_text ELSE saved_sql_files.sql_text END, \
|
||||
order_index = excluded.order_index, \
|
||||
open_count = excluded.open_count, \
|
||||
opened_at = excluded.opened_at, \
|
||||
@@ -3118,6 +3125,7 @@ impl Storage {
|
||||
file.folder_id,
|
||||
file.name,
|
||||
file.database,
|
||||
file.catalog,
|
||||
file.schema,
|
||||
file.sql,
|
||||
file.order_index,
|
||||
@@ -5567,6 +5575,42 @@ mod tests {
|
||||
assert!(entry.last_accessed_at >= entry.created_at);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn saved_sql_catalog_column_migrates_legacy_database() {
|
||||
let path = temp_db_path("saved-sql-catalog-migration");
|
||||
{
|
||||
let connection = Connection::open(&path).unwrap();
|
||||
connection
|
||||
.execute_batch(
|
||||
"CREATE TABLE saved_sql_files (
|
||||
id TEXT PRIMARY KEY,
|
||||
connection_id TEXT NOT NULL,
|
||||
folder_id TEXT,
|
||||
name TEXT NOT NULL DEFAULT '',
|
||||
database_name TEXT NOT NULL DEFAULT '',
|
||||
schema_name TEXT,
|
||||
sql_text TEXT NOT NULL DEFAULT '',
|
||||
order_index INTEGER NOT NULL DEFAULT 0,
|
||||
open_count INTEGER NOT NULL DEFAULT 0,
|
||||
opened_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT '',
|
||||
updated_at TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
INSERT INTO saved_sql_files
|
||||
(id, connection_id, name, database_name, sql_text, created_at, updated_at)
|
||||
VALUES
|
||||
('legacy-sql', 'conn-1', 'legacy.sql', 'sales', 'SELECT 1;', '2026-01-01', '2026-01-01');",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let storage = Storage::open(&path).await.unwrap();
|
||||
let loaded = storage.load_saved_sql_file("legacy-sql").await.unwrap().unwrap();
|
||||
|
||||
assert_eq!(loaded.database, "sales");
|
||||
assert_eq!(loaded.catalog, None);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn saved_sql_summary_omits_sql_text_and_loads_file_on_demand() {
|
||||
let path = temp_db_path("saved-sql-summary");
|
||||
@@ -5577,6 +5621,7 @@ mod tests {
|
||||
folder_id: None,
|
||||
name: "large.sql".to_string(),
|
||||
database: "main".to_string(),
|
||||
catalog: Some("hive".to_string()),
|
||||
schema: None,
|
||||
sql: "SELECT * FROM very_large_table;".repeat(100),
|
||||
sql_loaded: true,
|
||||
@@ -5592,10 +5637,12 @@ mod tests {
|
||||
let summary = storage.load_saved_sql_library_summary().await.unwrap();
|
||||
assert_eq!(summary.files.len(), 1);
|
||||
assert_eq!(summary.files[0].sql, "");
|
||||
assert_eq!(summary.files[0].catalog.as_deref(), Some("hive"));
|
||||
assert!(!summary.files[0].sql_loaded);
|
||||
|
||||
let loaded = storage.load_saved_sql_file("sql-1").await.unwrap().unwrap();
|
||||
assert_eq!(loaded.sql, file.sql);
|
||||
assert_eq!(loaded.catalog.as_deref(), Some("hive"));
|
||||
assert!(loaded.sql_loaded);
|
||||
}
|
||||
|
||||
@@ -5609,6 +5656,7 @@ mod tests {
|
||||
folder_id: None,
|
||||
name: "query.sql".to_string(),
|
||||
database: "main".to_string(),
|
||||
catalog: None,
|
||||
schema: None,
|
||||
sql: "SELECT 1;".to_string(),
|
||||
sql_loaded: true,
|
||||
|
||||
Reference in new issue
Block a user