diff --git a/README.md b/README.md
index f2e7460..622c3f1 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,18 @@

-# 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
diff --git a/docs/Quickstart.md b/docs/Quickstart.md
index dc920a4..1cc7cf0 100644
--- a/docs/Quickstart.md
+++ b/docs/Quickstart.md
@@ -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:
diff --git a/docs/Schema.md b/docs/Schema.md
index f617777..8c6ff09 100644
--- a/docs/Schema.md
+++ b/docs/Schema.md
@@ -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
diff --git a/docs/index.md b/docs/index.md
index 8ed59d7..276f2e6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -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.*
* Plan for more platforms like arm, 32 bit system.
-### 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.
diff --git a/docs/ziql/add.md b/docs/ziql/add.md
index a1d0afb..8d35d9e 100644
--- a/docs/ziql/add.md
+++ b/docs/ziql/add.md
@@ -27,3 +27,9 @@ ADD User
('Bob2', 33, 'bob2@email.com', [])
```
+## Soon
+
+* Default value
+* Array default is empty
+* Link default is none
+
diff --git a/docs/ziql/grab.md b/docs/ziql/grab.md
index b91d096..0b07ca7 100644
--- a/docs/ziql/grab.md
+++ b/docs/ziql/grab.md
@@ -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'.
diff --git a/docs/ziql/intro.md b/docs/ziql/intro.md
index 07aa116..2ab70b2 100644
--- a/docs/ziql/intro.md
+++ b/docs/ziql/intro.md
@@ -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}
```
+Note that the query are completly isolated, so files will be parse 3 times.
+
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)
+
diff --git a/docs/ziql/update.md b/docs/ziql/update.md
index 44af09e..db00e6f 100644
--- a/docs/ziql/update.md
+++ b/docs/ziql/update.md
@@ -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.
diff --git a/docs/ziql/vssql.md b/docs/ziql/vssql.md
index 9219a48..5667a08 100644
--- a/docs/ziql/vssql.md
+++ b/docs/ziql/vssql.md
@@ -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
+