2025-01-14 22:33:01 +01:00
2025-01-14 15:15:26 +01:00
2025-01-14 22:32:31 +01:00
2025-01-14 22:31:55 +01:00
.
2025-01-14 22:33:01 +01:00
.
2025-01-14 22:32:42 +01:00
2024-11-12 21:17:33 +01:00
2024-10-14 14:35:14 +02:00
2025-01-14 15:15:26 +01:00
2025-01-14 15:15:26 +01:00
2025-01-12 17:16:16 +01:00

alt text

Introduction

ZipponDB is a relational database written entirely in Zig from scratch with 0 dependencies.

ZipponDB's goal is to be ACID, light, simple, and high-performance. It aims at small to medium applications that don't need fancy features but a simple and reliable database.

Why Zippon ?

  • Relational database
  • Simple and minimal query language
  • Small, light, fast, and implementable everywhere

For more informations visit the docs: https://mrbounty.github.io/ZipponDB/

Note: ZipponDB is still in Alpha v0.2, see roadmap.

Declare a schema

In ZipponDB, you use structures, or structs for short, and not tables to organize how your data is stored and manipulated. A struct has a name like User and members like name and age.

Create a file that contains a schema that describes all structs. Compared to SQL, you can see it as a file where you declare all table names, column names, data types, and relationships. All structs have an id of the type UUID by default.

Here an example of a file:

User (
    name: str,
    email: str,
    best_friend: User,
)

Note that the best friend is a link to another User. You can find more examples here.

ZipponQL

ZipponDB uses its own query language, ZipponQL or ZiQL for short. Here are the key points to remember:

  • 4 actions available: GRAB, ADD, UPDATE, DELETE
  • All queries start with an action followed by a struct name
  • {} are filters
  • [] specify how much and what data
  • () contain new or updated data (not already in the file)

GRAB

The main action is GRAB, this will parse files and return data.

GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}

Can use [] before the filter to tell what to return.

GRAB User [id, email] {name = 'Bob'}

Relationship use filter within filter.

GRAB User {best_friend IN {name = 'Bob'}}

GRAB queries return a list of JSON objects with the data inside, e.g:

[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]

ADD

The ADD action adds one entity to the database. The syntax is similar to GRAB, but uses (). This signifies that the data is not yet in the database.

ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])

DELETE

Similar to GRAB but deletes all entities found using the filter and returns a list of deleted UUIDs.

DELETE User {name = 'Bob'}

UPDATE

A mix of GRAB and ADD. It takes a filter first, then the new data. Here, we update the first 5 User entities named 'bob' to capitalize the name and become 'Bob':

UPDATE User [5] {name='bob'} TO (name = 'Bob')

Vs SQL

SELECT * FROM User
GRAB User
SELECT *
FROM your_table_name
WHERE name = 'Bob'
AND (age > 30 OR age < 10);
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
SELECT u1.name AS user_name, GROUP_CONCAT(u2.name || ' (' || u2.age || ')') AS friends_list
FROM User u1
LEFT JOIN User u2 ON ',' || u1.friends || ',' LIKE '%,' || u2.id || ',%'
WHERE u1.age > 30
GROUP BY u1.name;
GRAB User [name, friends [name, age]] {age > 30}
SELECT u1.name AS user_name, GROUP_CONCAT(u2.name || ' (' || u2.age || ')') AS friends_list
FROM User u1
LEFT JOIN User u2 ON ',' || u1.friends || ',' LIKE '%,' || u2.id || ',%'
WHERE u2.age > 30
GROUP BY u1.name;
GRAB User [name, friends [name, age] {age > 30}]

You can also link query. Each query returns a list of UUID of a specific struct. You can use it in the next query. Here an example where I create a new Comment that I then append to the list of comment of one specific User.

ADD Comment (content='Hello world', at=NOW, like_by=[]) => added_comment => UPDATE User {id = '000'} TO (comments APPEND added_comment)

The name between => is the variable name of the list of UUID used for the next queries, you can have multiple one if the link has more than 2 queries. You can also just use one => but the list of UUID is discarded in that case.

This can be use with GRAB too. So you can create variable before making the query. Here an example:

GRAB User {name = 'Bob'} => bobs =>
GRAB User {age > 18} => adults =>
GRAB User {IN adults AND !IN bobs}

Which is the same as:

GRAB User {name != 'Bob' AND age > 18}
Description
No description provided
Readme 9.3 MiB
Languages
Zig 100%