diff --git a/Cargo.lock b/Cargo.lock index f4998f235a..e887dfee66 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1572,7 +1572,6 @@ dependencies = [ "sqlez", "tempdir", "util", - "uuid 1.2.2", ] [[package]] @@ -6835,7 +6834,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" dependencies = [ "getrandom 0.2.8", - "rand 0.8.5", ] [[package]] diff --git a/crates/db/Cargo.toml b/crates/db/Cargo.toml index 7e58b2e9bf..70721c310c 100644 --- a/crates/db/Cargo.toml +++ b/crates/db/Cargo.toml @@ -22,7 +22,6 @@ lazy_static = "1.4.0" log = { version = "0.4.16", features = ["kv_unstable_serde"] } parking_lot = "0.11.1" serde = { version = "1.0", features = ["derive"] } -uuid = { version = "1.2.2", features = ["v4", "fast-rng"] } [dev-dependencies] gpui = { path = "../gpui", features = ["test-support"] } diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs index aa09dc812d..7ec4a12223 100644 --- a/crates/db/src/db.rs +++ b/crates/db/src/db.rs @@ -5,7 +5,6 @@ pub use anyhow; pub use indoc::indoc; pub use lazy_static; pub use sqlez; -use sqlez::bindable::{Bind, Column}; #[cfg(any(test, feature = "test-support"))] use anyhow::Result; @@ -20,7 +19,6 @@ use std::fs::{create_dir_all, remove_dir_all}; use std::path::Path; use util::channel::{ReleaseChannel, RELEASE_CHANNEL, RELEASE_CHANNEL_NAME}; use util::paths::DB_DIR; -use uuid::Uuid as RealUuid; const INITIALIZE_QUERY: &'static str = indoc! {" PRAGMA journal_mode=WAL; @@ -30,47 +28,6 @@ const INITIALIZE_QUERY: &'static str = indoc! {" PRAGMA case_sensitive_like=TRUE; "}; -#[derive(Debug, Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub struct Uuid(RealUuid); - -impl std::ops::Deref for Uuid { - type Target = RealUuid; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl Bind for Uuid { - fn bind( - &self, - statement: &sqlez::statement::Statement, - start_index: i32, - ) -> anyhow::Result { - statement.bind(self.as_bytes(), start_index) - } -} - -impl Column for Uuid { - fn column( - statement: &mut sqlez::statement::Statement, - start_index: i32, - ) -> anyhow::Result<(Self, i32)> { - let blob = statement.column_blob(start_index)?; - Ok((Uuid::from_bytes(blob)?, start_index + 1)) - } -} - -impl Uuid { - pub fn new() -> Self { - Uuid(RealUuid::new_v4()) - } - - fn from_bytes(bytes: &[u8]) -> anyhow::Result { - Ok(Uuid(RealUuid::from_bytes(bytes.try_into()?))) - } -} - /// Open or create a database at the given directory path. pub fn open_file_db() -> ThreadSafeConnection { // Use 0 for now. Will implement incrementing and clearing of old db files soon TM @@ -186,7 +143,7 @@ macro_rules! select_row_method { pub fn $id(&self) -> $crate::sqlez::anyhow::Result> { use $crate::anyhow::Context; - self.select_row::<$return_type>($sql)?(()) + self.select_row::<$return_type>($sql)?() .context(::std::format!( "Error in {}, select_row failed to execute or parse for: {}", ::std::stringify!($id), diff --git a/crates/editor/src/persistence.rs b/crates/editor/src/persistence.rs index 4a44a32447..2344037384 100644 --- a/crates/editor/src/persistence.rs +++ b/crates/editor/src/persistence.rs @@ -19,7 +19,7 @@ impl Domain for Editor { &[indoc! {" CREATE TABLE editors( item_id INTEGER NOT NULL, - workspace_id BLOB NOT NULL, + workspace_id INTEGER NOT NULL, path BLOB NOT NULL, PRIMARY KEY(item_id, workspace_id), FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) diff --git a/crates/sqlez/src/thread_safe_connection.rs b/crates/sqlez/src/thread_safe_connection.rs index 5a5095ad77..7c5bf6388c 100644 --- a/crates/sqlez/src/thread_safe_connection.rs +++ b/crates/sqlez/src/thread_safe_connection.rs @@ -130,7 +130,7 @@ mod test { fn migrations() -> &'static [&'static str] { &[" CREATE TABLE workspaces( - workspace_id BLOB PRIMARY KEY, + workspace_id INTEGER PRIMARY KEY, dock_visible INTEGER, -- Boolean dock_anchor TEXT, -- Enum: 'Bottom' / 'Right' / 'Expanded' dock_pane INTEGER, -- NULL indicates that we don't have a dock pane yet @@ -141,7 +141,7 @@ mod test { CREATE TABLE panes( pane_id INTEGER PRIMARY KEY, - workspace_id BLOB NOT NULL, + workspace_id INTEGER NOT NULL, active INTEGER NOT NULL, -- Boolean FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE diff --git a/crates/terminal/src/persistence.rs b/crates/terminal/src/persistence.rs index 8928164676..d624724e5c 100644 --- a/crates/terminal/src/persistence.rs +++ b/crates/terminal/src/persistence.rs @@ -16,7 +16,7 @@ impl Domain for Terminal { fn migrations() -> &'static [&'static str] { &[indoc! {" CREATE TABLE terminals ( - workspace_id BLOB, + workspace_id INTEGER, item_id INTEGER, working_directory BLOB, PRIMARY KEY(workspace_id, item_id), @@ -29,7 +29,7 @@ impl Domain for Terminal { impl TerminalDb { exec_method!( - save_working_directory(model_id: ItemId, workspace_id: WorkspaceId, working_directory: &Path): + save_working_directory(item_id: ItemId, workspace_id: WorkspaceId, working_directory: &Path): "INSERT OR REPLACE INTO terminals(item_id, workspace_id, working_directory) VALUES (?1, ?2, ?3)" ); diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index bd59afd497..f635744817 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -5,7 +5,7 @@ pub mod model; use std::path::Path; use anyhow::{anyhow, bail, Context, Result}; -use db::connection; +use db::{connection, select_row_method}; use gpui::Axis; use indoc::indoc; @@ -32,8 +32,8 @@ impl Domain for Workspace { fn migrations() -> &'static [&'static str] { &[indoc! {" CREATE TABLE workspaces( - workspace_id BLOB PRIMARY KEY, - workspace_location BLOB NOT NULL UNIQUE, + workspace_id INTEGER PRIMARY KEY, + workspace_location BLOB UNIQUE, dock_visible INTEGER, -- Boolean dock_anchor TEXT, -- Enum: 'Bottom' / 'Right' / 'Expanded' dock_pane INTEGER, -- NULL indicates that we don't have a dock pane yet @@ -43,7 +43,7 @@ impl Domain for Workspace { CREATE TABLE pane_groups( group_id INTEGER PRIMARY KEY, - workspace_id BLOB NOT NULL, + workspace_id INTEGER NOT NULL, parent_group_id INTEGER, -- NULL indicates that this is a root node position INTEGER, -- NULL indicates that this is a root node axis TEXT NOT NULL, -- Enum: 'Vertical' / 'Horizontal' @@ -55,7 +55,7 @@ impl Domain for Workspace { CREATE TABLE panes( pane_id INTEGER PRIMARY KEY, - workspace_id BLOB NOT NULL, + workspace_id INTEGER NOT NULL, active INTEGER NOT NULL, -- Boolean FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE @@ -73,7 +73,7 @@ impl Domain for Workspace { CREATE TABLE items( item_id INTEGER NOT NULL, -- This is the item's view id, so this is not unique - workspace_id BLOB NOT NULL, + workspace_id INTEGER NOT NULL, pane_id INTEGER NOT NULL, kind TEXT NOT NULL, position INTEGER NOT NULL, @@ -149,10 +149,12 @@ impl WorkspaceDb { // Update or insert self.exec_bound(indoc! { - "INSERT OR REPLACE INTO + "INSERT INTO workspaces(workspace_id, workspace_location, dock_visible, dock_anchor, timestamp) VALUES - (?1, ?2, ?3, ?4, CURRENT_TIMESTAMP)" + (?1, ?2, ?3, ?4, CURRENT_TIMESTAMP) + ON CONFLICT DO UPDATE SET + workspace_location = ?2, dock_visible = ?3, dock_anchor = ?4, timestamp = CURRENT_TIMESTAMP" })?((workspace.id, &workspace.location, workspace.dock_position)) .context("Updating workspace")?; @@ -183,6 +185,11 @@ impl WorkspaceDb { .log_err(); } + select_row_method!( + next_id() -> WorkspaceId: + "INSERT INTO workspaces DEFAULT VALUES RETURNING workspace_id" + ); + /// Returns the previous workspace ids sorted by last modified along with their opened worktree roots pub fn recent_workspaces(&self, limit: usize) -> Vec<(WorkspaceId, WorkspaceLocation)> { iife!({ @@ -199,10 +206,7 @@ impl WorkspaceDb { .unwrap_or_default() } - pub(crate) fn get_center_pane_group( - &self, - workspace_id: WorkspaceId, - ) -> Result { + fn get_center_pane_group(&self, workspace_id: WorkspaceId) -> Result { self.get_pane_group(workspace_id, None)? .into_iter() .next() @@ -266,7 +270,7 @@ impl WorkspaceDb { .collect::>() } - pub(crate) fn save_pane_group( + fn save_pane_group( &self, workspace_id: WorkspaceId, pane_group: &SerializedPaneGroup, @@ -300,7 +304,7 @@ impl WorkspaceDb { } } - pub(crate) fn get_dock_pane(&self, workspace_id: WorkspaceId) -> Result { + fn get_dock_pane(&self, workspace_id: WorkspaceId) -> Result { let (pane_id, active) = self.select_row_bound(indoc! {" SELECT pane_id, active FROM panes @@ -315,7 +319,7 @@ impl WorkspaceDb { )) } - pub(crate) fn save_pane( + fn save_pane( &self, workspace_id: WorkspaceId, pane: &SerializedPane, @@ -341,14 +345,14 @@ impl WorkspaceDb { Ok(pane_id) } - pub(crate) fn get_items(&self, pane_id: PaneId) -> Result> { + fn get_items(&self, pane_id: PaneId) -> Result> { Ok(self.select_bound(indoc! {" SELECT kind, item_id FROM items WHERE pane_id = ? ORDER BY position"})?(pane_id)?) } - pub(crate) fn save_items( + fn save_items( &self, workspace_id: WorkspaceId, pane_id: PaneId, @@ -368,7 +372,7 @@ impl WorkspaceDb { #[cfg(test)] mod tests { - use db::{open_memory_db, Uuid}; + use db::open_memory_db; use settings::DockAnchor; use super::*; @@ -427,7 +431,7 @@ mod tests { }; let workspace = SerializedWorkspace { - id: Uuid::new(), + id: 5, location: (["/tmp", "/tmp2"]).into(), dock_position: DockPosition::Shown(DockAnchor::Bottom), center_group, @@ -454,7 +458,7 @@ mod tests { let db = WorkspaceDb(open_memory_db(Some("test_basic_functionality"))); let workspace_1 = SerializedWorkspace { - id: WorkspaceId::new(), + id: 1, location: (["/tmp", "/tmp2"]).into(), dock_position: crate::dock::DockPosition::Shown(DockAnchor::Bottom), center_group: Default::default(), @@ -462,7 +466,7 @@ mod tests { }; let mut workspace_2 = SerializedWorkspace { - id: WorkspaceId::new(), + id: 2, location: (["/tmp"]).into(), dock_position: crate::dock::DockPosition::Hidden(DockAnchor::Expanded), center_group: Default::default(), @@ -497,7 +501,7 @@ mod tests { // Test other mechanism for mutating let mut workspace_3 = SerializedWorkspace { - id: WorkspaceId::new(), + id: 3, location: (&["/tmp", "/tmp2"]).into(), dock_position: DockPosition::Shown(DockAnchor::Right), center_group: Default::default(), @@ -531,7 +535,7 @@ mod tests { center_group: &SerializedPaneGroup, ) -> SerializedWorkspace { SerializedWorkspace { - id: WorkspaceId::new(), + id: 4, location: workspace_id.into(), dock_position: crate::dock::DockPosition::Hidden(DockAnchor::Right), center_group: center_group.clone(), diff --git a/crates/workspace/src/persistence/model.rs b/crates/workspace/src/persistence/model.rs index ff8be51406..111a6904c6 100644 --- a/crates/workspace/src/persistence/model.rs +++ b/crates/workspace/src/persistence/model.rs @@ -255,7 +255,7 @@ mod tests { db.exec(indoc::indoc! {" CREATE TABLE workspace_id_test( - workspace_id BLOB, + workspace_id INTEGER, dock_anchor TEXT );"}) .unwrap()() diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 4b02522496..0a4a6c8740 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -26,7 +26,6 @@ use anyhow::{anyhow, Context, Result}; use call::ActiveCall; use client::{proto, Client, PeerId, TypedEnvelope, UserStore}; use collections::{hash_map, HashMap, HashSet}; -use db::Uuid; use dock::{DefaultItemFactory, Dock, ToggleDockButton}; use drag_and_drop::DragAndDrop; use fs::{self, Fs}; @@ -45,8 +44,8 @@ use language::LanguageRegistry; use log::{error, warn}; pub use pane::*; pub use pane_group::*; -use persistence::model::SerializedItem; pub use persistence::model::{ItemId, WorkspaceLocation}; +use persistence::{model::SerializedItem, DB}; use postage::prelude::Stream; use project::{Project, ProjectEntryId, ProjectPath, ProjectStore, Worktree, WorktreeId}; use serde::Deserialize; @@ -129,7 +128,7 @@ pub struct OpenProjectEntryInPane { project_entry: ProjectEntryId, } -pub type WorkspaceId = Uuid; +pub type WorkspaceId = i64; impl_internal_actions!( workspace, @@ -637,7 +636,7 @@ impl Workspace { let id = if let Some(id) = serialized_workspace.as_ref().map(|ws| ws.id) { id } else { - WorkspaceId::new() + DB.next_id().log_err().flatten().unwrap_or(0) }; let mut this = Workspace {