Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@ on:
- main

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: pre-commit/action@v3.0.1

test:
needs: pre-commit
strategy:
matrix:
feature_flags: ["no-default-features", "all-features"]
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v2

- name: fmt
run: cargo fmt --all -- --check
- uses: actions/checkout@v4

- name: build
run: cargo build --all --verbose
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Pre-commit

on:
pull_request:
types: [opened, ready_for_review, synchronize]
push:
branches:
- main

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0 # Fetch full history for better pre-commit performance

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Cache pre-commit
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}

- name: Install pre-commit
run: |
python -m pip install --upgrade pip
pip install pre-commit

- name: Run pre-commit on all files
run: pre-commit run --all-files

- name: Run pre-commit on changed files (for PRs)
if: github.event_name == 'pull_request'
run: pre-commit run --from-ref origin/${{ github.base_ref }} --to-ref HEAD
29 changes: 29 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
repos:
- repo: local
hooks:
- id: license-check
name: License Header Check
entry: scripts/check-license.sh
language: script
files: \.(rs|py)$
pass_filenames: true
stages: [pre-commit]

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml
- id: check-merge-conflict
- id: check-added-large-files

- repo: local
hooks:
- id: cargo-fmt
name: Cargo format
entry: cargo fmt --all -- --check
language: rust
files: \.rs$
pass_filenames: false
46 changes: 23 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
[![License](https://img.shields.io/crates/l/prollytree.svg)](https://github.com/yourusername/prollytree/blob/main/LICENSE)
[![Downloads](https://img.shields.io/crates/d/prollytree.svg)](https://crates.io/crates/prollytree)

A Prolly Tree is a hybrid data structure that combines the features of B-trees and Merkle trees to provide
both efficient data access and verifiable integrity. It is specifically designed to handle the requirements
of distributed systems and large-scale databases, making indexes syncable and distributable over
A Prolly Tree is a hybrid data structure that combines the features of B-trees and Merkle trees to provide
both efficient data access and verifiable integrity. It is specifically designed to handle the requirements
of distributed systems and large-scale databases, making indexes syncable and distributable over
peer-to-peer (P2P) networks.

## Key Features
Expand Down Expand Up @@ -111,23 +111,23 @@ use prollytree::git::GitVersionedKvStore;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize git-backed store
let mut store = GitVersionedKvStore::init("./my-data")?;

// Set values (automatically stages changes)
store.set(b"config/api_key", b"secret123")?;
store.set(b"config/timeout", b"30")?;

// Commit changes
store.commit("Update API configuration")?;

// Create a branch for experiments
store.checkout_new_branch("feature/new-settings")?;
store.set(b"config/timeout", b"60")?;
store.commit("Increase timeout")?;

// Switch back and see the difference
store.checkout("main")?;
let timeout = store.get(b"config/timeout")?; // Returns b"30"

Ok(())
}
```
Expand All @@ -143,23 +143,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize SQL-capable storage
let storage = ProllyStorage::<32>::init("./data")?;
let mut glue = Glue::new(storage);

// Create table and insert data
glue.execute("CREATE TABLE users (id INTEGER, name TEXT, age INTEGER)").await?;
glue.execute("INSERT INTO users VALUES (1, 'Alice', 30)").await?;
glue.execute("INSERT INTO users VALUES (2, 'Bob', 25)").await?;

// Query with SQL
let result = glue.execute("SELECT * FROM users WHERE age > 26").await?;
// Returns: [(1, 'Alice', 30)]

// Time travel query (requires commit)
glue.storage.commit("Initial user data").await?;
glue.execute("UPDATE users SET age = 31 WHERE id = 1").await?;

// Query previous version
let old_data = glue.storage.query_at_commit("HEAD~1", "SELECT * FROM users").await?;

Ok(())
}
```
Expand All @@ -176,19 +176,19 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut memory = AgentMemorySystem::init_with_thread_safe_git(
"./agent_memory", "assistant_001".to_string(), None
)?;

// Store conversation in short-term memory
memory.short_term.store_conversation_turn(
"session_123", "user", "What's the weather in Tokyo?", None
).await?;

// Store facts in semantic memory
memory.semantic.store_fact(
"location", "tokyo",
json!({"timezone": "JST", "temp": "22°C"}),
0.9, "weather_api"
).await?;

// Query memories
let query = MemoryQuery {
namespace: None,
Expand All @@ -201,11 +201,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
include_expired: false,
};
let results = memory.semantic.query(query).await?;

// Create checkpoint
let commit_id = memory.checkpoint("Weather session").await?;
println!("Stored {} memories, checkpoint: {}", results.len(), commit_id);

Ok(())
}
```
Expand All @@ -219,19 +219,19 @@ use prollytree::storage::InMemoryNodeStorage;
fn main() {
let storage = InMemoryNodeStorage::<32>::new();
let mut tree = ProllyTree::new(storage, Default::default());

// Insert sensitive data
tree.insert(b"balance:alice".to_vec(), b"1000".to_vec());
tree.insert(b"balance:bob".to_vec(), b"500".to_vec());

// Generate cryptographic proof
let proof = tree.generate_proof(b"balance:alice").unwrap();
let root_hash = tree.root_hash();

// Verify proof (can be done by third party)
let is_valid = tree.verify_proof(&proof, b"balance:alice", b"1000");
assert!(is_valid);

// Root hash changes if any data changes
tree.update(b"balance:alice".to_vec(), b"1100".to_vec());
let new_root = tree.root_hash();
Expand All @@ -249,4 +249,4 @@ Contributions are welcome! Please submit a pull request or open an issue to disc

## License

This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
This project is licensed under the Apache License 2.0. See the [LICENSE](LICENSE) file for details.
18 changes: 9 additions & 9 deletions benches/sql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async fn setup_database(record_count: usize) -> (Glue<ProllyStorage<32>>, TempDi
// Insert test data
for i in 0..record_count {
let insert_sql = format!(
"INSERT INTO users (id, name, email, age, city, created_at)
"INSERT INTO users (id, name, email, age, city, created_at)
VALUES ({}, 'User{}', 'user{}@example.com', {}, 'City{}', TIMESTAMP '2024-01-{:02} 12:00:00')",
i, i, i, 20 + (i % 50), i % 10, (i % 28) + 1
);
Expand Down Expand Up @@ -147,7 +147,7 @@ fn bench_sql_join(c: &mut Criterion) {
// Insert orders
for i in 0..size * 2 {
let sql = format!(
"INSERT INTO orders (id, user_id, amount, status)
"INSERT INTO orders (id, user_id, amount, status)
VALUES ({}, {}, {}, '{}')",
i,
i % size,
Expand Down Expand Up @@ -198,7 +198,7 @@ fn bench_sql_aggregation(c: &mut Criterion) {
runtime.block_on(async {
let result = glue
.execute(
"SELECT city,
"SELECT city,
COUNT(*) as user_count,
AVG(age) as avg_age,
MIN(age) as min_age,
Expand Down Expand Up @@ -237,8 +237,8 @@ fn bench_sql_update(c: &mut Criterion) {
// Update multiple records
let result = glue
.execute(
"UPDATE users
SET age = age + 1,
"UPDATE users
SET age = age + 1,
city = 'UpdatedCity'
WHERE age < 30",
)
Expand Down Expand Up @@ -368,16 +368,16 @@ fn bench_sql_complex_query(c: &mut Criterion) {
// Complex query with subqueries
let result = glue
.execute(
"SELECT
"SELECT
u.city,
COUNT(DISTINCT u.id) as user_count,
(SELECT COUNT(*)
FROM users u2
(SELECT COUNT(*)
FROM users u2
WHERE u2.city = u.city AND u2.age > 40) as senior_count,
AVG(u.age) as avg_age
FROM users u
WHERE u.id IN (
SELECT id FROM users
SELECT id FROM users
WHERE age BETWEEN 25 AND 45
)
GROUP BY u.city
Expand Down
10 changes: 5 additions & 5 deletions docs/git.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,11 +267,11 @@ git-prolly diff main feature/preferences
git-prolly diff main feature/preferences --format=detailed
# Output: Detailed Key-Value Changes (main -> feature/preferences):
# ═══════════════════════════════════════
#
#
# Key: pref:123:notifications
# Status: Added
# Value: "enabled"
#
#
# Key: user:123
# Status: Modified
# Old Value: "John Doe"
Expand Down Expand Up @@ -307,7 +307,7 @@ git-prolly show HEAD
# Output: Commit: f1e2d3c4 - Add user preferences
# Author: Developer
# Date: 2024-01-15 10:30:00
#
#
# Key-Value Changes:
# + pref:123:notifications = "enabled"
# ~ user:123 = "John Doe" -> "John A. Doe"
Expand Down Expand Up @@ -350,7 +350,7 @@ git-prolly history user:123 --format=detailed
# Date: 2024-01-15 10:30:00 UTC
# Author: Developer
# Message: Update user profile
#
#
# Commit: a1b2c3d4e5f6789012345678901234567890abcd
# Date: 2024-01-15 09:15:00 UTC
# Author: Developer
Expand Down Expand Up @@ -686,4 +686,4 @@ For issues, questions, or contributions:

## License

Licensed under the Apache License, Version 2.0.
Licensed under the Apache License, Version 2.0.
16 changes: 8 additions & 8 deletions docs/sql.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ CREATE TABLE products (
category TEXT
);

INSERT INTO products VALUES
INSERT INTO products VALUES
(1, 'Laptop', 1200, 'Electronics'),
(2, 'Book', 25, 'Education');
EOF
Expand Down Expand Up @@ -191,16 +191,16 @@ CREATE TABLE products (

```sql
-- Single row insert
INSERT INTO users (id, name, email)
INSERT INTO users (id, name, email)
VALUES (1, 'Alice Johnson', 'alice@example.com');

-- Multiple row insert
INSERT INTO users (id, name, email) VALUES
INSERT INTO users (id, name, email) VALUES
(2, 'Bob Smith', 'bob@example.com'),
(3, 'Charlie Brown', 'charlie@example.com');

-- Insert without specifying columns (must match table structure)
INSERT INTO products VALUES
INSERT INTO products VALUES
(1, 'Laptop', 1200, true, 'High-performance laptop');
```

Expand Down Expand Up @@ -443,7 +443,7 @@ ORDER BY revenue DESC
LIMIT 10;

-- Customer purchase history
SELECT c.name, COUNT(DISTINCT s.id) as purchase_count,
SELECT c.name, COUNT(DISTINCT s.id) as purchase_count,
SUM(s.quantity * s.price) as total_spent
FROM customers c
JOIN sales s ON c.id = s.customer_id
Expand Down Expand Up @@ -471,7 +471,7 @@ INSERT INTO users_new (id, name, email)
SELECT id, name, email FROM users;

-- Update new fields
UPDATE users_new SET
UPDATE users_new SET
created_at = '2024-01-01',
updated_at = '2024-01-01',
status = 'active';
Expand All @@ -489,7 +489,7 @@ git prolly sql -f migrate_v2.sql
```bash
# Generate daily report
git prolly sql -o json "
SELECT
SELECT
DATE(order_date) as date,
COUNT(*) as orders,
SUM(quantity * price) as revenue
Expand Down Expand Up @@ -713,4 +713,4 @@ The `git prolly sql` command brings the power of SQL to ProllyTree's versioned s
- Track data history over time
- Export data in multiple formats

For more examples and advanced usage, see the `examples/sql_example.rs` file in the repository.
For more examples and advanced usage, see the `examples/sql_example.rs` file in the repository.
Loading