Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

2 Commits

Repository files navigation

JaSQL

JaSQL's an SQL — a query language for AbuDB, the Abu Ecosystem's in-process database.

JaSQL is a DSL that sits on top of AbuDB (Python). You write SQL-style statements; the runtime handles parsing, type validation, lazy loading, hash joins, transactions, and structured errors. JaSQL is deliberately not named after the A-languages (AC, AI, AC+) because its syntax is normal — English keywords, standard operators, quoted strings.

SCT score: 9.2(Shariff Complexity Theorem, 2026 — easier to learn than Python at 10.0)


Quick Start

fromabudbimportDatabaseimportjasqldb=Database()
results=jasql.execute_script(db, """ CREATE TABLE users { id: int, name: string, age?: int } INSERT users { id: 1, name: "Alice", age: 30 } INSERT users { id: 2, name: "Bob", age: 25 } TAKE name FROM users IF age > 26""")
forrinresults:
print(r)

Single statement:

print(jasql.execute(db, 'TAKE * FROM users ORDER BY age DESC'))

Data Types

TypeExample valueNotes
int42Integer
float3.14Floating-point
string"hello"Quoted string
booltrue / false
date25.05.26dd.mm.yy
datetime25.05.26 14:30dd.mm.yy hh:mm
deltat01:30:00hh:mm:ss duration
nilNILNull / absent value

DDL — Tables

CREATE TABLE

CREATETABLEname { field: type, field?: type, ... }
  • First field is automatically the primary key
  • ? after the field name marks it as nullable (optional on insert)
CREATETABLEproducts { sku: string, name: string, price: float, stock?: int }

DROP TABLE

DROPTABLE products

ALTER TABLE

ALTERTABLE products ADD discount?: float DEFAULT 0.0ALTERTABLE products DROP stock
ALTERTABLE products RENAME price TO unit_price
ALTERTABLE products RENAME TO inventory

DML — Rows

INSERT

INSERT users { id: 1, name: "Alice", age: 30 }

Required (non-nullable) fields must be present. Types are validated and coerced.

UPDATE

UPDATE users SET age =31 IF id =1UPDATE users SET age +=5 IF name ="Bob"UPDATE users SET score *=1.1 IF active = true

Compound operators: +=, -=, *=, /=

RM (delete)

RM FROM users IF age <18

CROP (keep top N)

CROP 100DESCFROM products BY price -- keep the 100 most expensive
CROP 50ASCFROM logs BY date-- keep the 50 oldest

TAKE (query)

TAKE field, expr AS alias, *FROM table [clauses...]

Clauses (in order)

ClauseExampleNotes
IFIF age > 18 & active = trueFilter (WHERE)
JOINJOIN orders ON users.id = orders.uidSee JOIN section
GROUP BYGROUP BY departmentAggregate grouping
IF (after GROUP BY)IF SIZE(*) > 5Having
ORDER BYORDER BY age DESCASC/DESC or ABC/ZYX
FILTERFILTER name, deptDistinct by fields
TOP nTOP 10First n rows
BOTTOM nBOTTOM 5Last n rows
MIDDLE s eMIDDLE 3 7Rows s through e (1-indexed)

Aggregates

TAKE SIZE(*), SUM(price), MEAN(age), MAX(score), MIN(score) FROM table
TAKE dept, SIZE(*), MEAN(salary) FROM staff GROUP BY dept ORDER BY dept ASC

Expressions in TAKE / UPDATE SET

Arithmetic with correct precedence:

TAKE price *1.2AS with_tax FROM products
TAKE first +""+ last AS full_name FROM contacts

UNION

TAKE name FROM staff IF dept ="eng"UNION
TAKE name FROM contractors IF active = true

Conditions

SyntaxMeaning
field = valueEquality
field != valueInequality
field > valueGreater than (also >=, <, <=)
field = NILIs null
field != NILIs not null
field LIKE "pat%"Glob pattern (% = wildcard)
field IN (a, b, c)Value in list
field IN RANGE 10 20Inclusive range
field IN (TAKE ... FROM ...)Subquery
cond & condAND
cond | condOR
!condNOT

Scalar subquery on RHS:

TAKE name FROM students IF grade > (TAKE MEAN(grade) FROM students)

JOIN

TAKE name, total FROM users JOIN orders ONusers.id=orders.uid

JaSQL uses a hash join for equality conditions — O(n+m), not O(n×m). Non-equality conditions fall back to a nested loop.

KEEP ALL (left join)

TAKE name, total FROM users KEEP ALL, orders

Returns all rows from users, with NULLs for unmatched orders rows. Requires a prior CONNECT.

CONNECT (define a relationship)

CONNECT users.id TO orders.user_id

CONNECT registers a foreign-key-style relationship and merges the tables. Required before KEEP ALL.


Import and Export

IMPORT

