mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-24 02:46:43 +00:00
WIP almost compiling with sqlez
This commit is contained in:
parent
777f05eb76
commit
3c1b747f64
8 changed files with 77 additions and 57 deletions
|
@ -17,21 +17,21 @@ impl Db {
|
||||||
pub fn read_kvp(&self, key: &str) -> Result<Option<String>> {
|
pub fn read_kvp(&self, key: &str) -> Result<Option<String>> {
|
||||||
self.0
|
self.0
|
||||||
.prepare("SELECT value FROM kv_store WHERE key = (?)")?
|
.prepare("SELECT value FROM kv_store WHERE key = (?)")?
|
||||||
.bind(key)?
|
.with_bindings(key)?
|
||||||
.maybe_row()
|
.maybe_row()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_kvp(&self, key: &str, value: &str) -> Result<()> {
|
pub fn write_kvp(&self, key: &str, value: &str) -> Result<()> {
|
||||||
self.0
|
self.0
|
||||||
.prepare("INSERT OR REPLACE INTO kv_store(key, value) VALUES (?, ?)")?
|
.prepare("INSERT OR REPLACE INTO kv_store(key, value) VALUES (?, ?)")?
|
||||||
.bind((key, value))?
|
.with_bindings((key, value))?
|
||||||
.exec()
|
.exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_kvp(&self, key: &str) -> Result<()> {
|
pub fn delete_kvp(&self, key: &str) -> Result<()> {
|
||||||
self.0
|
self.0
|
||||||
.prepare("DELETE FROM kv_store WHERE key = (?)")?
|
.prepare("DELETE FROM kv_store WHERE key = (?)")?
|
||||||
.bind(key)?
|
.with_bindings(key)?
|
||||||
.exec()
|
.exec()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,17 +23,17 @@ use super::Db;
|
||||||
pub(crate) const WORKSPACES_MIGRATION: Migration = Migration::new(
|
pub(crate) const WORKSPACES_MIGRATION: Migration = Migration::new(
|
||||||
"workspace",
|
"workspace",
|
||||||
&[indoc! {"
|
&[indoc! {"
|
||||||
CREATE TABLE workspaces(
|
CREATE TABLE workspaces(
|
||||||
workspace_id INTEGER PRIMARY KEY,
|
workspace_id INTEGER PRIMARY KEY,
|
||||||
timestamp TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL
|
timestamp TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||||
) STRICT;
|
) STRICT;
|
||||||
|
|
||||||
CREATE TABLE worktree_roots(
|
CREATE TABLE worktree_roots(
|
||||||
worktree_root BLOB NOT NULL,
|
worktree_root BLOB NOT NULL,
|
||||||
workspace_id INTEGER NOT NULL,
|
workspace_id INTEGER NOT NULL,
|
||||||
FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE
|
FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id) ON DELETE CASCADE
|
||||||
PRIMARY KEY(worktree_root, workspace_id)
|
PRIMARY KEY(worktree_root, workspace_id)
|
||||||
) STRICT;"}],
|
) STRICT;"}],
|
||||||
);
|
);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, Default)]
|
||||||
|
@ -159,9 +159,9 @@ impl Db {
|
||||||
|
|
||||||
/// Returns the previous workspace ids sorted by last modified along with their opened worktree roots
|
/// Returns the previous workspace ids sorted by last modified along with their opened worktree roots
|
||||||
pub fn recent_workspaces(&self, limit: usize) -> Vec<(WorkspaceId, Vec<Arc<Path>>)> {
|
pub fn recent_workspaces(&self, limit: usize) -> Vec<(WorkspaceId, Vec<Arc<Path>>)> {
|
||||||
let res = self.with_savepoint("recent_workspaces", |conn| {
|
self.with_savepoint("recent_workspaces", |conn| {
|
||||||
let ids = conn.prepare("SELECT workspace_id FROM workspaces ORDER BY last_opened_timestamp DESC LIMIT ?")?
|
let ids = conn.prepare("SELECT workspace_id FROM workspaces ORDER BY last_opened_timestamp DESC LIMIT ?")?
|
||||||
.bind(limit)?
|
.with_bindings(limit)?
|
||||||
.rows::<i64>()?
|
.rows::<i64>()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|row| WorkspaceId(*row));
|
.map(|row| WorkspaceId(*row));
|
||||||
|
@ -170,7 +170,7 @@ impl Db {
|
||||||
|
|
||||||
let stmt = conn.prepare("SELECT worktree_root FROM worktree_roots WHERE workspace_id = ?")?;
|
let stmt = conn.prepare("SELECT worktree_root FROM worktree_roots WHERE workspace_id = ?")?;
|
||||||
for workspace_id in ids {
|
for workspace_id in ids {
|
||||||
let roots = stmt.bind(workspace_id.0)?
|
let roots = stmt.with_bindings(workspace_id.0)?
|
||||||
.rows::<Vec<u8>>()?
|
.rows::<Vec<u8>>()?
|
||||||
.iter()
|
.iter()
|
||||||
.map(|row| {
|
.map(|row| {
|
||||||
|
@ -180,17 +180,11 @@ impl Db {
|
||||||
result.push((workspace_id, roots))
|
result.push((workspace_id, roots))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
});
|
}).unwrap_or_else(|err| {
|
||||||
|
log::error!("Failed to get recent workspaces, err: {}", err);
|
||||||
match res {
|
Vec::new()
|
||||||
Ok(result) => result,
|
})
|
||||||
Err(err) => {
|
|
||||||
log::error!("Failed to get recent workspaces, err: {}", err);
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,14 +204,14 @@ where
|
||||||
connection.prepare(
|
connection.prepare(
|
||||||
"DELETE FROM workspaces WHERE workspace_id = ?",
|
"DELETE FROM workspaces WHERE workspace_id = ?",
|
||||||
)?
|
)?
|
||||||
.bind(preexisting_id.0)?
|
.with_bindings(preexisting_id.0)?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connection
|
connection
|
||||||
.prepare("DELETE FROM worktree_roots WHERE workspace_id = ?")?
|
.prepare("DELETE FROM worktree_roots WHERE workspace_id = ?")?
|
||||||
.bind(workspace_id.0)?
|
.with_bindings(workspace_id.0)?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
for root in worktree_roots {
|
for root in worktree_roots {
|
||||||
|
@ -226,12 +220,12 @@ where
|
||||||
// let path = root.as_ref().to_string_lossy().to_string();
|
// let path = root.as_ref().to_string_lossy().to_string();
|
||||||
|
|
||||||
connection.prepare("INSERT INTO worktree_roots(workspace_id, worktree_root) VALUES (?, ?)")?
|
connection.prepare("INSERT INTO worktree_roots(workspace_id, worktree_root) VALUES (?, ?)")?
|
||||||
.bind((workspace_id.0, path))?
|
.with_bindings((workspace_id.0, path))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
connection.prepare("UPDATE workspaces SET last_opened_timestamp = CURRENT_TIMESTAMP WHERE workspace_id = ?")?
|
connection.prepare("UPDATE workspaces SET last_opened_timestamp = CURRENT_TIMESTAMP WHERE workspace_id = ?")?
|
||||||
.bind(workspace_id.0)?
|
.with_bindings(workspace_id.0)?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -330,16 +324,11 @@ where
|
||||||
// Make sure we bound the parameters correctly
|
// Make sure we bound the parameters correctly
|
||||||
debug_assert!(worktree_roots.len() as i32 + 1 == stmt.parameter_count());
|
debug_assert!(worktree_roots.len() as i32 + 1 == stmt.parameter_count());
|
||||||
|
|
||||||
for i in 0..worktree_roots.len() {
|
let root_bytes: Vec<&[u8]> = worktree_roots.iter()
|
||||||
let path = &worktree_roots[i].as_ref().as_os_str().as_bytes();
|
.map(|root| root.as_ref().as_os_str().as_bytes()).collect();
|
||||||
// If you need to debug this, here's the string parsing:
|
|
||||||
// let path = &worktree_roots[i].as_ref().to_string_lossy().to_string()
|
stmt.with_bindings((root_bytes, root_bytes.len()))?
|
||||||
stmt.bind_value(*path, i as i32 + 1);
|
.maybe_row()
|
||||||
}
|
|
||||||
// No -1, because SQLite is 1 based
|
|
||||||
stmt.bind_value(worktree_roots.len(), worktree_roots.len() as i32 + 1)?;
|
|
||||||
|
|
||||||
stmt.maybe_row()
|
|
||||||
.map(|row| row.map(|id| WorkspaceId(id)))
|
.map(|row| row.map(|id| WorkspaceId(id)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,3 +207,25 @@ impl<T: Column + Default + Copy, const COUNT: usize> Column for [T; COUNT] {
|
||||||
Ok((array, current_index))
|
Ok((array, current_index))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Bind> Bind for Vec<T> {
|
||||||
|
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||||
|
let mut current_index = start_index;
|
||||||
|
for binding in self.iter() {
|
||||||
|
current_index = binding.bind(statement, current_index)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(current_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Bind> Bind for &[T] {
|
||||||
|
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||||
|
let mut current_index = start_index;
|
||||||
|
for binding in *self {
|
||||||
|
current_index = binding.bind(statement, current_index)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(current_index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ mod test {
|
||||||
connection
|
connection
|
||||||
.prepare("INSERT INTO text (text) VALUES (?);")
|
.prepare("INSERT INTO text (text) VALUES (?);")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.bind(text)
|
.with_bindings(text)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.exec()
|
.exec()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -185,8 +185,16 @@ mod test {
|
||||||
.prepare("INSERT INTO test (text, integer, blob) VALUES (?, ?, ?)")
|
.prepare("INSERT INTO test (text, integer, blob) VALUES (?, ?, ?)")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
insert.bind(tuple1.clone()).unwrap().exec().unwrap();
|
insert
|
||||||
insert.bind(tuple2.clone()).unwrap().exec().unwrap();
|
.with_bindings(tuple1.clone())
|
||||||
|
.unwrap()
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
insert
|
||||||
|
.with_bindings(tuple2.clone())
|
||||||
|
.unwrap()
|
||||||
|
.exec()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
connection
|
connection
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl Migration {
|
||||||
WHERE domain = ?
|
WHERE domain = ?
|
||||||
ORDER BY step
|
ORDER BY step
|
||||||
"})?
|
"})?
|
||||||
.bind(self.domain)?
|
.with_bindings(self.domain)?
|
||||||
.rows::<(String, usize, String)>()?;
|
.rows::<(String, usize, String)>()?;
|
||||||
|
|
||||||
let mut store_completed_migration = connection
|
let mut store_completed_migration = connection
|
||||||
|
@ -72,7 +72,7 @@ impl Migration {
|
||||||
|
|
||||||
connection.exec(migration)?;
|
connection.exec(migration)?;
|
||||||
store_completed_migration
|
store_completed_migration
|
||||||
.bind((self.domain, index, *migration))?
|
.with_bindings((self.domain, index, *migration))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ mod test {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
store_completed_migration
|
store_completed_migration
|
||||||
.bind((domain, i, i.to_string()))
|
.with_bindings((domain, i, i.to_string()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.exec()
|
.exec()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -76,14 +76,14 @@ mod tests {
|
||||||
connection.with_savepoint("first", |save1| {
|
connection.with_savepoint("first", |save1| {
|
||||||
save1
|
save1
|
||||||
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
||||||
.bind((save1_text, 1))?
|
.with_bindings((save1_text, 1))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
assert!(save1
|
assert!(save1
|
||||||
.with_savepoint("second", |save2| -> Result<Option<()>, anyhow::Error> {
|
.with_savepoint("second", |save2| -> Result<Option<()>, anyhow::Error> {
|
||||||
save2
|
save2
|
||||||
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
||||||
.bind((save2_text, 2))?
|
.with_bindings((save2_text, 2))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -108,7 +108,7 @@ mod tests {
|
||||||
save1.with_savepoint_rollback::<(), _>("second", |save2| {
|
save1.with_savepoint_rollback::<(), _>("second", |save2| {
|
||||||
save2
|
save2
|
||||||
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
||||||
.bind((save2_text, 2))?
|
.with_bindings((save2_text, 2))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -131,7 +131,7 @@ mod tests {
|
||||||
save1.with_savepoint_rollback("second", |save2| {
|
save1.with_savepoint_rollback("second", |save2| {
|
||||||
save2
|
save2
|
||||||
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
.prepare("INSERT INTO text(text, idx) VALUES (?, ?)")?
|
||||||
.bind((save2_text, 2))?
|
.with_bindings((save2_text, 2))?
|
||||||
.exec()?;
|
.exec()?;
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
|
@ -179,10 +179,9 @@ impl<'a> Statement<'a> {
|
||||||
Ok(str::from_utf8(slice)?)
|
Ok(str::from_utf8(slice)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind_value<T: Bind>(&self, value: T, idx: i32) -> Result<()> {
|
pub fn bind<T: Bind>(&self, value: T, index: i32) -> Result<i32> {
|
||||||
debug_assert!(idx > 0);
|
debug_assert!(index > 0);
|
||||||
value.bind(self, idx)?;
|
value.bind(self, index)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn column<T: Column>(&mut self) -> Result<T> {
|
pub fn column<T: Column>(&mut self) -> Result<T> {
|
||||||
|
@ -203,8 +202,8 @@ impl<'a> Statement<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&mut self, bindings: impl Bind) -> Result<&mut Self> {
|
pub fn with_bindings(&mut self, bindings: impl Bind) -> Result<&mut Self> {
|
||||||
self.bind_value(bindings, 1)?;
|
self.bind(bindings, 1)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,8 @@ impl ThreadSafeConnection {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Migrations have to be run per connection because we fallback to memory
|
||||||
|
/// so this needs
|
||||||
pub fn with_migrations(mut self, migrations: &'static [Migration]) -> Self {
|
pub fn with_migrations(mut self, migrations: &'static [Migration]) -> Self {
|
||||||
self.migrations = Some(migrations);
|
self.migrations = Some(migrations);
|
||||||
self
|
self
|
||||||
|
|
Loading…
Reference in a new issue