From 024a566c730570245931b94c07234cb7e1c368ac Mon Sep 17 00:00:00 2001 From: Kareem Mahlees Date: Fri, 22 Dec 2023 19:27:17 +0200 Subject: [PATCH] feat: mysql support --- docker-compose.yml | 11 +++ src-tauri/src/connection.rs | 4 +- src-tauri/src/drivers/mod.rs | 1 + src-tauri/src/drivers/mysql/connection.rs | 20 ++++ src-tauri/src/drivers/mysql/decode.rs | 97 +++++++++++++++++++ src-tauri/src/drivers/mysql/mod.rs | 4 + src-tauri/src/drivers/mysql/row.rs | 89 +++++++++++++++++ src-tauri/src/drivers/mysql/table.rs | 75 ++++++++++++++ src-tauri/src/drivers/sqlite/decode.rs | 1 - src-tauri/src/main.rs | 4 +- src-tauri/src/row.rs | 18 ++-- src-tauri/src/table.rs | 37 +------ src/app/dashboard/actions.ts | 3 +- .../dashboard/details/_components/columns.tsx | 6 +- .../details/_components/data-table.tsx | 3 +- .../details/_components/edit-row-sheet.tsx | 2 +- src/app/dashboard/details/page.tsx | 5 +- src/lib/utils.ts | 4 +- 18 files changed, 329 insertions(+), 55 deletions(-) create mode 100644 docker-compose.yml create mode 100644 src-tauri/src/drivers/mysql/connection.rs create mode 100644 src-tauri/src/drivers/mysql/decode.rs create mode 100644 src-tauri/src/drivers/mysql/mod.rs create mode 100644 src-tauri/src/drivers/mysql/row.rs create mode 100644 src-tauri/src/drivers/mysql/table.rs diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..30935d2e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,11 @@ +version: "3" +services: + tablex_mysql: + image: mysql + container_name: tablex_mysql + restart: always + environment: + MYSQL_ROOT_PASSWORD: tablex + MYSQL_DATABASE: tablex + ports: + - 3306:3306 diff --git a/src-tauri/src/connection.rs b/src-tauri/src/connection.rs index 008fd2b9..77801702 100644 --- a/src-tauri/src/connection.rs +++ b/src-tauri/src/connection.rs @@ -1,5 +1,5 @@ use crate::{ - drivers::{postgres, sqlite}, + drivers::{mysql, postgres, sqlite}, utils::{read_from_connections_file, write_into_connections_file, Drivers}, DbInstance, }; @@ -48,7 +48,7 @@ pub async fn establish_connection( Drivers::PostgreSQL => { postgres::connection::establish_connection(&db, conn_string, driver).await } - Drivers::MySQL => unimplemented!(), + Drivers::MySQL => mysql::connection::establish_connection(&db, conn_string, driver).await, } } diff --git a/src-tauri/src/drivers/mod.rs b/src-tauri/src/drivers/mod.rs index bde05d13..be12554a 100644 --- a/src-tauri/src/drivers/mod.rs +++ b/src-tauri/src/drivers/mod.rs @@ -1,2 +1,3 @@ +pub mod mysql; pub mod postgres; pub mod sqlite; diff --git a/src-tauri/src/drivers/mysql/connection.rs b/src-tauri/src/drivers/mysql/connection.rs new file mode 100644 index 00000000..edd4d89a --- /dev/null +++ b/src-tauri/src/drivers/mysql/connection.rs @@ -0,0 +1,20 @@ +use crate::{utils::Drivers, DbInstance}; +use sqlx::mysql::MySqlPoolOptions; +use std::time::Duration; +use tauri::State; + +pub async fn establish_connection( + db: &State<'_, DbInstance>, + conn_string: String, + driver: Drivers, +) -> Result<(), String> { + let pool = MySqlPoolOptions::new() + .acquire_timeout(Duration::new(5, 0)) + .test_before_acquire(true) + .connect(&conn_string) + .await + .map_err(|_| "Couldn't establish connection to db".to_string())?; + *db.mysql_pool.lock().await = Some(pool); + *db.driver.lock().await = Some(driver); + Ok(()) +} diff --git a/src-tauri/src/drivers/mysql/decode.rs b/src-tauri/src/drivers/mysql/decode.rs new file mode 100644 index 00000000..e3eca962 --- /dev/null +++ b/src-tauri/src/drivers/mysql/decode.rs @@ -0,0 +1,97 @@ +use serde_json::Value as JsonValue; +use sqlx::{mysql::MySqlValueRef, TypeInfo, Value, ValueRef}; +use time::{Date, OffsetDateTime, PrimitiveDateTime, Time}; + +// this code was taken from here +// https://github.com/tauri-apps/tauri-plugin-sql/blob/v1/src/decode/mysql.rs +pub fn to_json(v: MySqlValueRef) -> Result { + if v.is_null() { + return Ok(JsonValue::Null); + } + + let res = match v.type_info().name() { + "CHAR" | "VARCHAR" | "TINYTEXT" | "TEXT" | "MEDIUMTEXT" | "LONGTEXT" | "ENUM" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode() { + JsonValue::String(v) + } else { + JsonValue::Null + } + } + "FLOAT" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::() { + JsonValue::from(v) + } else { + JsonValue::Null + } + } + "DOUBLE" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::() { + JsonValue::from(v) + } else { + JsonValue::Null + } + } + "TINYINT" | "SMALLINT" | "INT" | "MEDIUMINT" | "BIGINT" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::() { + JsonValue::Number(v.into()) + } else { + JsonValue::Null + } + } + "TINYINT UNSIGNED" | "SMALLINT UNSIGNED" | "INT UNSIGNED" | "MEDIUMINT UNSIGNED" + | "BIGINT UNSIGNED" | "YEAR" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::() { + JsonValue::Number(v.into()) + } else { + JsonValue::Null + } + } + "BOOLEAN" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode() { + JsonValue::Bool(v) + } else { + JsonValue::Null + } + } + "DATE" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::() { + JsonValue::String(v.to_string()) + } else { + JsonValue::Null + } + } + "TIME" => { + if let Ok(v) = ValueRef::to_owned(&v).try_decode::