githubEdit

Database

AppFlowy use SQLitearrow-up-right as database and Dieselarrow-up-right as ORMarrow-up-right.

The flowy-sqlite

The crate, flowy-sqlite, contains the logic for creating the SQLite schemaarrow-up-right and providing a shared kv storage. It is located in frontend/rust-lib/flowy-sqlite.

flowy-sqlite.png

The following section will guide you through how to create or update a schema. Before starting, I recommend checking out the Diesel Getting Startedarrow-up-right if you don't know about diesel before. Make sure you install the diesel CLI tool. You can install it by running:

cargo install diesel_cli --no-default-features --features sqlite

Create schema

Create a new schema.

Output

  • Creating migrations/2022-08-07-140433_user/up.sql

  • Creating migrations/2022-08-07-140433_user/down.sql

Create a table named user_table. Open the up.sql

When doing revert operation, the down.sql will be applied. We drop the user_table here.

Run the migration

Migrations allow us to evolve the database schema over time. Each migration can be applied (up.sql) or reverted (down.sql). Applying and immediately reverting a migration should leave your database schema unchanged. It’s a good idea to make sure that down.sql is correct. You can quickly confirm that your down.sql rolls back your migration correctly by redoing the migration:

Output:

  • Rolling back migration 2022-08-07-140433_user

  • Running migration 2022-08-07-140433_user

Ok, here we go. Everything is fine. After running the migration, the schema is automatically added to the schema.rs

Writing Rust

Update schema

Update an existing schema.

Output

  • Creating migrations/2022-08-07-140433_user-add-icon/up.sql

  • Creating migrations/2022-08-07-140433_user-add-icon/down.sql

up.sql

down.sql

After running the migration, the icon_url is added to the user_table schema automatically.

Write Rust

Let's write some Rust to read the database data. We're not going to explain how to use the diesel macros here, you can check thisarrow-up-right out for that.

We create a struct named UserTable to read the record of the user_table. The name of the properties should be the same as the user_table. We can use UserTable to insert a new record or read the existing record from the database.

Diesel provides lots of handy functions for reading and updating a record.

Read

Insert

Check out thisarrow-up-right for more information about inserting a record.

Update

We useAsChangeset macro that diesel provides to implement the AsChangeset trait. Check out thisarrow-up-right for more information about updating a record.

Apply the changeset to the database

Architecture

We use dependency injection to forbid the other crates directly dependencies on the flowy-sqlite crate. Each crate defines their database traitsarrow-up-right to meet their need.

Traits are a name given to a group of functions that a data structure can implement. I think using traits to isolate dependencies is a very good practice.

The flowy-user dependencies on the flowy-sqlite crate directly. It initializes the database connection when the Application launch or when the user switches account. The flowy-grid defines the GridDatabase trait and the flowy-folder defines the WorkspaceDatabase trait, these two traits are implemented in the flowy-sdk crate.

flowy-sdk is a crate that aggregates all the crates and resolves each crate's dependencies. flowy-sqlite is a crate that handles all the grid operations

flowy-folder is a crate that handles all the folder operations. The folder represents the concepts that include the workspace, app, and view.

file : database.plantuml

Last updated

Was this helpful?