Skip to content

Commit

Permalink
feat: add basic opertaions
Browse files Browse the repository at this point in the history
  • Loading branch information
invm committed Jun 17, 2023
1 parent d1c68b1 commit e45784a
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 104 deletions.
31 changes: 12 additions & 19 deletions src-tauri/src/bin/main.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use query_noir::{database::database, state};
use query_noir::methods::connections::{add_connection, get_all_connections, delete_connection, update_connection};
use query_noir::{database::database, state, utils::init};

use state::{AppState, ServiceAccess};
use tauri::{AppHandle, Manager, State};

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greet(app_handle: AppHandle, name: &str) -> String {
// Should handle errors instead of unwrapping here
app_handle.db(|db| database::add_item(name, db)).unwrap();

let items = app_handle.db(|db| database::get_all(db)).unwrap();

let items_string = items.join(" | ");

format!("Your name log: {}", items_string)
}
use state::AppState;
use tauri::{Manager, State};

fn main() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![greet])
.manage(AppState {
db: Default::default(),
})
.setup(|app| {
init::init_app()?;
let handle = app.handle();

let app_state: State<AppState> = handle.state();
let db =
database::initialize_database(&handle).expect("Database initialize should succeed");
let db = database::initialize_database().expect("Database initialize should succeed");
*app_state.db.lock().unwrap() = Some(db);

Ok(())
})
.invoke_handler(tauri::generate_handler![
add_connection,
get_all_connections,
delete_connection,
update_connection,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
23 changes: 0 additions & 23 deletions src-tauri/src/database/app.rs

This file was deleted.

24 changes: 0 additions & 24 deletions src-tauri/src/database/credentials.rs

This file was deleted.

84 changes: 48 additions & 36 deletions src-tauri/src/database/database.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
use rusqlite::{Connection, named_params};
use tauri::AppHandle;
use std::fs;
use rusqlite::Connection;
use anyhow::Result;
use log::info;
use crate::utils::fs::get_app_path;

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(app_handle: &AppHandle) -> Result<Connection, rusqlite::Error> {
let app_dir = app_handle.path_resolver().app_data_dir().expect("The app data directory should exist.");
fs::create_dir_all(&app_dir).expect("The app data directory should be created.");
let sqlite_path = app_dir.join("QueryNoir.sqlite");

let mut db = Connection::open(sqlite_path)?;
pub fn initialize_database() -> Result<Connection, rusqlite::Error> {
let db_path = get_db_path();
let mut db = Connection::open(db_path)?;

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

upgrade_database_if_needed(&mut db, existing_user_version)?;
Expand All @@ -23,43 +21,57 @@ pub fn initialize_database(app_handle: &AppHandle) -> Result<Connection, rusqlit
}

/// Upgrades the database to the current version.
pub fn upgrade_database_if_needed(db: &mut Connection, existing_version: u32) -> Result<(), rusqlite::Error> {
if existing_version < CURRENT_DB_VERSION {
db.pragma_update(None, "journal_mode", "WAL")?;
pub fn upgrade_database_if_needed(
db: &mut Connection,
existing_version: u32,
) -> Result<(), rusqlite::Error> {
if existing_version < CURRENT_DB_VERSION {
db.pragma_update(None, "journal_mode", "WAL")?;

let tx = db.transaction()?;
let tx = db.transaction()?;

tx.pragma_update(None, "user_version", CURRENT_DB_VERSION)?;
tx.pragma_update(None, "user_version", CURRENT_DB_VERSION)?;

tx.execute_batch(
"
tx.execute_batch(
"
CREATE TABLE items (
title TEXT NOT NULL
);"
)?;
);",
)?;

tx.commit()?;
}
tx.commit()?;
}

Ok(())
Ok(())
}

pub fn add_item(title: &str, db: &Connection) -> Result<(), rusqlite::Error> {
let mut statement = db.prepare("INSERT INTO items (title) VALUES (@title)")?;
statement.execute(named_params! { "@title": title })?;

Ok(())

pub fn get_db_path() -> String {
let app_path = get_app_path();
return format!("{}/.app.db", app_path);
}

pub fn get_all(db: &Connection) -> Result<Vec<String>, rusqlite::Error> {
let mut statement = db.prepare("SELECT * FROM items")?;
let mut rows = statement.query([])?;
let mut items = Vec::new();
while let Some(row) = rows.next()? {
let title: String = row.get("title")?;

items.push(title);
pub fn create_app_db(app_path: &str) -> Result<()> {
info!("Creating app database at {}", app_path);
let db_path = get_db_path();
let db = Connection::open(db_path)?;

db.execute(
"create table `connections` (
`id` integer not null primary key autoincrement,
`name` varchar(255) not null,
`color` varchar(255) not null,
`credentials` TEXT not null,
`default_db` VARCHAR(255) not null,
`save_password` TINYINT not null,
`metadata` TEXT null
)",
[],
)?;
match db.close() {
Ok(_) => info!("Successfully created app database"),
Err(e) => info!("Failed to create app database: {:?}", e),
}

Ok(items)
Ok(())
}
3 changes: 1 addition & 2 deletions src-tauri/src/database/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
pub mod database;
pub mod credentials;
pub mod app;
pub mod queries;
68 changes: 68 additions & 0 deletions src-tauri/src/database/queries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use anyhow::Result;
use rusqlite::{named_params, Connection};

use crate::methods::connections::{Credentials, DBConnection};

pub fn add_connection(conn: &DBConnection, db: &Connection) -> Result<()> {
let mut statement = db.prepare("INSERT INTO connections (name, color, credentials, default_db, save_password, metadata) VALUES (:name, :color, :credentials, :default_db, :save_password, :metadata)")?;
let credentials = serde_json::to_string(&conn.credentials)?;
let metadata = serde_json::to_string(&conn.metadata)?;
statement.execute(named_params! {
":name": conn.name,
":color": conn.color,
":credentials": credentials,
":default_db": conn.default_db,
":save_password": conn.save_password,
":metadata": metadata,
})?;

Ok(())
}

pub fn update_connection(conn: &DBConnection, db: &Connection) -> Result<()> {
let mut statement = db.prepare("INSERT INTO connections (name, color, credentials, default_db, save_password, metadata) VALUES (:name, :color, :credentials, :default_db, :save_password, :metadata) where id = :id")?;
let credentials = serde_json::to_string(&conn.credentials)?;
let metadata = serde_json::to_string(&conn.metadata)?;
statement.execute(named_params! {
":name": conn.name,
":color": conn.color,
":credentials": credentials,
":default_db": conn.default_db,
":save_password": conn.save_password,
":metadata": metadata,
":id": conn.id,
})?;

Ok(())
}

pub fn delete_connection(conn: &DBConnection, db: &Connection) -> Result<()> {
let mut statement = db.prepare("DELETE FROM connections where id = :id")?;
statement.execute(named_params! {":id": conn.id})?;

Ok(())
}

pub fn get_all_connections(db: &Connection) -> Result<Vec<DBConnection>> {
let mut statement = db.prepare("SELECT * FROM connections")?;
let mut rows = statement.query([])?;
let mut items = Vec::new();
while let Some(row) = rows.next()? {
let credentials: String = row.get("credentials")?;
let credentials: Credentials = serde_json::from_str(&credentials)?;
let metadata: String = row.get("metadata")?;
let metadata: Option<String> = serde_json::from_str(&metadata).ok();

items.push(DBConnection {
id: row.get("id")?,
name: row.get("name")?,
color: row.get("color")?,
credentials,
default_db: row.get("default_db")?,
save_password: row.get("save_password")?,
metadata,
});
}

Ok(items)
}
1 change: 1 addition & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod state;
pub mod database;
pub mod utils;
pub mod methods;
37 changes: 37 additions & 0 deletions src-tauri/src/methods/connections.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use crate::{database::queries, state};
use anyhow::Result;
use serde::{Deserialize, Serialize};

use state::ServiceAccess;
use tauri::AppHandle;

pub struct DSN {}

#[derive(Debug, Serialize, Deserialize)]
pub struct Credentials {
pub scheme: String,
pub username: String,
pub password: Option<String>,
pub host: String,
pub port: u16,
pub dbname: String,
pub params: Option<Vec<String>>,
}

pub struct DBConnection {
pub id: u32,
pub name: String,
pub color: String,
pub credentials: Credentials,
pub default_db: String,
pub save_password: bool,
pub metadata: Option<String>,
}

pub fn add_connection(app_handle: AppHandle, conn: DBConnection) -> Result<()> {
return app_handle.db(|db| queries::add_connection(&conn, db));
}

pub fn get_all_connections(app_handle: AppHandle) -> Result<Vec<DBConnection>> {
return app_handle.db(|db| queries::get_all_connections(db));
}
1 change: 1 addition & 0 deletions src-tauri/src/methods/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod connections;
9 changes: 9 additions & 0 deletions src/pages/connections.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'

function Connections() {
return (
<div>Connections</div>
)
}

export default Connections

0 comments on commit e45784a

Please sign in to comment.