mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add frontend folder
This commit is contained in:
53
frontend/rust-lib/flowy-database/src/lib.rs
Normal file
53
frontend/rust-lib/flowy-database/src/lib.rs
Normal file
@ -0,0 +1,53 @@
|
||||
pub mod schema;
|
||||
|
||||
#[macro_use]
|
||||
pub mod macros;
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
pub use diesel::*;
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel_derives;
|
||||
pub use diesel_derives::*;
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel_migrations;
|
||||
|
||||
pub use lib_sqlite::{ConnectionPool, DBConnection, Database};
|
||||
pub type Error = diesel::result::Error;
|
||||
|
||||
use diesel_migrations::*;
|
||||
use lib_sqlite::PoolConfig;
|
||||
use std::{fmt::Debug, io, path::Path};
|
||||
|
||||
pub mod prelude {
|
||||
pub use super::UserDatabaseConnection;
|
||||
pub use diesel::{query_dsl::*, BelongingToDsl, ExpressionMethods, RunQueryDsl};
|
||||
}
|
||||
|
||||
embed_migrations!("../flowy-database/migrations/");
|
||||
pub const DB_NAME: &str = "flowy-database.db";
|
||||
|
||||
pub fn init(storage_path: &str) -> Result<Database, io::Error> {
|
||||
if !Path::new(storage_path).exists() {
|
||||
std::fs::create_dir_all(storage_path)?;
|
||||
}
|
||||
let pool_config = PoolConfig::default();
|
||||
let database = Database::new(storage_path, DB_NAME, pool_config).map_err(as_io_error)?;
|
||||
let conn = database.get_connection().map_err(as_io_error)?;
|
||||
let _ = embedded_migrations::run(&*conn).map_err(as_io_error)?;
|
||||
Ok(database)
|
||||
}
|
||||
|
||||
fn as_io_error<E>(e: E) -> io::Error
|
||||
where
|
||||
E: Into<lib_sqlite::Error> + Debug,
|
||||
{
|
||||
let msg = format!("{:?}", e);
|
||||
io::Error::new(io::ErrorKind::NotConnected, msg)
|
||||
}
|
||||
|
||||
pub trait UserDatabaseConnection: Send + Sync {
|
||||
fn get_connection(&self) -> Result<DBConnection, String>;
|
||||
}
|
162
frontend/rust-lib/flowy-database/src/macros.rs
Normal file
162
frontend/rust-lib/flowy-database/src/macros.rs
Normal file
@ -0,0 +1,162 @@
|
||||
#[rustfmt::skip]
|
||||
/*
|
||||
diesel master support on_conflict on sqlite but not 1.4.7 version. Workaround for this
|
||||
|
||||
match dsl::workspace_table
|
||||
.filter(workspace_table::id.eq(table.id.clone()))
|
||||
.count()
|
||||
.get_result(conn)
|
||||
.unwrap_or(0)
|
||||
{
|
||||
0 => diesel::insert_into(workspace_table::table).values(table)
|
||||
.on_conflict(workspace_table::id)
|
||||
.do_update()
|
||||
.set(WorkspaceTableChangeset::from_table(workspace_table))
|
||||
.execute(conn)?,
|
||||
_ => {
|
||||
let changeset = WorkspaceTableChangeset::from_table(table);
|
||||
let filter = dsl::workspace_table.filter(workspace_table::id.eq(changeset.id.clone()));
|
||||
diesel::update(filter).set(changeset).execute(conn)?;
|
||||
},
|
||||
}
|
||||
|
||||
is equivalent to:
|
||||
|
||||
match diesel_record_count!(workspace_table, &table.id, conn) {
|
||||
0 => diesel_insert_table!(workspace_table, table, conn),
|
||||
_ => diesel_update_table!(workspace_table, WorkspaceTableChangeset::from_table(table), &*conn),
|
||||
}
|
||||
*/
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! diesel_insert_table {
|
||||
(
|
||||
$table_name:ident,
|
||||
$table:expr,
|
||||
$connection:expr
|
||||
) => {
|
||||
{
|
||||
let _ = diesel::insert_into($table_name::table)
|
||||
.values($table.clone())
|
||||
// .on_conflict($table_name::dsl::id)
|
||||
// .do_update()
|
||||
// .set(WorkspaceTableChangeset::from_table(workspace_table))
|
||||
.execute($connection)?;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! diesel_record_count {
|
||||
(
|
||||
$table_name:ident,
|
||||
$id:expr,
|
||||
$connection:expr
|
||||
) => {
|
||||
$table_name::dsl::$table_name
|
||||
.filter($table_name::dsl::id.eq($id.clone()))
|
||||
.count()
|
||||
.get_result($connection)
|
||||
.unwrap_or(0);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! diesel_update_table {
|
||||
(
|
||||
$table_name:ident,
|
||||
$changeset:expr,
|
||||
$connection:expr
|
||||
) => {{
|
||||
let filter = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($changeset.id.clone()));
|
||||
let affected_row = diesel::update(filter).set($changeset).execute($connection)?;
|
||||
debug_assert_eq!(affected_row, 1);
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! diesel_delete_table {
|
||||
(
|
||||
$table_name:ident,
|
||||
$id:ident,
|
||||
$connection:ident
|
||||
) => {
|
||||
let filter = $table_name::dsl::$table_name.filter($table_name::dsl::id.eq($id));
|
||||
let affected_row = diesel::delete(filter).execute(&*$connection)?;
|
||||
debug_assert_eq!(affected_row, 1);
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_sql_binary_expression {
|
||||
($target:ident) => {
|
||||
impl diesel::serialize::ToSql<diesel::sql_types::Binary, diesel::sqlite::Sqlite> for $target {
|
||||
fn to_sql<W: std::io::Write>(
|
||||
&self,
|
||||
out: &mut diesel::serialize::Output<W, diesel::sqlite::Sqlite>,
|
||||
) -> diesel::serialize::Result {
|
||||
let bytes: Vec<u8> = self.try_into().map_err(|e| format!("{:?}", e))?;
|
||||
diesel::serialize::ToSql::<diesel::sql_types::Binary, diesel::sqlite::Sqlite>::to_sql(&bytes, out)
|
||||
}
|
||||
}
|
||||
// https://docs.diesel.rs/src/diesel/sqlite/types/mod.rs.html#30-33
|
||||
// impl FromSql<sql_types::Binary, Sqlite> for *const [u8] {
|
||||
// fn from_sql(bytes: Option<&SqliteValue>) -> deserialize::Result<Self> {
|
||||
// let bytes = not_none!(bytes).read_blob();
|
||||
// Ok(bytes as *const _)
|
||||
// }
|
||||
// }
|
||||
impl<DB> diesel::deserialize::FromSql<diesel::sql_types::Binary, DB> for $target
|
||||
where
|
||||
DB: diesel::backend::Backend,
|
||||
*const [u8]: diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
||||
let slice_ptr =
|
||||
<*const [u8] as diesel::deserialize::FromSql<diesel::sql_types::Binary, DB>>::from_sql(bytes)?;
|
||||
let bytes = unsafe { &*slice_ptr };
|
||||
|
||||
match $target::try_from(bytes) {
|
||||
Ok(object) => Ok(object),
|
||||
Err(e) => {
|
||||
log::error!(
|
||||
"{:?} deserialize from bytes fail. {:?}",
|
||||
std::any::type_name::<$target>(),
|
||||
e
|
||||
);
|
||||
panic!();
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_sql_integer_expression {
|
||||
($target:ident) => {
|
||||
impl<DB> diesel::serialize::ToSql<Integer, DB> for $target
|
||||
where
|
||||
DB: diesel::backend::Backend,
|
||||
i32: diesel::serialize::ToSql<Integer, DB>,
|
||||
{
|
||||
fn to_sql<W: std::io::Write>(
|
||||
&self,
|
||||
out: &mut diesel::serialize::Output<W, DB>,
|
||||
) -> diesel::serialize::Result {
|
||||
(*self as i32).to_sql(out)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB> diesel::deserialize::FromSql<Integer, DB> for $target
|
||||
where
|
||||
DB: diesel::backend::Backend,
|
||||
i32: diesel::deserialize::FromSql<Integer, DB>,
|
||||
{
|
||||
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
||||
let smaill_int = i32::from_sql(bytes)?;
|
||||
Ok($target::from(smaill_int))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
92
frontend/rust-lib/flowy-database/src/schema.rs
Normal file
92
frontend/rust-lib/flowy-database/src/schema.rs
Normal file
@ -0,0 +1,92 @@
|
||||
table! {
|
||||
app_table (id) {
|
||||
id -> Text,
|
||||
workspace_id -> Text,
|
||||
name -> Text,
|
||||
desc -> Text,
|
||||
color_style -> Binary,
|
||||
last_view_id -> Nullable<Text>,
|
||||
modified_time -> BigInt,
|
||||
create_time -> BigInt,
|
||||
version -> BigInt,
|
||||
is_trash -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
doc_table (id) {
|
||||
id -> Text,
|
||||
data -> Text,
|
||||
rev_id -> BigInt,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
rev_table (id) {
|
||||
id -> Integer,
|
||||
doc_id -> Text,
|
||||
base_rev_id -> BigInt,
|
||||
rev_id -> BigInt,
|
||||
data -> Binary,
|
||||
state -> Integer,
|
||||
ty -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
trash_table (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
desc -> Text,
|
||||
modified_time -> BigInt,
|
||||
create_time -> BigInt,
|
||||
ty -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
user_table (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
token -> Text,
|
||||
email -> Text,
|
||||
workspace -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
view_table (id) {
|
||||
id -> Text,
|
||||
belong_to_id -> Text,
|
||||
name -> Text,
|
||||
desc -> Text,
|
||||
modified_time -> BigInt,
|
||||
create_time -> BigInt,
|
||||
thumbnail -> Text,
|
||||
view_type -> Integer,
|
||||
version -> BigInt,
|
||||
is_trash -> Bool,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
workspace_table (id) {
|
||||
id -> Text,
|
||||
name -> Text,
|
||||
desc -> Text,
|
||||
modified_time -> BigInt,
|
||||
create_time -> BigInt,
|
||||
user_id -> Text,
|
||||
version -> BigInt,
|
||||
}
|
||||
}
|
||||
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
app_table,
|
||||
doc_table,
|
||||
rev_table,
|
||||
trash_table,
|
||||
user_table,
|
||||
view_table,
|
||||
workspace_table,
|
||||
);
|
Reference in New Issue
Block a user