Skip to content

sgchris/sledoview

Repository files navigation

SledoView

License

A powerful console application for performing CRUD operations on SLED database files through an interactive terminal interface.

Features

  • 🔍 Interactive REPL - Browse your SLED database with a user-friendly terminal interface
  • 🌳 Tree Management - Work with named trees for organized data storage and isolation
  • 🔎 Pattern Matching - Search keys, values, and trees using glob patterns or regular expressions
  • ✏️ CRUD Operations - Create, Read, Update, and Delete key-value pairs in any tree
  • 📝 Write Operations - Safely modify database contents with immediate persistence
  • 🎯 Tree Selection - Switch between trees with visual prompt indicators

Installation

From Source

git clone https://github.com/sgchris/sledoview
cd sledoview
cargo build --release

The executable will be available at target/release/sledoview (or target/release/sledoview.exe on Windows).

Usage

Basic Usage

sledoview /path/to/your/sled.db

Upon successful validation and opening, you'll see:

SledoView - SLED Database Client
═══════════════════════════════════
Validating database...
✓ Database validation passed
✓ Successfully opened database: /path/to/your/sled.db
✓ Database is writable - modification commands available

Interactive SLED Database Client
Type 'help' for available commands or 'exit' to quit.
Use TAB for completion, type partial keys and TAB to auto-complete!

> 

When a tree is selected, the prompt will show the tree name:

[settings]> 

Available Commands

count

Display the total number of records in the database.

> count
Total records: 1,532

list [pattern]

List all keys matching the specified pattern. Uses glob pattern matching by default.

Examples:

# List all keys
> list
> list *

# List keys starting with "user_"
> list user_*

# List keys ending with "_config"
> list *_config

# List keys containing "session"
> list *session*

list regex <pattern>

List keys matching a regular expression pattern.

Examples:

# List keys matching a regex pattern
> list regex user_\d+

# List keys with specific format
> list regex ^config_[a-z]+$

# List keys containing numbers
> list regex .*\d.*

set <key> <value>

Set or update a key-value pair in the database. The operation will be immediately persisted to disk.

Key Validation Rules:

  • Must contain only alphanumeric characters, _, -, ., :, /, and spaces
  • Maximum length of 512 characters
  • Cannot be empty

Quoting Support:

  • Use double quotes to include spaces in keys or values
  • Escape quotes within quoted strings with backslash: \"
  • Examples of valid quoted usage:
    • "key with spaces"
    • "value with \"quotes\""
    • "path/to/config"

Examples:

# Set a simple key-value pair
> set user_name "John Doe"
✓ Successfully set key 'user_name'

# Set a key with spaces (using quotes)
> set "user settings" "{'theme': 'dark', 'lang': 'en'}"
✓ Successfully set key 'user settings'

# Update an existing key
> set config_timeout 3600
✓ Successfully set key 'config_timeout'

# Set a complex value with quotes
> set message "He said \"Hello, World!\""
✓ Successfully set key 'message'

delete <key>

Delete a key from the database. The operation will be immediately persisted to disk.

Examples:

# Delete a simple key
> delete user_temp
✓ Successfully deleted key 'user_temp'

# Delete a key with spaces (using quotes)  
> delete "temporary setting"
✓ Successfully deleted key 'temporary setting'

# Try to delete a non-existent key
> delete nonexistent
✗ Key 'nonexistent' not found

get <key>

Retrieve detailed information about a specific key, including its value, size, and UTF-8 validity.

Examples:

> get user_123
═══════════════════════════════════════════════════════
Key: user_123
Size: 45 bytes
UTF-8: Yes
Value:
───────────────────────────────────────────────────────
{"name": "John Doe", "email": "[email protected]"}
═══════════════════════════════════════════════════════

> get config_settings
═══════════════════════════════════════════════════════
Key: config_settings  
Size: 156 bytes
UTF-8: Yes
Value:
───────────────────────────────────────────────────────
{"theme": "dark", "language": "en-US", "timeout": 3600}
═══════════════════════════════════════════════════════

search <pattern>

Search for entries where the value matches the specified pattern.

Examples:

# Search for values containing email addresses
> search *@example.com

# Search for values containing specific text
> search *John*

# Search for JSON values containing specific fields
> search *"theme"*

search regex <pattern>

Search for entries where the value matches a regular expression.

Examples:

# Search for email addresses using regex
> search regex \w+@\w+\.\w+

# Search for dates in YYYY-MM-DD format
> search regex \d{4}-\d{2}-\d{2}

# Search for JSON objects with specific structure
> search regex \{"name":\s*"[^"]+".*\}

Tree Management Commands

SLED databases support multiple named trees for organizing data. Trees provide complete isolation - keys in one tree don't affect keys in another tree. When no tree is selected, operations work on the default tree.

trees [pattern]

List all trees in the database, optionally filtered by pattern.

Examples:

# List all trees
> trees
Found 5 trees:
  settings
  sessions
  cache
  logs
  metrics

# List trees matching a pattern
> trees *_data
Found 2 trees:
  binary_data
  test_data

# List trees starting with "user"
> trees user*
Found 3 trees:
  user_profiles
  user_sessions
  user_preferences

