Skip to content

Commit

Permalink
feat: add app db migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
invm authored and Michael Ionov committed Jan 18, 2024
1 parent d89fa13 commit 7294f33
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 74 deletions.
33 changes: 33 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ postgres = { version = "0.19.7", features = ["array-impls", "with-serde_json-1",
deadpool-postgres = "0.12.1"
deadpool-sqlite = "0.7.0"
magic-crypt = "3.1.13"
rusqlite_migration = { version= "1.1.0", features = ["from-directory"] }
include_dir = "0.7.3"
lazy_static = "1.4.0"

[features]
# this feature is used for production builds or when `devPath` points to the filesystem
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use chrono;
use log::error;
use state::AppState;
use tracing::error;
use std::path::PathBuf;
use std::{fs, panic};
use tauri::{Manager, State};
Expand All @@ -12,7 +12,7 @@ use tokio::sync::Mutex;
use tracing_subscriber;

use noir::{
database::queries::initialize_database,
database::init::initialize_database,
handlers::{connections, queries},
queues::query::{async_process_model, rs2js},
state::{self, AsyncState},
Expand Down
27 changes: 27 additions & 0 deletions src-tauri/src/database/init.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::utils::fs::get_db_path;
use deadpool_sqlite::rusqlite::{Connection as AppConnection, Error};
use include_dir::{include_dir, Dir};
use lazy_static::lazy_static;
use rusqlite_migration::Migrations;
use tracing::error;

static MIGRATIONS_DIR: Dir = include_dir!("$CARGO_MANIFEST_DIR/src/database/migrations");

// Define migrations. These are applied atomically.
lazy_static! {
static ref MIGRATIONS: Migrations<'static> =
Migrations::from_directory(&MIGRATIONS_DIR).unwrap();
}

/// Initializes the database connection, creating the .sqlite file if needed, and upgrading the database
/// if it's out of date.
pub fn initialize_database() -> Result<AppConnection, Error> {
let db_path = get_db_path();
let mut db = AppConnection::open(db_path)?;

let _ = MIGRATIONS.to_latest(&mut db).map_err(|e| {
error!("Error applying migrations: {:?}", e);
});

Ok(db)
}
10 changes: 10 additions & 0 deletions src-tauri/src/database/migrations/01-initial-schema/up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
CREATE TABLE connections
(
id TEXT NOT NULL,
dialect VARCHAR(255) NOT NULL,
mode VARCHAR(255) NOT NULL,
credentials VARCHAR(255) NOT NULL,
SCHEMA VARCHAR(255) NOT NULL,
NAME VARCHAR(255) NOT NULL,
color VARCHAR(255) NOT NULL
)
1 change: 1 addition & 0 deletions src-tauri/src/database/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod init;
pub mod queries;
71 changes: 2 additions & 69 deletions src-tauri/src/database/queries.rs
Original file line number Diff line number Diff line change
@@ -1,77 +1,10 @@
use std::path::PathBuf;

use crate::utils::{
crypto::{decrypt_data, encrypt_data, get_app_key},
fs::get_app_path,
};
use crate::utils::crypto::{decrypt_data, encrypt_data, get_app_key};
use anyhow::Result;
use deadpool_sqlite::rusqlite::{named_params, Connection as AppConnection, Error};
use tracing::{error, info};
use deadpool_sqlite::rusqlite::{named_params, Connection as AppConnection};
use uuid::Uuid;

use crate::engine::types::config::{ConnectionConfig, Credentials, Dialect, Mode};

const CURRENT_DB_VERSION: u32 = 1;

/// Initializes the database connection, creating the .sqlite file if needed, and upgrading the database
/// if it's out of date.
pub fn initialize_database() -> Result<AppConnection, Error> {
let db_path = get_db_path();
let mut db = AppConnection::open(db_path)?;

let mut user_pragma = db.prepare("PRAGMA user_version")?;
let existing_user_version: u32 = user_pragma.query_row([], |row| row.get(0))?;
drop(user_pragma);

upgrade_database_if_needed(&mut db, existing_user_version)?;

Ok(db)
}

/// Upgrades the database to the current version.
pub fn upgrade_database_if_needed(
db: &mut AppConnection,
existing_version: u32,
) -> Result<(), Error> {
if existing_version < CURRENT_DB_VERSION {
db.pragma_update(None, "journal_mode", "WAL")?;
let tx = db.transaction()?;
tx.pragma_update(None, "user_version", CURRENT_DB_VERSION)?;
tx.commit()?;
}
Ok(())
}

pub fn get_db_path() -> PathBuf {
let app_path = get_app_path();
PathBuf::from(format!("{}/.app.db", app_path.to_str().unwrap()))
}

pub fn create_app_db() -> Result<()> {
let db_path = get_db_path();
info!("Creating app database at {}", db_path.to_str().unwrap());
let db_path = get_db_path();
let db = AppConnection::open(db_path)?;

db.execute(
"create table `connections` (
`id` TEXT not null,
`dialect` varchar(255) not null,
`mode` varchar(255) not null,
`credentials` varchar(255) not null,
`schema` varchar(255) not null,
`name` varchar(255) not null,
`color` varchar(255) not null
)",
[],
)?;
match db.close() {
Ok(_) => info!("Successfully created app database"),
Err(e) => error!("Failed to create app database: {:?}", e),
}
Ok(())
}

pub fn add_connection(db: &AppConnection, conn: &ConnectionConfig) -> Result<()> {
let mut statement = db.prepare(
"INSERT INTO connections (
Expand Down
7 changes: 6 additions & 1 deletion src-tauri/src/utils/fs.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{database::queries::get_db_path, engine::types::result::ResultSet};
use crate::engine::types::result::ResultSet;
use anyhow::Result;
use fs::metadata;
use serde_json::json;
Expand All @@ -8,6 +8,11 @@ use tracing::error;

use rand::{distributions::Alphanumeric, Rng};

pub fn get_db_path() -> PathBuf {
let app_path = get_app_path();
PathBuf::from(format!("{}/.app.db", app_path.to_str().unwrap()))
}

fn get_key_path() -> PathBuf {
PathBuf::from(format!("{}/._", get_app_path().to_str().unwrap()))
}
Expand Down
3 changes: 1 addition & 2 deletions src-tauri/src/utils/init.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::Result;
use tracing::debug;

use crate::{database::queries::create_app_db, utils::fs::create_app_key};
use crate::utils::fs::create_app_key;

use super::fs::{create_app_dir, is_appdir_populated};

Expand All @@ -10,7 +10,6 @@ pub fn init_app() -> Result<()> {
debug!("appdir is not populated");
create_app_dir()?;
create_app_key()?;
create_app_db()?;
}
Ok(())
}

0 comments on commit 7294f33

Please sign in to comment.