Skip to content

Commit bb7457a

Browse files
Merge pull request #293 from github/change-storage-serde
Improve SQLite storage
2 parents d15b259 + 0e55284 commit bb7457a

File tree

11 files changed

+91
-26
lines changed

11 files changed

+91
-26
lines changed

languages/tree-sitter-stack-graphs-typescript/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ clap = { version = "4", optional = true }
3232
glob = "0.3"
3333
serde = { version = "1.0", features = ["derive"] }
3434
serde_json = "1.0"
35-
stack-graphs = { version = "0.11", path = "../../stack-graphs" }
35+
stack-graphs = { version = ">=0.11, <=0.12", path = "../../stack-graphs" }
3636
tree-sitter-stack-graphs = { version = "0.7", path = "../../tree-sitter-stack-graphs" }
3737
tree-sitter-typescript = "0.20.2"
3838
tsconfig = "0.1.0"

stack-graphs/CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8-
## Unreleased
8+
## v0.12.0 -- 2023-07-27
9+
10+
### Added
11+
12+
- New `SQLiteReader::clear` and `SQLiteReader::clear_paths` methods that make it easier to reuse instances.
13+
- The method `SQLiteReader::load_graph_for_file` now returns the file handle for the loaded file.
914

1015
### Changed
1116

1217
- The `Appendable` trait has been simplified. Its `Ctx` type parameter is gone, in favor of a separate trait `ToAppendable` that is used to find appendables for a handle. The type itself moved from the `cycles` to the `stitching` module.
1318
- The `ForwardPartialPathStitcher` has been generalized so that it can be used to build paths from a database or from graph edges. It now takes a type parameter indicating the type of candidates it uses. Instead of a `Database` instance, it expects a value that implements the `Candidates` and `ToAppendable` traits. The `ForwardPartialPathStitcher::process_next_phase` expects an additional `extend_until` closure that controls whether the extended paths are considered for further extension or not (using `|_,_,_| true` retains old behavior).
1419
- The SQLite database implementation is using a new schema which stores binary instead of JSON values, resulting in faster write times and smaller databases.
20+
- Renamed method `SQLiteReader::load_graph_for_file_or_directory` to `SQLiteReader::load_graphs_for_file_or_directory`.
1521

1622
### Fixed
1723

stack-graphs/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "stack-graphs"
3-
version = "0.11.0"
3+
version = "0.12.0"
44
description = "Name binding for arbitrary programming languages"
55
homepage = "https://github.com/github/stack-graphs/tree/main/stack-graphs"
66
repository = "https://github.com/github/stack-graphs/"
@@ -15,7 +15,7 @@ edition = "2018"
1515
[features]
1616
copious-debugging = []
1717
serde = ["dep:serde", "lsp-positions/serde"]
18-
storage = ["rusqlite", "serde", "rmp-serde"]
18+
storage = ["postcard", "rusqlite", "serde"]
1919
visualization = ["serde", "serde_json"]
2020

2121
[lib]
@@ -31,7 +31,7 @@ fxhash = "0.2"
3131
itertools = "0.10"
3232
libc = "0.2"
3333
lsp-positions = { version = "0.3", path = "../lsp-positions" }
34-
rmp-serde = { version = "1.1", optional = true }
34+
postcard = { version = "1", optional = true, features = ["use-std"] }
3535
rusqlite = { version = "0.28", optional = true, features = ["bundled", "functions"] }
3636
serde = { version = "1.0", optional = true, features = ["derive"] }
3737
serde_json = { version = "1.0", optional = true }

stack-graphs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ To use this library, add the following to your `Cargo.toml`:
99

1010
``` toml
1111
[dependencies]
12-
stack-graphs = "0.11"
12+
stack-graphs = "0.12"
1313
```
1414

1515
Check out our [documentation](https://docs.rs/stack-graphs/) for more details on

stack-graphs/src/arena.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ impl<T> Arena<T> {
181181
}
182182
}
183183

184+
/// Clear the arena, keeping underlying allocated capacity. After this, all previous handles into
185+
/// the arena are invalid.
186+
#[cfg_attr(not(feature = "storage"), allow(dead_code))]
187+
#[inline(always)]
188+
pub(crate) fn clear(&mut self) {
189+
self.items.clear();
190+
}
191+
184192
/// Adds a new instance to this arena, returning a stable handle to it.
185193
///
186194
/// Note that we do not deduplicate instances of `T` in any way. If you add two instances that
@@ -280,6 +288,14 @@ impl<H, T> SupplementalArena<H, T> {
280288
}
281289
}
282290

