This guide demonstrates how to integrate SQLite databases with Skardi, including INSERT, UPDATE, DELETE operations and federated queries with CSV data.
SQLite requires no external server — just a local .db file:
# 1. Create the SQLite database and test data
sqlite3 demo/sqlite/demo.db << 'EOF'
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT UNIQUE NOT NULL
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL,
product TEXT NOT NULL,
amount REAL NOT NULL
);
CREATE TABLE user_order_stats (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL UNIQUE,
user_name TEXT NOT NULL,
user_email TEXT NOT NULL,
total_orders INTEGER NOT NULL,
total_spent REAL NOT NULL,
last_order_date TEXT
);
INSERT INTO users (name, email) VALUES
('Alice Smith', 'alice@example.com'),
('Bob Johnson', 'bob@example.com'),
('Carol Williams', 'carol@example.com');
INSERT INTO orders (user_id, product, amount) VALUES
(1, 'Laptop', 999.99),
(2, 'Keyboard', 79.99),
(3, 'Monitor', 299.99);
EOF
# 1b. Create sample CSV file (for federated query demo)
mkdir -p demo/sample_data
cat > demo/sample_data/orders.csv << 'EOF'
order_id,user_id,product,amount,order_date
1001,1,Laptop,999.99,2024-01-15
1002,1,Mouse,29.99,2024-01-16
1003,2,Keyboard,79.99,2024-01-17
1004,3,Monitor,299.99,2024-01-18
1005,1,USB Cable,9.99,2024-01-19
1006,2,Headphones,149.99,2024-01-20
EOF
# 2. Start Skardi server
cargo run --bin skardi-server -- \
--ctx demo/sqlite/ctx_sqlite_demo.yaml \
--pipeline demo/sqlite/pipelines/ \
--port 8080
# 3. Execute with parameters
curl -X POST http://localhost:8080/query_user_by_id/execute \
-H "Content-Type: application/json" \
-d '{"user_id": 1}'SQLite tables can be queried directly by path — no context file needed. Use the pattern path/to/file.db.table_name:
# Query a table directly
skardi query --sql "SELECT * FROM './demo/sqlite/demo.db.users'"
# Join two tables from the same database
skardi query --sql "
SELECT u.name, o.product, o.amount
FROM './demo/sqlite/demo.db.users' u
JOIN './demo/sqlite/demo.db.orders' o ON u.id = o.user_id
"
# Works with .sqlite and .sqlite3 extensions too
skardi query --sql "SELECT * FROM './data/app.sqlite.customers'"
skardi query --sql "SELECT * FROM './data/app.sqlite3.customers'"-
Create the database (see Quick Start step 1 above)
-
Start Skardi server with pipelines:
Example pipeline files are provided in
demo/sqlite/pipelines/:query_user_by_id.yaml- Query user by IDinsert_user.yaml- Insert new userupdate_user_email.yaml- Update a user's email by namedelete_user.yaml- Delete a user by namefederated_join_and_insert.yaml- Join CSV + SQLite and write results back
Pass them all at server start using the
--pipelineflag (accepts a directory or individual files):cargo run --bin skardi-server -- \ --ctx demo/sqlite/ctx_sqlite_demo.yaml \ --pipeline demo/sqlite/pipelines/ \ --port 8080
-
Execute pipelines:
# Query a user by ID curl -X POST http://localhost:8080/query_user_by_id/execute \ -H "Content-Type: application/json" \ -d '{"user_id": 1}'
Insert a new user into the SQLite table:
# Execute INSERT with parameters
curl -X POST http://localhost:8080/insert_user/execute \
-H "Content-Type: application/json" \
-d '{"name": "David Brown", "email": "david@example.com"}'Verify the insert:
sqlite3 demo/sqlite/demo.db "SELECT * FROM users"Update an existing user's email address:
# Execute UPDATE with parameters
curl -X POST http://localhost:8080/update_user_email/execute \
-H "Content-Type: application/json" \
-d '{"name": "Alice Smith", "new_email": "alice.smith@newdomain.com"}'Response:
{
"data": [{"count": 1}],
"execution_time_ms": 12,
"rows": 1,
"success": true
}The count field reports the number of rows affected. A value of 0 means no row matched the WHERE clause.
Verify the update:
sqlite3 demo/sqlite/demo.db "SELECT * FROM users WHERE name = 'Alice Smith'"Delete a user by name:
# Execute DELETE with parameters
curl -X POST http://localhost:8080/delete_user/execute \
-H "Content-Type: application/json" \
-d '{"name": "David Brown"}'Response:
{
"data": [{"count": 1}],
"execution_time_ms": 8,
"rows": 1,
"success": true
}Verify the delete:
sqlite3 demo/sqlite/demo.db "SELECT * FROM users"Note: Omitting the
WHEREclause deletes all rows in the table. Always double-check your filter parameters before executing a DELETE pipeline against production data.
This example demonstrates joining data from multiple sources (CSV file + SQLite table) and writing the aggregated results back to SQLite.
CSV File (orders.csv) SQLite (users table)
6 rows of order data + 3 rows of user data
| |
+-------------+--------------+
|
DataFusion
JOIN + Aggregate
|
v
SQLite (user_order_stats)
Aggregated statistics per user
# Execute for a specific user by name
curl -X POST http://localhost:8080/federated_join_and_insert/execute \
-H "Content-Type: application/json" \
-d '{"name": "Alice Smith"}'Response:
{
"data": [{"count": 1}],
"execution_time_ms": 42,
"rows": 1,
"success": true
}sqlite3 demo/sqlite/demo.db "SELECT * FROM user_order_stats"Output (after executing for "Alice Smith"):
1|1|Alice Smith|alice@example.com|3|1039.97|2024-01-19
You can execute for other users as well:
# Execute for Bob
curl -X POST http://localhost:8080/federated_join_and_insert/execute \
-H "Content-Type: application/json" \
-d '{"name": "Bob Johnson"}'
# Execute for Carol
curl -X POST http://localhost:8080/federated_join_and_insert/execute \
-H "Content-Type: application/json" \
-d '{"name": "Carol Williams"}'Error: Failed to create SQLite connection pool
Solution: Verify the database file exists and the path is correct:
ls -la demo/sqlite/demo.dbError: Failed to create table provider
Solution: Verify the table exists in the database:
sqlite3 demo/sqlite/demo.db ".tables"
sqlite3 demo/sqlite/demo.db ".schema users"Error: database is locked
Solution: SQLite only allows one writer at a time. Check if another process has the database open:
# Check for processes using the database file
lsof demo/sqlite/demo.dbYou can also increase the busy timeout via the busy_timeout_ms option in the context file:
options:
table: "users"
busy_timeout_ms: "10000" # Wait up to 10 seconds for locks| Option | Required | Default | Description |
|---|---|---|---|
table |
Yes | — | SQLite table name to register |
busy_timeout_ms |
No | 5000 |
Time in milliseconds to wait for database locks |