Good docs update, stillo need some work. Need to take a step back and think
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# ADD
|
||||
|
||||
The `ADD` action adds entities to the database. The syntax is similar to `GRAB`, but uses `()`. This signifies that the data is not yet in the database.
|
||||
|
||||
Here's an example:
|
||||
```lua
|
||||
ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])
|
||||
```
|
||||
|
||||
You need to specify all members when adding an entity (default values comming).
|
||||
|
||||
|
||||
The `ADD` query will return a list of added IDs, e.g.:
|
||||
```
|
||||
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
|
||||
```
|
||||
|
||||
And you can also add them in batch
|
||||
```
|
||||
ADD User (name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82]) (name = 'Bob2', age = 33, email = 'bob2@email.com', scores = [])
|
||||
```
|
||||
|
||||
You don't need to specify member's name for the second entity as long as the order is respected:
|
||||
```
|
||||
ADD User
|
||||
(name = 'Bob', age = 30, email = 'bob@email.com', scores = [1 100 44 82])
|
||||
('Bob2', 33, 'bob2@email.com', [])
|
||||
```
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# DELETE
|
||||
|
||||
Similar to `GRAB` but deletes all entities found using the filter and returns a list of deleted UUIDs.
|
||||
```js
|
||||
DELETE User {name = 'Bob'}
|
||||
```
|
||||
|
||||
The `DELETE` query will return a list of deleted IDs, e.g.:
|
||||
```
|
||||
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
|
||||
```
|
||||
@@ -0,0 +1,120 @@
|
||||
# GRAB
|
||||
|
||||
The main action is `GRAB`, this will parse files and return data.
|
||||
|
||||
#### Basic
|
||||
|
||||
Here's how to return all `User` entities without any filtering:
|
||||
```
|
||||
GRAB User
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To get all `User` entities above 30 years old:
|
||||
```
|
||||
GRAB User {age > 30}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To return only the `name` member of `User` entities:
|
||||
```
|
||||
GRAB User [name] {age > 30}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
To return the 10 first `User` entities:
|
||||
```
|
||||
GRAB User [10] {age > 30}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
You can combine these options:
|
||||
```
|
||||
GRAB User [10; name] {age > 30}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Use multiple conditions:
|
||||
```
|
||||
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
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: [], }, ]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Ordering - Not yet implemented
|
||||
|
||||
To order the results by `name`:
|
||||
```js
|
||||
GRAB User [10; name] {age > 10} |ASC name|
|
||||
```
|
||||
|
||||
#### 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']}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### Relationship
|
||||
|
||||
2 main things to remember with relationship:
|
||||
|
||||
* You can use filter inside filter.
|
||||
* You can use the dot `.` to refer to a relationship. (Not yet implemented)
|
||||
|
||||
Get `User` that have a best friend named Adrien:
|
||||
```js
|
||||
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`:
|
||||
```js
|
||||
GRAB User [10; friends [1; name]]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
When using `IN`, it return all `User` that have AT LEAST one friend named Adrien:
|
||||
```js
|
||||
GRAB User { friends IN { name = 'Adrien' } }
|
||||
```
|
||||
---
|
||||
|
||||
To get `User` entities with all friends named Adrien:
|
||||
```js
|
||||
GRAB User { friends ALLIN { name = 'Adrien' } }
|
||||
```
|
||||
---
|
||||
|
||||
You can use `!` to say not in:
|
||||
```js
|
||||
GRAB User { friends !IN { name = 'Adrien' } }
|
||||
```
|
||||
---
|
||||
|
||||
#### 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
|
||||
GRAB User { orders.products.category.name = 'Book' }
|
||||
```
|
||||
|
||||
Same as:
|
||||
```
|
||||
GRAB User {orders IN { products IN { category IN { name = 'Book'} } } }
|
||||
```
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
# ZipponQL
|
||||
|
||||
ZipponDB uses its own query language, ZipponQL or ZiQL for short.
|
||||
The language goal is to be minimal, small and simple.
|
||||
Yet allowing powerful relationship.
|
||||
|
||||
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 files)
|
||||
* `||` for ordering
|
||||
* By default, all members that are not links are returned
|
||||
|
||||
***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:
|
||||
```lua
|
||||
Error: Expected string
|
||||
GRAB User {name = Bob}
|
||||
^^^
|
||||
```
|
||||
|
||||
```
|
||||
Error: Expected ( or member name.
|
||||
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.
|
||||
|
||||
Here I return just the name of all users:
|
||||
```
|
||||
GRAB User [name] {}
|
||||
```
|
||||
|
||||
|
||||
Here the 100 first users:
|
||||
```
|
||||
GRAB User [100] {}
|
||||
```
|
||||
|
||||
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:
|
||||
```
|
||||
GRAB User [name, best_friend] {}
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
For example `{ name = 'Bob' }` will return `true` if the member `name` of the evaluated entity is equal to `Bob`. This is the most important thing in ZipponDB.
|
||||
|
||||
Here an example in a query:
|
||||
|
||||
```
|
||||
GRAB User {name = 'Bob' AND age > 44}
|
||||
```
|
||||
|
||||
### For relationship
|
||||
|
||||
Filter can be use inside filter. This allow simple yet powerfull relationship.
|
||||
|
||||
This query will return all users that have a best friend named 'Bob'.
|
||||
|
||||
```
|
||||
GRAB User {best_friend IN {name = 'Bob'}}
|
||||
```
|
||||
|
||||
You are obviously not limited to one depth. This will return all users that ordered at least one book in 2024:
|
||||
|
||||
```go
|
||||
GRAB User {
|
||||
orders IN {
|
||||
products IN {
|
||||
category IN {
|
||||
name = 'Book'
|
||||
}
|
||||
},
|
||||
date > 2024/01/01
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Same as:
|
||||
```go
|
||||
GRAB User {orders IN { products.category.name = 'Book' AND date > 2024/01/01} } // (1)!
|
||||
```
|
||||
|
||||
1. Dot not yet implemented
|
||||
|
||||
|
||||
## Link query - Not yet implemented
|
||||
|
||||
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=[], by={id='000'})
|
||||
=> 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}
|
||||
```
|
||||
|
||||
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}
|
||||
```
|
||||
@@ -0,0 +1,45 @@
|
||||
# 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 'adrien' to capitalize the name and become 'Adrien':
|
||||
```js
|
||||
UPDATE User [5] {name='adrien'} TO (name = 'Adrien')
|
||||
```
|
||||
|
||||
Note that, compared to `ADD`, you don't need to specify all members between `()`. Only the ones specified will be updated.
|
||||
|
||||
The `UPDATE` query will return a list of updated IDs, e.g.:
|
||||
```
|
||||
["1e170a80-84c9-429a-be25-ab4657894653", "1e170a80-84c9-429a-be25-ab4657894654", ]
|
||||
```
|
||||
|
||||
## Not yet implemented
|
||||
|
||||
You can use operations on values themselves when updating:
|
||||
```js
|
||||
UPDATE User {name = 'Bob'} TO (age += 1)
|
||||
```
|
||||
|
||||
You can also manipulate arrays, like adding or removing values:
|
||||
```js
|
||||
UPDATE User {name='Bob'} TO (scores APPEND 45)
|
||||
UPDATE User {name='Bob'} TO (scores APPEND [45 99])
|
||||
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.
|
||||
- `REMOVEAT`: Deletes the value at a specific index.
|
||||
- `CLEAR`: Removes all values from the array.
|
||||
|
||||
Except for `CLEAR`, which takes no value, each keyword can use one value or an array of values. If you choose an array, it will perform the operation on all values in the array.
|
||||
|
||||
For relationships, you can use filters:
|
||||
```js
|
||||
UPDATE User {name='Bob'} TO (comments APPEND {id = '000'})
|
||||
UPDATE User {name='Bob'} TO (comments REMOVE [1] { at < '2023/12/31'})
|
||||
```
|
||||
|
||||
I may include more options later.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Vs SQL
|
||||
|
||||
A good way to see how ZipponQl work is to compare it to SQL.
|
||||
|
||||
## Select everything
|
||||
|
||||
```
|
||||
SELECT * FROM User
|
||||
```
|
||||
|
||||
```
|
||||
GRAB User
|
||||
or
|
||||
GRAB User {}
|
||||
```
|
||||
|
||||
## Selection on condition
|
||||
|
||||
```
|
||||
SELECT *
|
||||
FROM Users
|
||||
WHERE name = 'Bob'
|
||||
AND (age > 30 OR age < 10);
|
||||
```
|
||||
|
||||
```go
|
||||
GRAB User {name = 'Bob' AND (age > 30 OR age < 10)}
|
||||
```
|
||||
|
||||
## Select something
|
||||
|
||||
```
|
||||
SELECT name, age
|
||||
FROM Users
|
||||
LIMIT 100
|
||||
```
|
||||
|
||||
```go
|
||||
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
|
||||
FROM Users u1
|
||||
LEFT JOIN User u2 ON ',' || u1.friends || ',' LIKE '%,' || u2.id || ',%'
|
||||
WHERE u1.age > 30
|
||||
GROUP BY u1.name;
|
||||
```
|
||||
|
||||
```go
|
||||
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;
|
||||
```
|
||||
|
||||
ZiQL:
|
||||
```go
|
||||
GRAB User [name, order [id, date]] {}
|
||||
```
|
||||
|
||||
#### More complexe one
|
||||
|
||||
SQL:
|
||||
```
|
||||
SELECT
|
||||
U.name AS UserName,
|
||||
O.orderID,
|
||||
O.orderDate,
|
||||
P.productName,
|
||||
C.categoryName,
|
||||
OD.quantity,
|
||||
FROM
|
||||
Users U
|
||||
INNER JOIN Orders O ON U.UserID = O.UserID
|
||||
INNER JOIN OrderDetails OD ON O.OrderID = OD.OrderID
|
||||
INNER JOIN Products P ON OD.ProductID = P.ProductID
|
||||
INNER JOIN Categories C ON P.CategoryID = C.CategoryID
|
||||
WHERE
|
||||
O.orderDate >= '2023-01-01'
|
||||
AND C.categoryName != 'Accessories'
|
||||
ORDER BY
|
||||
O.orderDate DESC;
|
||||
```
|
||||
|
||||
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)!
|
||||
```
|
||||
|
||||
1. Ordering not yet implemented
|
||||
Reference in New Issue
Block a user