Update README and doc

This commit is contained in:
Adrien Bouvais 2025-01-16 20:45:58 +01:00
parent 154a146678
commit a16c9b29c1
9 changed files with 180 additions and 49 deletions

View File

@ -1,16 +1,18 @@
![alt text](https://github.com/MrBounty/ZipponDB/blob/main/docs/images/banner.png)
# 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 ?
Key Features:
- Relational database
- Simple and minimal query language
- Small, light, fast, and implementable everywhere
* **Small:** Binary is small, around 2-3Mb.
* **Fast:** Parse millions of entities in milliseconds.
* **Relationship:** Build with focus on easy relationship.
* **Query Language:** Use it's own simple query language.
* **No dependencies:** Depend on nothing, every line of code running is in the codebase.
* **Open-source:** Open-source under MIT licence.
* **Portable:** Easily compiled and deployed across various platforms.
For more informations visit the docs: https://mrbounty.github.io/ZipponDB/
@ -20,18 +22,32 @@ For more informations visit the docs: https://mrbounty.github.io/ZipponDB/
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.
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:
```lua
User (
name: str,
age: int,
email: str,
best_friend: User,
Parent: User,
childrens: []User,
orders: []Order,
)
Order (
at: datetime,
items: []Item,
)
Item (
name: str,
category: str,
)
```
Note that the best friend is a link to another `User`. You can find more examples [here](https://github.com/MrBounty/ZipponDB/tree/main/schema).
Note that parent is a link to another `User` and can be `none`, `[]` mean an array. You can find more examples [here](https://github.com/MrBounty/ZipponDB/tree/main/schema).
# ZipponQL
@ -44,12 +60,12 @@ ZipponDB uses its own query language, ZipponQL or ZiQL for short. Here are the k
## GRAB
The main action is `GRAB`, this will parse files and return data.
The main action is `GRAB`, it parse files and return data.
```js
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
Can use [] before the filter to tell what to return.
Using `[]` before the filter tell what to return.
```js
GRAB User [id, email] {name = 'Bob'}
```
@ -59,7 +75,7 @@ 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:
GRAB queries return a list of JSON objects, e.g:
```
[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]
```
@ -68,7 +84,7 @@ GRAB queries return a list of JSON objects with the data inside, e.g:
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.
```js
ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])
ADD User (name = 'Bob', age = 30)
```
## DELETE

View File

@ -25,7 +25,7 @@ Alternatively, set the `ZIPPONDB_PATH` environment variable.
Define a [schema](/ZipponDB/Schema) and attach it to the database by running:
```bash
schema init path/to/schema.txt
schema use path/to/schema.txt
```
This will create the necessary directories and empty files for data storage. Test the current database schema by running:

View File

@ -13,7 +13,7 @@ User (
)
```
In this example, the `best_friend` member is a reference to another `User` struct, demonstrating how relationships between structs can be established.
In this example, the `best_friend` member is a reference to another `User`.
Here's a more complex example featuring multiple structs:
```lua
@ -48,7 +48,7 @@ In future releases, ZipponDB will support schema updates, allowing you to modify
I will add commands or query to add, delete and update struct in the schema. Maybe the schema will be a Struct itself with a schema like that:
```
```lua
Struct (
name: str,
members: []Member,
@ -60,7 +60,7 @@ Member (
)
```
Like that can just do ZiQL qquery directly on it.
Like that can just do ZiQL query directly on it.
### Planned Migration Features

View File

@ -28,14 +28,14 @@ medium applications that want a quick and simple database.
* **Small:** ZipponDB binary is small, around 2-3Mb.
* **Fast:** ZipponDB can parse millions of entities in milliseconds.
* **Relationship:** ZipponDB is build with focus on easy relationship.
* **Query Language:** ZipponDB use it's own simple query language named ZipponQL.
* **No dependencies:** ZipponDB depend on nothing, every line of code is in the codebase.
* **Query Language:** ZipponDB use it's own simple query language.
* **No dependencies:** ZipponDB depend on nothing, every line of code running is in the codebase.
* **Open-source:** ZipponDB is open-source under MIT licence.
* **Portable:** ZipponDB can be easily compiled and deployed across various platforms.*
<small>* Plan for more platforms like arm, 32 bit system.</small>
### To come
### After
* **Auth:** Be able to auth users, maybe third-party OAuth.
* **HTTP server:** Be able to start a simple HTTP server and send json.

View File

@ -27,3 +27,9 @@ ADD User
('Bob2', 33, 'bob2@email.com', [])
```
## Soon
* Default value
* Array default is empty
* Link default is none

View File

@ -2,30 +2,30 @@
The main action is `GRAB`, this will parse files and return data.
#### Basic
## Basic
Here's how to return all `User` entities without any filtering:
Here's how to return all `User` without any filtering:
```
GRAB User
```
---
To get all `User` entities above 30 years old:
To get all `User` above 30 years old:
```
GRAB User {age > 30}
```
---
To return only the `name` member of `User` entities:
To return only the member `name` of `User`:
```
GRAB User [name] {age > 30}
```
---
To return the 10 first `User` entities:
To return the 10 first `User`:
```
GRAB User [10] {age > 30}
```
@ -53,14 +53,14 @@ GRAB queries return a list of JSON objects with the data inside, e.g:
---
#### Ordering - Not yet implemented
## Ordering - Not yet implemented
To order the results by `name`:
```js
GRAB User [10; name] {age > 10} |ASC name|
```
#### Array
## Array
You can use the `IN` operator to check if something is in an array:
```js
GRAB User { age > 10 AND name IN ['Adrien' 'Bob']}
@ -68,7 +68,7 @@ GRAB User { age > 10 AND name IN ['Adrien' 'Bob']}
---
#### Relationship
## Relationship
2 main things to remember with relationship:
@ -81,7 +81,7 @@ GRAB User { bestfriend IN { name = 'Adrien' } }
```
---
You can specify how much data to return and which members to include, even for links inside entity. In this example, I get 1 friend's name for 10 `User`:
You can specify how much data to return and which members to include, even for links. In this example, I get 1 friend's name for 10 `User`:
```js
GRAB User [10; friends [1; name]]
```
@ -94,7 +94,7 @@ GRAB User { friends IN { name = 'Adrien' } }
```
---
To get `User` entities with all friends named Adrien:
To get `User` with all friends named Adrien:
```js
GRAB User { friends ALLIN { name = 'Adrien' } }
```
@ -106,7 +106,7 @@ GRAB User { friends !IN { name = 'Adrien' } }
```
---
#### Dot - Not yet implemented
## Dot - Not yet implemented
You can use `.` if you just want to do one comparison. Here I get all `User` that ordered at least one book:
```js
@ -118,3 +118,13 @@ Same as:
GRAB User {orders IN { products IN { category IN { name = 'Book'} } } }
```
---
You can also use the dot like that:
```js
GRAB User.orders {name = 'Bob'}
```
The filter is done on User but it return Order.
It return all Order from User named 'Bob'.

View File

@ -16,6 +16,8 @@ Here are the key points to remember:
***Disclaimer: The language may change a bit over time.***
---
## Making errors
When you make an error writing ZiQL, you should see something like this to help you understand where you made a mistake:
@ -31,9 +33,11 @@ GRAB User {name = 'Bob' AND {age > 10}}
^
```
---
## To return
What is between `[]` are what data to return. You can see it as the column name after `SELECT` in SQL.
What is between `[]` are what data to return. You can see it as the column name after `SELECT` in SQL and number after `LIMIT`.
Here I return just the name of all users:
```
@ -51,8 +55,6 @@ Here the name of the 100 first users:
GRAB User [100; name]
```
### For relationship
You can also specify what data to return for each relationship returned. By default, query do not return any relationship.
This will return the name and best friend of all users:
@ -66,6 +68,8 @@ You can also specify what the best friend return:
GRAB User [name, best_friend [name, age]] {}
```
---
## Filters
What is between `{}` are filters, basically as a list of condition. This filter is use when parsing files and evaluate entities. You can see it as `WHERE` in SQL.
@ -78,7 +82,9 @@ Here an example in a query:
GRAB User {name = 'Bob' AND age > 44}
```
### For relationship
---
## Relationship
Filter can be use inside filter. This allow simple yet powerfull relationship.
@ -110,6 +116,8 @@ GRAB User {orders IN { products.category.name = 'Book' AND date > 2024/01/01} }
1. Dot not yet implemented
---
## Link query - Not yet implemented
@ -136,9 +144,68 @@ Which is the same as:
GRAB User {name != 'Bob' AND age > 18}
```
<small>Note that the query are completly isolated, so files will be parse 3 times.</small>
Another example:
```
GRAB Product [1] {category.name = 'Book'} => book =>
GRAB Order {date > 2024/01/01 AND products IN book} => book_orders =>
GRAB User [100] {orders IN book_orders}
```
---
## Actions
### [GRAB](/ZipponDB/ziql/grab)
The main action is `GRAB`, it parse files and return data.
```js
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
Using `[]` before the filter tell what to return.
```js
GRAB User [id, email] {name = 'Bob'}
```
Relationship use filter within filter.
```js
GRAB User {best_friend IN {name = 'Bob'}}
```
GRAB queries return a list of JSON objects, e.g:
```
[{id:"1e170a80-84c9-429a-be25-ab4657894653", name: "Gwendolyn Ray", age: 70, email: "austin92@example.org", scores: [ 77 ], friends: [], }, ]
```
[More info.](/ZipponDB/ziql/grab)
### [ADD](/ZipponDB/ziql/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.
```js
ADD User (name = 'Bob', age = 30)
```
[More info.](/ZipponDB/ziql/add)
### [DELETE](/ZipponDB/ziql/delete)
Similar to `GRAB` but deletes all entities found using the filter and returns a list of deleted UUIDs.
```js
DELETE User {name = 'Bob'}
```
[More info.](/ZipponDB/ziql/delete)
### [UPDATE](/ZipponDB/ziql/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':
```js
UPDATE User [5] {name='bob'} TO (name = 'Bob')
```
[More info.](/ZipponDB/ziql/update)

View File

@ -20,6 +20,8 @@ You can use operations on values themselves when updating:
UPDATE User {name = 'Bob'} TO (age += 1)
```
## Array - Not yet implemented
You can also manipulate arrays, like adding or removing values:
```js
UPDATE User {name='Bob'} TO (scores APPEND 45)
@ -30,7 +32,7 @@ UPDATE User {name='Bob'} TO (scores REMOVEAT [0 1 2])
Currently, there will be four keywords for manipulating lists:
- `APPEND`: Adds a value to the end of the list.
- `REMOVE`: Checks the list, and if the same value is found, deletes it.
- `REMOVE`: Checks the list, and if the value is found, deletes it.
- `REMOVEAT`: Deletes the value at a specific index.
- `CLEAR`: Removes all values from the array.

View File

@ -9,11 +9,11 @@ SELECT * FROM User
```
```
GRAB User
or
GRAB User {}
```
---
## Selection on condition
```
@ -27,6 +27,8 @@ AND (age > 30 OR age < 10);
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
```
---
## Select something
```
@ -39,9 +41,10 @@ LIMIT 100
GRAB User [100; name, age] {}
```
---
## Relationship
### List of other entity
```
SELECT u1.name AS user_name, GROUP_CONCAT(u2.name || ' (' || u2.age || ')') AS friends_list
@ -55,15 +58,13 @@ GROUP BY u1.name;
GRAB User [name, friends [name, age]] {age > 30}
```
### Join
#### Simple one
---
SQL:
```
SELECT Users.name, Orders.orderID, Orders.orderDate
FROM Users
INNER JOIN Orders ON Users.UsersID = Orders.CustomerID;
INNER JOIN Orders ON Users.UserID = Orders.UserID;
```
ZiQL:
@ -71,7 +72,7 @@ ZiQL:
GRAB User [name, order [id, date]] {}
```
#### More complexe one
---
SQL:
```
@ -95,12 +96,41 @@ ORDER BY
O.orderDate DESC;
```
ZiQL
ZiQL:
```go
GRAB User
[ name, orders [id, date, details [quantity]], product [name], category [name] ]
{ orders IN {date >= 2023/01/01} AND category IN {name != 'Accessories'} }
| orders.date DESC | // (1)!
[ name, orders [id, date, details [quantity, products [name, category [name]]]]]
{ orders IN {date >= 2023/01/01 AND details.products.category.name != 'Accessories' } } // (1)!
| orders.date DESC | // (2)!
```
1. Ordering not yet implemented
1. Dot not yet implemented. But you can do it with:
```
details IN { products IN {category IN {name != 'Accessories'}}}
```
2. Ordering not yet implemented
---
SQL:
```
UPDATE orders o
JOIN customers c ON o.customer_id = c.customer_id
SET o.status = 'Priority'
WHERE c.membership_level = 'Premium' AND o.order_date > '2023-01-01';
```
ZiQL:
```go
GRAB User.orders { membership_level = 'Premium' } // (1)!
=> premium_order => // (2)!
UPDATE Order {id IN premium_order AND date > 2023/01/01}
TO (status = 'Priority')
```
1. Not yet implemented. Can't do it now.
Here that mean filter are done on User but it return Order.
It return all order of User with a premium membership.
2. Linked query not implemented