SawitDB: The First Agricultural-Based Database with Anti-Corruption Protocols. Built for Data Sovereignty to oppose expensive, unreliable state infrastructure.
SawitDB: The First Agricultural-Based Database with Anti-Corruption Protocols. Built for Data Sovereignty to oppose expensive, unreliable state infrastructure.
SawitDB is a unique database solution stored in .sawit binary files.
The system features a custom Hybrid Paged Architecture similar to SQLite but supercharged with Object Caching, using fixed-size 4KB pages to ensure efficient memory usage and near-instant access. What differentiates SawitDB is its unique Agricultural Query Language (AQL), which replaces standard SQL keywords with Indonesian farming terminology.
Now available on NPM! Connect via TCP using sawitdb:// protocol.
** Emergency: Aceh Flood Relief** Please support our brothers and sisters in Aceh. Organized by Human Initiative Aceh
.sawit file.fsync protocols. Data cannot be "corrupted" or "disappear" mysteriously like social aid funds (Bansos). No "Sunat Massal" here.JOIN (Left/Right/Full/Cross), JAVING, DISTINCT, and more.npm install @wowoengine/sawitdb.MULAI AKAD, SAHKAN, BATALKAN.PASANG TEROPONG and BUANG TEROPONG.SIMPAN SOP and JALANKAN SOP.CPO adapter and custom event hooks (OnTableCreated, OnTableInserted, etc).BLUSUKAN KE ... CARI.BERI IZIN and CABUT IZIN.SawitDB dibangun dengan semangat "Kemandirian Data". Kami percaya database yang handal tidak butuh Infrastruktur Langit yang harganya triliunan tapi sering down. Berbeda dengan proyek negara yang mahal di budget tapi murah di kualitas, SawitDB menggunakan arsitektur Single File (.sawit) yang hemat biaya. Backup cukup copy-paste, tidak perlu sewa vendor konsultan asing. Fitur fsync kami menjamin data tertulis di disk, karena bagi kami, integritas data adalah harga mati, bukan sekadar bahan konferensi pers untuk minta maaf.
SawitDB is built with the spirit of "Data Sovereignty". We believe a reliable database doesn't need "Sky Infrastructure" that costs trillions yet goes down often. Unlike state projects that are expensive in budget but cheap in quality, SawitDB uses a cost-effective Single File (.sawit) architecture. Backup is just copy-paste, no need to hire expensive foreign consultants. Our fsync feature guarantees data is written to disk, because for us, data integrity is non-negotiable, not just material for a press conference to apologize.
src/WowoEngine.js: Core Database Engine Entry Point.src/SawitServer.js: Server Class.src/SawitClient.js: Client Class.src/modules/: Core modules (QueryParser, BTreeIndex, WAL, Pager).src/services/: Logic services (TableManager, IndexManager, QueryExecutor).src/services/executors/: Specific query executors (Select, Insert, Update, Delete, Aggregate).src/services/logic/: Complex logic handlers (JoinProcessor, ConditionEvaluator).src/server/: Server components (AuthManager, RequestRouter, DatabaseRegistry).bin/sawit-server.js: Server executable.cli/: Command Line Interface tools (local, remote, test, bench).Install via NPM:
npm install @wowoengine/sawitdbnode bin/sawit-server.js
# Or with Cluster Mode enabled in .envThe server will start on 0.0.0.0:7878 by default.
You can use the built-in CLI tool:
node cli/remote.jsOr use the SawitClient class in your Node.js application.
SawitDB introduces the Generic Syntax alongside the classic Agricultural Query Language (AQL), making it easier for developers familiar with standard SQL to adopt.
| Operation | Agricultural Query Language (AQL) | Generic SQL (Standard) |
|---|---|---|
| Create DB | BUKA WILAYAH sales_db |
CREATE DATABASE sales_db |
| Use DB | MASUK WILAYAH sales_db |
USE sales_db |
| Show DBs | LIHAT WILAYAH |
SHOW DATABASES |
| Drop DB | BAKAR WILAYAH sales_db |
DROP DATABASE sales_db |
| Create Table | LAHAN products |
CREATE TABLE products |
| Insert | TANAM KE products (...) BIBIT (...) |
INSERT INTO products (...) VALUES (...) |
| Select | PANEN * DARI products DIMANA ... |
SELECT * FROM products WHERE ... |
| Update | PUPUK products DENGAN ... |
UPDATE products SET ... |
| Delete | GUSUR DARI products DIMANA ... |
DELETE FROM products WHERE ... |
| Indexing | INDEKS products PADA price |
CREATE INDEX ON products (price) |
| Aggregation | HITUNG SUM(stock) DARI products |
Same Syntax |
| Begin Transaction | MULAI AKAD |
BEGIN TRANSACTION |
| Commit | SAHKAN |
COMMIT |
| Rollback | BATALKAN |
ROLLBACK |
| Create View | PASANG TEROPONG [nama] SEBAGAI [query] |
CREATE VIEW [nama] AS [query] |
| Drop View | BUANG TEROPONG [nama] |
DROP VIEW [nama] |
| Trigger | PASANG KENTONGAN [nama] PADA ... |
CREATE TRIGGER [nama] ON ... |
| Procedure | SIMPAN SOP [nama] SEBAGAI ... |
CREATE PROCEDURE [nama] AS ... |
| Replication | SETEL CABANG SEBAGAI ... |
CONFIGURE REPLICATION AS ... |
| Search (FTS) | BLUSUKAN KE [table] CARI "term" |
SEARCH [table] "term" |
| Grant Permission | BERI IZIN [action] KEPADA [user] DI [table] |
GRANT [action] ON [table] TO [user] |
| Revoke Permission | CABUT IZIN [action] DARI [user] DI [table] |
REVOKE [action] ON [table] FROM [user] |
-- Tani
LAHAN users
-- Generic
CREATE TABLE users-- Tani
LIHAT LAHAN
-- Generic
SHOW TABLES-- Tani
BAKAR LAHAN users
-- Generic
DROP TABLE users-- Tani
TANAM KE users (name, role) BIBIT ('Alice', 'Admin')
-- Generic
INSERT INTO users (name, role) VALUES ('Alice', 'Admin')-- Tani
PANEN name, role DARI users DIMANA role = 'Admin' ORDER BY name ASC LIMIT 10
-- Generic
SELECT name, role FROM users WHERE role = 'Admin' ORDER BY name ASC LIMIT 10Operators: =, !=, >, =, ` 5
#### DISTINCT
```sql
SELECT DISTINCT category FROM products
-- Returns only unique values-- INNER JOIN (default)
SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id
-- LEFT OUTER JOIN
SELECT * FROM employees LEFT JOIN departments ON employees.dept_id = departments.id
-- RIGHT OUTER JOIN
SELECT * FROM employees RIGHT JOIN departments ON employees.dept_id = departments.id
-- CROSS JOIN (Cartesian product)
SELECT * FROM colors CROSS JOIN sizesEXPLAIN SELECT * FROM users WHERE id = 5
-- Returns execution plan: scan type, index usage, join methods-- Tani (AQL)
MULAI AKAD
TANAM KE ...
SAHKAN
BATALKAN
-- Generic
BEGIN TRANSACTION
INSERT INTO ...
COMMIT
ROLLBACKdb.query('MULAI AKAD');
db.query("TANAM KE Users (name) BIBIT ('Alice')");
db.query("TANAM KE Users (name) BIBIT ('Bob')");
db.query('SAHKAN');-- Tani (AQL)
PASANG TEROPONG [name] SEBAGAI [query]
PANEN * DARI [name]
BUANG TEROPONG [name]
-- Generic
CREATE VIEW [name] AS [query]
SELECT * FROM [name]
DROP VIEW [name]// Create View
db.query("PASANG TEROPONG ActiveUsers SEBAGAI PANEN * DARI Users DIMANA status = 'active'");
// Query View
const active = db.query('PANEN * DARI ActiveUsers');-- Tani (AQL)
PASANG KENTONGAN [nama] PADA [event] [table] LAKUKAN [query]
BUANG KENTONGAN [nama]
-- Generic (Mapped)
CREATE TRIGGER [nama] ON [event] [table] DO [query]
DROP TRIGGER [nama]PASANG KENTONGAN LogInsert PADA INSERT users LAKUKAN TANAM KE logs (msg) BIBIT ('New User Inserted')-- Tani (AQL)
SIMPAN SOP [nama] SEBAGAI [query]
JALANKAN SOP [nama]
BUANG SOP [nama]
-- Generic (Mapped)
CREATE PROCEDURE [nama] AS [query]
EXECUTE PROCEDURE [nama]
DROP PROCEDURE [nama]SIMPAN SOP ArchiveUsers SEBAGAI TANAM KE archive SELECT * FROM users WHERE status='deleted'
JALANKAN SOP ArchiveUsers-- Tani (AQL)
SETEL CABANG SEBAGAI [role] [host] [port]
-- Roles:
-- PRIMARY / PUSAT : The master database
-- REPLICA / CABANG : The slave database-- On Master
SETEL CABANG SEBAGAI PRIMARY
-- On Slave
SETEL CABANG SEBAGAI REPLICA 192.168.1.100 7878-- Tani (AQL)
BLUSUKAN KE [table] CARI "[term]"
-- Generic
SEARCH [table] "[term]"
FULLTEXT [table] "[term]"BLUSUKAN KE products CARI "sawit"
-- Returns all rows in 'products' containing "sawit" in any text field.-- Tani (AQL)
BERI IZIN [action] KEPADA [user] DI [table]
CABUT IZIN [action] DARI [user] DI [table]
-- Generic
GRANT [action] ON [table] TO [user]
REVOKE [action] ON [table] FROM [user]read: SELECT, SEARCHwrite: INSERT, UPDATE, DELETEall: All permissionsBERI IZIN read KEPADA 'guest' DI products
REVOKE write ON users FROM 'intern'
…
env
SAWIT_CDC_FILE=./examples/logs/sawit.cpo
SAWIT_CDC_ADAPTER=cpoNote: Kafka support coming soon.
You can use a custom event handler by passing it to the constructor:
const CustomHandler = require('./dbeventHandlerExample');
const db = new SawitDB(dbPath, { dbevent: new CustomHandler() });Least-Busy Load Balancing.No open issues yet, or sync has not completed.