Skip to content

Commit

Permalink
Use random id (#205)
Browse files Browse the repository at this point in the history
  • Loading branch information
phillipleblanc authored Dec 25, 2024
1 parent 8ce045d commit 19683a4
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 8 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ fallible-iterator = "0.3.0"
futures = "0.3.30"
mysql_async = { version = "0.34.1", features = ["native-tls-tls", "chrono"], optional = true }
prost = { version = "0.13.2", optional = true }
rand = "0.8.5"
r2d2 = { version = "0.8.10", optional = true }
rusqlite = { version = "0.31.0", optional = true }
sea-query = { git = "https://github.com/spiceai/sea-query.git", rev = "213b6b876068f58159ebdd5852604a021afaebf9", features = ["backend-sqlite", "backend-postgres", "postgres-array", "with-rust_decimal", "with-bigdecimal", "with-time", "with-chrono"] }
Expand Down
29 changes: 21 additions & 8 deletions src/sql/db_connection_pool/dbconnection/duckdbconn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ use duckdb::vtab::to_duckdb_type_id;
use duckdb::ToSql;
use duckdb::{Connection, DuckdbConnectionManager};
use dyn_clone::DynClone;
use rand::distributions::{Alphanumeric, DistString};
use snafu::{prelude::*, ResultExt};
use tokio::sync::mpsc::Sender;

Expand Down Expand Up @@ -63,31 +64,34 @@ pub type DuckDBParameter = Box<dyn DuckDBSyncParameter>;
pub struct DuckDBAttachments {
attachments: Vec<Arc<str>>,
search_path: Arc<str>,
random_id: String,
}

impl DuckDBAttachments {
/// Creates a new instance of a `DuckDBAttachments`, which instructs DuckDB connections to attach other DuckDB databases for queries.
#[must_use]
pub fn new(id: &str, attachments: &[Arc<str>]) -> Self {
let search_path = Self::get_search_path(id, attachments);
let random_id = Alphanumeric.sample_string(&mut rand::thread_rng(), 8);
let search_path = Self::get_search_path(id, &random_id, attachments);
Self {
attachments: attachments.to_owned(),
search_path,
random_id,
}
}

/// Returns the search path for the given database and attachments.
/// The given database needs to be included separately, as search path by default do not include the main database.
#[must_use]
pub fn get_search_path(id: &str, attachments: &[Arc<str>]) -> Arc<str> {
pub fn get_search_path(id: &str, random_id: &str, attachments: &[Arc<str>]) -> Arc<str> {
// search path includes the main database and all attached databases
let mut search_path: Vec<Arc<str>> = vec![id.into()];

search_path.extend(
attachments
.iter()
.enumerate()
.map(|(i, _)| format!("attachment_{i}").into()),
.map(|(i, _)| Self::get_attachment_name(random_id, i).into()),
);

search_path.join(",").into()
Expand Down Expand Up @@ -128,14 +132,16 @@ impl DuckDBAttachments {
})?;

conn.execute(
&format!("ATTACH IF NOT EXISTS '{db}' AS attachment_{i} (READ_ONLY)"),
&format!(
"ATTACH IF NOT EXISTS '{db}' AS {} (READ_ONLY)",
Self::get_attachment_name(&self.random_id, i)
),
[],
)
.context(DuckDBConnectionSnafu)?;
}

self.set_search_path(conn)?;

Ok(())
}

Expand All @@ -146,14 +152,21 @@ impl DuckDBAttachments {
/// Returns an error if an attachment cannot be detached, search path cannot be set or the connection fails.
pub fn detach(&self, conn: &Connection) -> Result<()> {
for (i, _) in self.attachments.iter().enumerate() {
conn.execute(&format!("DETACH attachment_{i}"), [])
.context(DuckDBConnectionSnafu)?;
conn.execute(
&format!("DETACH {}", Self::get_attachment_name(&self.random_id, i)),
[],
)
.context(DuckDBConnectionSnafu)?;
}

self.reset_search_path(conn)?;

Ok(())
}

#[must_use]
fn get_attachment_name(random_id: &str, index: usize) -> String {
format!("attachment_{random_id}_{index}")
}
}

pub struct DuckDbConnection {
Expand Down

0 comments on commit 19683a4

Please sign in to comment.