diff --git a/one/src/lib.rs b/one/src/lib.rs index 21bb5139..748763de 100644 --- a/one/src/lib.rs +++ b/one/src/lib.rs @@ -44,6 +44,27 @@ enum Command { Query(query::QueryOpts), } +#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)] +/// Value for Sqlite `pragma temp_store` +enum SqliteTempStore { + /// Default database was compiled with + Default, + /// Use the filesystem + File, + /// Temporary tables and indices are kept as if they were in pure in-memory databases + Memory, +} + +impl From for ceramic_sql::sqlite::SqliteTempStore { + fn from(value: SqliteTempStore) -> Self { + match value { + SqliteTempStore::Default => Self::Default, + SqliteTempStore::File => Self::File, + SqliteTempStore::Memory => Self::Memory, + } + } +} + #[derive(ValueEnum, Debug, Clone, PartialEq, Eq)] enum Network { /// Production network @@ -187,6 +208,10 @@ struct DBOpts { /// The maximum number of read only connections in the pool #[arg(long, default_value = "8", env = "CERAMIC_ONE_DB_MAX_CONNECTIONS")] max_connections: u32, + /// The sqlite temp_store value to use + /// 0 = default, 1 = file, 2 = memory + #[arg(long, env = "CERAMIC_ONE_TEMP_STORE")] + temp_store: Option, } // Shared options for how logging is configured. @@ -252,6 +277,7 @@ impl DBOpts { mmap_size: self.mmap_size, cache_size: self.cache_size, max_ro_connections: self.max_connections, + temp_store: self.temp_store.map(|t| t.into()), }, ceramic_sql::sqlite::Migrations::Apply, ) diff --git a/one/src/migrations.rs b/one/src/migrations.rs index 891624c5..3c05c20e 100644 --- a/one/src/migrations.rs +++ b/one/src/migrations.rs @@ -113,6 +113,7 @@ impl From<&FromIpfsOpts> for DBOpts { mmap_size: None, cache_size: None, max_connections: 8, + temp_store: None, } } } diff --git a/sql/src/sqlite.rs b/sql/src/sqlite.rs index 11ca3144..d1cdb730 100644 --- a/sql/src/sqlite.rs +++ b/sql/src/sqlite.rs @@ -25,6 +25,23 @@ pub struct SqlitePool { reader: sqlx::SqlitePool, } +#[derive(Clone, Debug, Copy, PartialEq, Eq)] +pub enum SqliteTempStore { + Default, + File, + Memory, +} + +impl SqliteTempStore { + fn pragma_value(self) -> String { + match self { + SqliteTempStore::Default => 0.to_string(), + SqliteTempStore::File => 1.to_string(), + SqliteTempStore::Memory => 2.to_string(), + } + } +} + #[derive(Clone, Debug)] pub struct SqliteOpts { /// Value to use for the sqlite cache_size pragma @@ -38,6 +55,7 @@ pub struct SqliteOpts { pub mmap_size: Option, /// Number of connections in the read only pool (default 8) pub max_ro_connections: u32, + pub temp_store: Option, } impl Default for SqliteOpts { @@ -46,6 +64,7 @@ impl Default for SqliteOpts { mmap_size: None, cache_size: None, max_ro_connections: 8, + temp_store: None, } } } @@ -54,8 +73,6 @@ impl SqlitePool { /// Connect to the sqlite database at the given path. Creates the database if it does not exist. /// Uses WAL journal mode. pub async fn connect(path: &str, opts: SqliteOpts, migrate: Migrations) -> Result { - // As we benchmark, we will likely adjust settings and make things configurable. - // A few ideas: number of RO connections, mmap_size, temp_store = memory let conn_opts = SqliteConnectOptions::from_str(path)? .journal_mode(SqliteJournalMode::Wal) .synchronous(sqlx::sqlite::SqliteSynchronous::Normal) @@ -73,6 +90,11 @@ impl SqlitePool { } else { conn_opts }; + let conn_opts = if let Some(temp) = opts.temp_store { + conn_opts.pragma("temp_store", temp.pragma_value()) + } else { + conn_opts + }; let ro_opts = conn_opts.clone().read_only(true);