trees regex <pattern>

List trees matching a regular expression pattern.

Examples:

# List trees with numbers
> trees regex .*\d+
Found 2 trees:
  cache_v2
  session_store_1

# List trees ending with specific suffixes
> trees regex .*(data|cache)$
Found 4 trees:
  user_data
  temp_cache
  binary_data
  session_cache

select <tree>

Select a tree to work with. All subsequent CRUD operations (list, get, set, delete, search) will operate only on the selected tree.

Examples:

# Select a tree
> select settings
✓ Selected tree: settings
[settings]> 

# Now all operations work on the 'settings' tree
[settings]> count
Total records: 15

[settings]> list
Found 15 keys:
  1: app.theme = dark
  2: app.language = en-US
  3: ui.sidebar_width = 250
  ...

# Set a key in the selected tree
[settings]> set debug.enabled true
✓ Successfully set key debug.enabled

unselect

Return to working with the default tree. After unselecting, operations will work on keys that aren't in any named tree.

Examples:

[settings]> unselect
✓ Tree unselected. Now working with the default tree.
> 

# If no tree was selected
> unselect
! No tree was previously selected.

Tree Operation Examples

# Check default tree content
> count
Total records: 10

> list
Found 10 keys:
  1: user:001
  2: user:002
  3: config:main
  ...

# Switch to settings tree
> select settings
✓ Selected tree: settings
[settings]> count
Total records: 5

[settings]> set theme dark
✓ Successfully set key theme

# Switch to different tree
[settings]> select sessions  
✓ Selected tree: sessions
[sessions]> count
Total records: 23

[sessions]> list sess_*
Found 12 keys:
  1: sess_abc123
  2: sess_def456
  ...

# Return to default tree
[sessions]> unselect
✓ Tree unselected. Now working with the default tree.
> count
Total records: 10

# The key we set in settings tree isn't in default tree
> get theme
✗ Key 'theme' not found

# But it's still in the settings tree
> select settings
[settings]> get theme
═══════════════════════════════════════════════════════
Key: theme
Size: 4 bytes
UTF-8: Yes
Value:
───────────────────────────────────────────────────────
dark
═══════════════════════════════════════════════────────

help

Display the help message with all available commands.

exit / quit / q

Exit the application.

Output Examples

Basic Command Examples

> count
Total records: 150

> list user_*
Found 3 keys:
  1: user_001
  2: user_002  
  3: user_admin

> set new_user "Alice Smith"
✓ Successfully set key 'new_user'

> get new_user
═══════════════════════════════════════════════════════
Key: new_user
Size: 11 bytes
UTF-8: Yes
Value:
───────────────────────────────────────────────────────
Alice Smith
═══════════════════════════════════════════════────────

> delete temp_key
✓ Successfully deleted key 'temp_key'

> search *@gmail.com
Found 5 matches:
  1: email_john => [email protected]
  2: email_mary => [email protected]
  3: contact_primary => [email protected]
  4: backup_email => [email protected]
  5: user_email_005 => [email protected]

Tree Management Examples

> trees
Found 8 trees:
  binary_data
  cache
  configuration
  logs
  metrics
  sessions
  settings
  test_data

> select settings
✓ Selected tree: settings
[settings]> list app.*
Found 3 keys:
  1: app.language = en-US
  2: app.theme = dark
  3: app.timeout = 3600

[settings]> set app.version "2.1.0"
✓ Successfully set key app.version

[settings]> select sessions
✓ Selected tree: sessions
[sessions]> count
Total records: 45

[sessions]> trees *data*
Found 2 trees:
  binary_data
  test_data

[sessions]> unselect
✓ Tree unselected. Now working with the default tree.
> 

Development

Prerequisites

  • Rust 1.70+ (2021 edition)
  • Cargo

Building

git clone https://github.com/sgchris/sledoview
cd sledoview
cargo build --release

Running Tests

cargo test

Test Coverage

The project includes comprehensive tests covering:

  • Database validation logic
  • All CLI commands and their variations (including CRUD operations)
  • Pattern matching (both glob and regex)
  • Quote parsing and argument handling
  • Key validation logic
  • Write operations and persistence
  • Error handling scenarios
  • Binary data handling
  • Edge cases (empty databases, non-existent keys, etc.)

Contributing

We welcome contributions! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

Guidelines

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Write tests for your changes
  4. Ensure all tests pass (cargo test)
  5. Follow Rust formatting conventions (cargo fmt)
  6. Check for linting issues (cargo clippy)
  7. Commit your changes (git commit -m 'Add some amazing feature')
  8. Push to the branch (git push origin feature/amazing-feature)
  9. Open a Pull Request

Code Style

  • Follow standard Rust formatting (cargo fmt)
  • Ensure code passes Clippy lints (cargo clippy)
  • Add documentation for public APIs
  • Write tests for new functionality

License

This project is licensed under the MIT License - see the LICENSE-MIT file for details.

Acknowledgments

  • SLED - The embedded database that makes this tool possible
  • Rustyline - For the excellent REPL functionality
  • Colored - For beautiful terminal colors