291+
/// Clear the supplemantal arena, keeping underlying allocated capacity. After this,
292+
/// all previous handles into the arena are invalid.
293+
#[cfg_attr(not(feature = "storage"), allow(dead_code))]
294+
#[inline(always)]
295+
pub(crate) fn clear(&mut self) {
296+
self.items.clear();
297+
}
298+
283299
/// Creates a new, empty supplemental arena, preallocating enough space to store supplemental
284300
/// data for all of the instances that have already been allocated in a (regular) arena.
285301
pub fn with_capacity(arena: &Arena<H>) -> SupplementalArena<H, T> {

stack-graphs/src/partial.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2624,4 +2624,11 @@ impl PartialPaths {
26242624
partial_path_edges: Deque::new_arena(),
26252625
}
26262626
}
2627+
2628+
#[cfg_attr(not(feature = "storage"), allow(dead_code))]
2629+
pub(crate) fn clear(&mut self) {
2630+
self.partial_symbol_stacks.clear();
2631+
self.partial_scope_stacks.clear();
2632+
self.partial_path_edges.clear();
2633+
}
26272634
}

stack-graphs/src/stitching.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,18 @@ impl Database {
249249
}
250250
}
251251

252+
/// Clear the database. After this, all previous handles into the database are
253+
/// invalid.
254+
#[cfg_attr(not(feature = "storage"), allow(dead_code))]
255+
pub(crate) fn clear(&mut self) {
256+
self.partial_paths.clear();
257+
self.local_nodes.clear();
258+
self.symbol_stack_keys.clear();
259+
self.symbol_stack_key_cache.clear();
260+
self.paths_by_start_node.clear();
261+
self.root_paths_by_precondition.clear();
262+
}
263+
252264
/// Adds a partial path to this database. We do not deduplicate partial paths in any way; it's
253265
/// your responsibility to only add each partial path once.
254266
pub fn add_partial_path(

stack-graphs/src/storage.rs

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ use crate::stitching::ForwardPartialPathStitcher;
3030
use crate::CancellationError;
3131
use crate::CancellationFlag;
3232

33-
const VERSION: usize = 3;
33+
const VERSION: usize = 4;
3434

3535
const SCHEMA: &str = r#"
3636
CREATE TABLE metadata (
@@ -75,9 +75,7 @@ pub enum StorageError {
7575
#[error(transparent)]
7676
Serde(#[from] serde::Error),
7777
#[error(transparent)]
78-
RmpSerdeDecode(#[from] rmp_serde::decode::Error),
79-
#[error(transparent)]
80-
RmpSerdeEncode(#[from] rmp_serde::encode::Error),
78+
PostcardError(#[from] postcard::Error),
8179
}
8280

8381
pub type Result<T> = std::result::Result<T, StorageError>;
@@ -283,7 +281,7 @@ impl SQLiteWriter {
283281
&file.to_string_lossy(),
284282
tag,
285283
error,
286-
&rmp_serde::to_vec(&graph)?,
284+
&postcard::to_stdvec(&graph)?,
287285
))?;
288286
Ok(())
289287
}
@@ -323,7 +321,7 @@ impl SQLiteWriter {
323321
let mut stmt =
324322
conn.prepare_cached("INSERT INTO graphs (file, tag, value) VALUES (?, ?, ?)")?;
325323
let graph = serde::StackGraph::from_graph_filter(graph, &FileFilter(file));
326-
stmt.execute((file_str, tag, &rmp_serde::to_vec(&graph)?))?;
324+
stmt.execute((file_str, tag, &postcard::to_stdvec(&graph)?))?;
327325
Ok(())
328326
}
329327

@@ -364,7 +362,7 @@ impl SQLiteWriter {
364362
);
365363
let symbol_stack = path.symbol_stack_precondition.storage_key(graph, partials);
366364
let path = serde::PartialPath::from_partial_path(graph, partials, path);
367-
root_stmt.execute((file_str, symbol_stack, &rmp_serde::to_vec(&path)?))?;
365+
root_stmt.execute((file_str, symbol_stack, &postcard::to_stdvec(&path)?))?;
368366
root_path_count += 1;
369367
} else if start_node.is_in_file(file) {
370368
copious_debugging!(
@@ -375,7 +373,7 @@ impl SQLiteWriter {
375373
node_stmt.execute((
376374
file_str,
377375
path.start_node.local_id,
378-
&rmp_serde::to_vec(&path)?,
376+
&postcard::to_stdvec(&path)?,
379377
))?;
380378
node_path_count += 1;
381379
} else {
@@ -447,6 +445,28 @@ impl SQLiteReader {
447445
})
448446
}
449447

448+
/// Clear all data that has been loaded into this reader instance.
449+
/// After this call, all existing handles from this reader are invalid.
450+
pub fn clear(&mut self) {
451+
self.loaded_graphs.clear();
452+
self.graph = StackGraph::new();
453+
454+
self.loaded_node_paths.clear();
455+
self.loaded_root_paths.clear();
456+
self.partials.clear();
457+
self.db.clear();
458+
}
459+
460+
/// Clear path data that has been loaded into this reader instance.
461+
/// After this call, all node handles remain valid, but all path data
462+
/// is invalid.
463+
pub fn clear_paths(&mut self) {
464+
self.loaded_node_paths.clear();
465+
self.loaded_root_paths.clear();
466+
self.partials.clear();
467+
self.db.clear();
468+
}
469+
450470
/// Get the file's status in the database. If a tag is provided, it must match or the file
451471
/// is reported missing.
452472
pub fn status_for_file<T: AsRef<str>>(
@@ -485,7 +505,7 @@ impl SQLiteReader {
485505
}
486506

487507
/// Ensure the graph for the given file is loaded.
488-
pub fn load_graph_for_file(&mut self, file: &str) -> Result<()> {
508+
pub fn load_graph_for_file(&mut self, file: &str) -> Result<Handle<File>> {
489509
Self::load_graph_for_file_inner(file, &mut self.graph, &mut self.loaded_graphs, &self.conn)
490510
}
491511

@@ -494,21 +514,21 @@ impl SQLiteReader {
494514
graph: &mut StackGraph,
495515
loaded_graphs: &mut HashSet<String>,
496516
conn: &Connection,
497-
) -> Result<()> {
517+
) -> Result<Handle<File>> {
498518
copious_debugging!("--> Load graph for {}", file);
499519
if !loaded_graphs.insert(file.to_string()) {
500520
copious_debugging!(" * Already loaded");
501-
return Ok(());
521+
return Ok(graph.get_file(file).expect("loaded file to exist"));
502522
}
503523
copious_debugging!(" * Load from database");
504-
let mut stmt = conn.prepare_cached("SELECT json FROM graphs WHERE file = ?")?;
524+
let mut stmt = conn.prepare_cached("SELECT value FROM graphs WHERE file = ?")?;
505525
let value = stmt.query_row([file], |row| row.get::<_, Vec<u8>>(0))?;
506-
let file_graph = rmp_serde::from_slice::<serde::StackGraph>(&value)?;
526+
let file_graph = postcard::from_bytes::<serde::StackGraph>(&value)?;
507527
file_graph.load_into(graph)?;
508-
Ok(())
528+
Ok(graph.get_file(file).expect("loaded file to exist"))
509529
}
510530

511-
pub fn load_graph_for_file_or_directory(
531+
pub fn load_graphs_for_file_or_directory(
512532
&mut self,
513533
file_or_directory: &Path,
514534
cancellation_flag: &dyn CancellationFlag,
@@ -559,7 +579,7 @@ impl SQLiteReader {
559579
&mut self.loaded_graphs,
560580
&self.conn,
561581
)?;
562-
let path = rmp_serde::from_slice::<serde::PartialPath>(&value)?;
582+
let path = postcard::from_bytes::<serde::PartialPath>(&value)?;
563583
let path = path.to_partial_path(&mut self.graph, &mut self.partials)?;
564584
copious_debugging!(
565585
" > Loaded {}",
@@ -613,7 +633,7 @@ impl SQLiteReader {
613633
&mut self.loaded_graphs,
614634
&self.conn,
615635
)?;
616-
let path = rmp_serde::from_slice::<serde::PartialPath>(&value)?;
636+
let path = postcard::from_bytes::<serde::PartialPath>(&value)?;
617637
let path = path.to_partial_path(&mut self.graph, &mut self.partials)?;
618638
copious_debugging!(
619639
" > Loaded {}",

tree-sitter-stack-graphs/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## v0.7.1 -- 2023-07-27
9+
10+
Support `stack-graphs` version `0.12`.
11+
812
## v0.7.0 -- 2023-06-08
913

1014
### Library

tree-sitter-stack-graphs/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "tree-sitter-stack-graphs"
3-
version = "0.7.0"
3+
version = "0.7.1"
44
description = "Create stack graphs using tree-sitter parsers"
55
homepage = "https://github.com/github/stack-graphs/tree/main/tree-sitter-stack-graphs"
66
repository = "https://github.com/github/stack-graphs/"
@@ -69,7 +69,7 @@ regex = "1"
6969
rust-ini = "0.18"
7070
serde_json = { version="1.0", optional=true }
7171
sha1 = { version="0.10", optional=true }
72-
stack-graphs = { version="0.11", path="../stack-graphs" }
72+
stack-graphs = { version=">=0.11, <=0.12", path="../stack-graphs" }
7373
thiserror = "1.0"
7474
time = { version = "0.3", optional = true }
7575
tokio = { version = "1.26", optional = true, features = ["io-std", "rt", "rt-multi-thread"] }

0 commit comments

Comments
 (0)