IMPORT data/people.datac-- datac format (lazy, multi-table)
IMPORT exports/report.csv TO sales -- CSV (lazy)
IMPORT data/sheet.xlsx TO budget -- Excel (lazy, requires openpyxl)

All imports are lazy — schema is read eagerly; rows stream from disk only when queried. Filter pushdown means only matching rows enter memory.

IMPORT classic-regex

IMPORT classic-regex

Activates the regex DSL (see Regex section). This is a module load, not a file import.

SAVE / MTSAVE / ALLSAVE

SAVE users TO backup/users.datac
MTSAVE users, orders TO backup/snapshot.datac
ALLSAVE TO backup/full.datac

Transactions

BEGIN
INSERT orders { id: 1, total: 500 }
UPDATE inventory SET qty -=1 IF sku ="ABC"COMMIT
BEGINUPDATE prices SET amount *=1.05 IF category ="food"ROLLBACK-- undo everything since BEGIN
  • ROLLBACK restores all tables, indexes, and connections to their state at BEGIN
  • Nested BEGIN raises Preposterous: TransactionError
  • COMMIT with no active transaction raises Preposterous: TransactionError

Indexes

INDEX users ON id -- build hash index on users.idDROPINDEX users ON id -- remove it

Indexes are used automatically for IF field = value conditions on eager (fully-loaded) tables.


Regex DSL

Activate with IMPORT classic-regex, then use in any IF condition or TAKE/UPDATE SET expression.

Conditions

TAKE email FROM contacts IF email MATCH "[a-z]+@corp\.com"-- full match (anchored)
TAKE email FROM contacts IF email NOT MATCH "..."
TAKE name FROM users IF name SEARCH "^A"-- partial (unanchored)
TAKE name FROM users IF name NOT SEARCH "bot"

Expression functions

FunctionReturns
regex.match(field, "pat")bool — full match
regex.test(field, "pat")bool — partial match
regex.search(field, "pat")first match string or ""
regex.replace(field, "pat", "r")replace first occurrence
regex.replace_all(f, "pat", "r")replace all occurrences
regex.count(field, "pat")number of matches
regex.escape(field)escape regex special chars
regex.find_all(field, "pat")comma-joined list of matches
regex.groups(field, "pat")comma-joined capture groups
regex.split(field, "pat")comma-joined split result
TAKE regex.replace(email, "@.+", "@***") AS masked FROM contacts
UPDATE users SET email =regex.replace(email, "\\.com$", ".org") IF id =1

datac Format

JaSQL's native file format. Schema headers appear before each data block.

class int property: id
string sub.id: name
int sub.id: age
set inclusion id.age to nil
users {
id: 1, name: "Alice", age: 30
id: 2, name: "Bob", age: 25
id: 3, name: "Carol" ; age is nil — omitted
}
  • ; begins a comment
  • Multi-table files are supported — each table is a separate named block
  • nil fields are omitted (absent = null)

Errors

All errors use the Preposterous: format with caret pointing to the offending token:

Preposterous: TableNotFound found ln:3 Char:12
TAKE * FROM ghost
^
Error kindCause
TableNotFoundTable name doesn't exist
TableExistsCREATE TABLE on an existing name
MissingFieldsINSERT missing a required (non-nullable) field
TypeErrorValue doesn't match schema type
SyntaxErrorUnrecognised clause or malformed statement
AlterErrorALTER TABLE on missing/protected field
TransactionErrorNested BEGIN or COMMIT outside transaction
IOErrorFile write failure in SAVE
NoTablesALLSAVE with no tables defined

SCT Rating

Rated using the Shariff Complexity Theorem (SCT, Abu Shariff, 2026):

DimensionValueNotes
Coordinate (x, y)(8, 85)Very far from machine semantics; near English
Esotericosity E8min(8, 85) — low, DSL reads like English
Work Distribution12Runtime handles joins, validation, lazy load; programmer learns relational model
Barrier tax+0Runs on any Python install, free
SCT9.20.7(8) + 0.3(12) = 5.6 + 3.6

For reference: Python = 10.0, ASM = 30, Lambda Calculus = 35. JaSQL scores below Python because it is a DSL with a single domain — the runtime absorbs far more complexity than a general-purpose language runtime can.


File Overview

FilePurpose
abudb.pyIn-memory database engine (Table, Database)
jasql.pyJaSQL parser, evaluator, dispatcher
datac_parser.pydatac file format parser (eager + streaming)
repl.pyInteractive REPL
test_jasql.pypytest suite (59 tests)
*.datacdatac data files
*.jasqlJaSQL script files

Part of the Abu Ecosystem — AC · AI · AC+ · AbuDB · JaSQL
Abu Shariff · 2026 · abu.shariffaiml@gmail.com

About

"A readable query language with hash joins, transactions, regex DSL, and a duration type SQL got wrong

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages