Add SQL commands for local database operations#2108
Conversation
WalkthroughAdds two new local-db CLI commands (DecodedEventsToSql and Dump), updates CLI wiring and exports, extends SQLite schema with a Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor U as User
participant CLI as CLI (LocalDb)
participant CMD as DecodedEventsToSql
participant FS as File System
participant Conv as Converter
U->>CLI: local-db decoded-events-to-sql --input <json> [--output <sql>]
CLI->>CMD: execute()
CMD->>FS: read <json>
CMD->>Conv: parse JSON → generate SQL
Conv-->>CMD: SQL text
CMD->>FS: write SQL to output (provided or default)
CMD-->>CLI: Result / message
CLI-->>U: exit status
sequenceDiagram
autonumber
actor U as User
participant CLI as CLI (LocalDb)
participant D as DbDump
participant Shell as sqlite3
participant FS as File System
participant GZ as gzip
U->>CLI: local-db dump --input <data.sql> --table-schema <schema.sql> [--db <path>] [--dump <path>]
CLI->>D: execute()
D->>FS: resolve paths, remove existing DB if present
D->>Shell: create DB, apply schema.sql
D->>Shell: apply data.sql
D->>Shell: .dump -> dump.sql
D->>GZ: gzip dump.sql -> dump.sql.gz
D-->>CLI: Result / message
CLI-->>U: exit status
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (6)
crates/cli/.gitignore(1 hunks)crates/cli/src/commands/local_db/decoded_events_to_sql.rs(1 hunks)crates/cli/src/commands/local_db/dump.rs(1 hunks)crates/cli/src/commands/local_db/mod.rs(1 hunks)crates/cli/src/lib.rs(2 hunks)crates/common/src/raindex_client/sqlite_web/sql/tables.sql(1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: git-clean
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
- GitHub Check: build-tauri (ubuntu-22.04, true)
- GitHub Check: copilot-setup-steps
| let _ = Command::new("sqlite3") | ||
| .arg(&db_path) | ||
| .arg(format!(".read {}", tables_sql_path)) | ||
| .status()?; | ||
|
|
||
| let _ = Command::new("sqlite3") | ||
| .arg(&db_path) | ||
| .arg(format!(".read {}", sql_file_path)) | ||
| .status()?; | ||
|
|
||
| let output = Command::new("sqlite3") | ||
| .arg(&db_path) | ||
| .arg(".dump") | ||
| .output()?; | ||
|
|
||
| fs::write(&dump_file_path, output.stdout)?; | ||
|
|
||
| Command::new("gzip") | ||
| .arg("-f") | ||
| .arg(&dump_file_path) | ||
| .status()?; | ||
|
|
There was a problem hiding this comment.
Propagate sqlite3/gzip failures
We’re ignoring every external command’s exit status. If sqlite3 or gzip exits non‑zero (bad schema/data, disk full, etc.), the CLI happily proceeds and produces a corrupted/empty dump without signalling failure. Please capture the status, ensure it succeeded, and surface stderr for debugging.
-use anyhow::Result;
+use anyhow::{ensure, Context, Result};
@@
- let _ = Command::new("sqlite3")
- .arg(&db_path)
- .arg(format!(".read {}", tables_sql_path))
- .status()?;
-
- let _ = Command::new("sqlite3")
- .arg(&db_path)
- .arg(format!(".read {}", sql_file_path))
- .status()?;
-
- let output = Command::new("sqlite3")
- .arg(&db_path)
- .arg(".dump")
- .output()?;
-
- fs::write(&dump_file_path, output.stdout)?;
-
- Command::new("gzip")
- .arg("-f")
- .arg(&dump_file_path)
- .status()?;
+ let schema_status = Command::new("sqlite3")
+ .arg(&db_path)
+ .arg(format!(".read {}", tables_sql_path))
+ .status()
+ .context("sqlite3 failed while applying table schema")?;
+ ensure!(schema_status.success(), "sqlite3 returned {}", schema_status);
+
+ let data_status = Command::new("sqlite3")
+ .arg(&db_path)
+ .arg(format!(".read {}", sql_file_path))
+ .status()
+ .context("sqlite3 failed while applying data dump")?;
+ ensure!(data_status.success(), "sqlite3 returned {}", data_status);
+
+ let output = Command::new("sqlite3")
+ .arg(&db_path)
+ .arg(".dump")
+ .output()
+ .context("sqlite3 failed while dumping database")?;
+ ensure!(
+ output.status.success(),
+ "sqlite3 dump failed: {}",
+ String::from_utf8_lossy(&output.stderr)
+ );
+
+ fs::write(&dump_file_path, output.stdout)?;
+
+ let gzip_status = Command::new("gzip")
+ .arg("-f")
+ .arg(&dump_file_path)
+ .status()
+ .context("gzip failed while compressing dump")?;
+ ensure!(gzip_status.success(), "gzip returned {}", gzip_status);🤖 Prompt for AI Agents
In crates/cli/src/commands/local_db/dump.rs around lines 34 to 55, the code
currently ignores exit statuses of sqlite3/gzip commands which can produce
corrupted or empty dumps; change each Command::new(...).status()? call to run
the command with .output()? so you can check output.status.success() and, on
failure, return an Err (or bail!) that includes the command, its args, exit code
and stderr (converted to string) for debugging; specifically for the two ".read"
invocations and the final "gzip" invocation capture output, assert success, and
for the dump step check output.status.success() before writing dump_file_path
and include stdout/stderr in any error returned.
There was a problem hiding this comment.
this is fine we are going to get these errors any way
There was a problem hiding this comment.
@findolor, understood. I'll leave the error handling as-is. 👍
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (3)
crates/cli/src/commands/local_db/decode_events.rs(3 hunks)crates/cli/src/commands/local_db/decoded_events_to_sql.rs(1 hunks)crates/common/src/raindex_client/sqlite_web/decode.rs(5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
crates/**/{src,tests,benches,examples}/**/*.rs
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
crates/**/{src,tests,benches,examples}/**/*.rs: Rust crates: lint withcargo clippy --workspace --all-targets --all-features -D warnings
Rust crates: ensurecargo test --workspacepasses
Rust crates: build withcargo buildduring development/readiness checks
Files:
crates/cli/src/commands/local_db/decoded_events_to_sql.rscrates/common/src/raindex_client/sqlite_web/decode.rscrates/cli/src/commands/local_db/decode_events.rs
🧬 Code graph analysis (1)
crates/cli/src/commands/local_db/decoded_events_to_sql.rs (3)
crates/common/src/raindex_client/sqlite_web/insert.rs (1)
decoded_events_to_sql(84-142)crates/cli/src/commands/local_db/decode_events.rs (1)
execute(20-54)crates/cli/src/lib.rs (2)
execute(22-31)execute(66-77)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
- GitHub Check: build-tauri (ubuntu-22.04, true)
- GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-artifacts)
- GitHub Check: standard-tests (ubuntu-latest, test-js-bindings)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-legal)
- GitHub Check: standard-tests (ubuntu-latest, rainix-wasm-test)
- GitHub Check: standard-tests (ubuntu-latest, ob-rs-test, true)
- GitHub Check: standard-tests (ubuntu-latest, rainix-rs-static)
- GitHub Check: standard-tests (ubuntu-latest, rainix-rs-artifacts, true)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-artifacts)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-static)
- GitHub Check: standard-tests (ubuntu-latest, rainix-sol-test)
- GitHub Check: git-clean
- GitHub Check: test
- GitHub Check: test
- GitHub Check: test
- GitHub Check: Deploy-Docs-Preview
- GitHub Check: Deploy-Preview-Push
🔇 Additional comments (7)
crates/cli/src/commands/local_db/decode_events.rs (3)
8-8: LGTM!The Path and PathBuf imports are necessary for the enhanced output path derivation logic introduced in this PR.
34-40: LGTM!The output path derivation logic is well-designed, properly handling the edge case where the input file has no parent directory. This approach is consistent with the new DecodedEventsToSql command introduced in this PR.
43-52: LGTM!The test simplification removes unnecessary complexity while maintaining correctness. The use of
.display()for PathBuf formatting in error messages and logs is idiomatic Rust.Also applies to: 178-178
crates/cli/src/commands/local_db/decoded_events_to_sql.rs (3)
11-21: LGTM!The struct definition follows clap conventions correctly. The
end_blockparameter is appropriately included to support the sync_status table update in the generated SQL.
37-43: LGTM!The output path derivation logic is consistent with the pattern used in
decode_events.rs, with an appropriate default filename for SQL output.
53-154: LGTM!The test suite provides comprehensive coverage of success scenarios, error conditions, and edge cases. The tests follow proper tokio async testing conventions.
crates/common/src/raindex_client/sqlite_web/decode.rs (1)
14-14: LGTM!The addition of
Deserializederives to these types enables the new CLI commands to read decoded events from JSON files. The serde bounds onDecodedEventDataare correctly specified to requireT: Deserialize<'de>for deserialization, maintaining proper generic constraints.Also applies to: 24-24, 70-71, 81-81, 162-162
| let file = File::open(&self.input_file) | ||
| .with_context(|| format!("Failed to open input file: {:?}", self.input_file))?; |
There was a problem hiding this comment.
Use {} instead of {:?} for cleaner error messages.
The {:?} format specifier will display the string with surrounding quotes. For consistency with decode_events.rs (line 24) and cleaner error messages, use {} instead.
Apply this diff:
- let file = File::open(&self.input_file)
- .with_context(|| format!("Failed to open input file: {:?}", self.input_file))?;
+ let file = File::open(&self.input_file)
+ .with_context(|| format!("Failed to open input file: {}", self.input_file))?;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let file = File::open(&self.input_file) | |
| .with_context(|| format!("Failed to open input file: {:?}", self.input_file))?; | |
| let file = File::open(&self.input_file) | |
| .with_context(|| format!("Failed to open input file: {}", self.input_file))?; |
🤖 Prompt for AI Agents
In crates/cli/src/commands/local_db/decoded_events_to_sql.rs around lines 27-28,
replace the debug-style formatting that uses "{:?}" in the with_context format
string with a display-style formatting; change the call to format!("Failed to
open input file: {:?}", self.input_file) to use "{}" and call
self.input_file.display() (e.g. format!("Failed to open input file: {}",
self.input_file.display())) so the error message is clean and consistent with
decode_events.rs.
|
@coderabbitai assess this PR size classification for the totality of the PR with the following criterias and report it in your comment: S/M/L PR Classification Guidelines:This guide helps classify merged pull requests by effort and complexity rather than just line count. The goal is to assess the difficulty and scope of changes after they have been completed. Small (S)Characteristics:
Review Effort: Would have taken 5-10 minutes Examples:
Medium (M)Characteristics:
Review Effort: Would have taken 15-30 minutes Examples:
Large (L)Characteristics:
Review Effort: Would have taken 45+ minutes Examples:
Additional Factors to ConsiderWhen deciding between sizes, also consider:
Notes:
|
|
Tip For best results, initiate chat on the files or code changes. SIZE=M 🧠 Learnings used |
Caution
Chained PR
Do not merge before #2104
Note
This PR rainlanguage/rainix#88 also needs to be merged to enable sqlite3 command in nix shell
Motivation
Previously, we could fetch and decode events but lacked the ability to convert decoded events to SQL
format and create complete database dumps.
Solution
This PR adds two new CLI commands for local database SQL operations:
and end block parameters
dumps
Key changes include:
handling
Checks
By submitting this for review, I'm confirming I've done the following:
Summary by CodeRabbit
New Features
Improvements
Chores