surrealpatch/doc/QUERIES.md
Tobie Morgan Hitchcock 151d73b954 Remove MODIFY SQL command and add DIFF to UPDATE
MODIFY SQL statements have now been merged with UPDATE SQL statements, as the functionality was similar, but the code was duplicated.

The DIFF SQL command has been added to the UPDATE query, so that records can be updated with DIFFs.
2016-10-30 00:33:28 +01:00

262 lines
9.7 KiB
Markdown

# Queries
This document describes example SQL queries which can be used to query the database.
### TABLE
```sql
/* Define the table */
DEFINE TABLE person
```
```sql
/* Remove the table */
REMOVE TABLE person
```
### SCOPE
```sql
/* Define the scope */
DEFINE SCOPE account SESSION 1h POLICY {"min": 8, "max": null, "lowercase": 1, "uppercase": 1, "numeric": 1, "special": 1, "expiry": 180}
DEFINE SIGNUP FOR SCOPE account AS CREATE admin SET email=$email, password=$password, account=( CREATE @account:{$accountname} SET name=$accountname )
DEFINE SIGNIN FOR SCOPE account AS SELECT * FROM admin WHERE email=$email AND password=$password
DEFINE SCOPE profile SESSION 24h POLICY {"min": 8, "max": null, "lowercase": 1, "uppercase": 1, "numeric": 1, "special": 1, "expiry": null}
DEFINE SIGNUP FOR SCOPE profile AS CREATE person SET email=$email, password=$password
DEFINE SIGNIN FOR SCOPE profile AS SELECT * FROM person WHERE email=$email AND password=$password
```
```sql
/* Remove the scope */
REMOVE SCOPE account
REMOVE SCOPE profile
```
### RULES
```sql
/* Define the rules */
DEFINE RULES FOR person WHEN select ACCEPT
DEFINE RULES FOR person WHEN delete REJECT
DEFINE RULES FOR person WHEN select, create, update ACCEPT
DEFINE RULES FOR person WHEN select, create, update, delete ACCEPT WHERE $auth.accountid = accountid
DEFINE RULES FOR age ON person WHEN select, create, update, delete ACCEPT WHERE $auth.accountid = accountid AND $auth.type = "admin"
```
```sql
/* Remove the rules */
REMOVE RULES FOR person WHEN SELECT
REMOVE RULES FOR age ON person WHEN SELECT, CREATE, UPDATE, MODIFY, DELETE
```
### FIELD
```sql
/* Example of defining a field */
DEFINE FIELD age ON person TYPE number -- Define a numeric field
DEFINE FIELD age ON person TYPE number MIN 0 MAX 100 -- ... with min and max allowed values
DEFINE FIELD age ON person TYPE number MIN 0 MAX 100 NOTNULL -- ... which can't be set to null
DEFINE FIELD age ON person TYPE number MIN 0 MAX 100 NOTNULL VALIDATE -- ... which will fail if not a number
DEFINE FIELD age ON person TYPE number MIN 0 MAX 100 NOTNULL VALIDATE READONLY -- ... which is not able to be changed once defined
DEFINE FIELD iso ON output TYPE string MATCH /^[A-Z]{3}$/ -- Define a field which matches a regular expresion
DEFINE FIELD name.first ON person TYPE string
DEFINE FIELD name.last ON person TYPE string
/* Example of defining a field with allowed values */
DEFINE FIELD kind ON address TYPE custom ENUM ["home","work"] -- Define a custom field
DEFINE FIELD kind ON address TYPE custom ENUM ["home","work"] DEFAULT "home" -- ... which defaults to 'home' if not defined
/* Example of defining a computed field */
DEFINE FIELD name ON person TYPE string CODE "return [doc.data.firstname, doc.data.lastname].join(' ');" -- Define a computed field
```
```sql
/* Remove the field definition */
REMOVE FIELD name ON person
```
### INDEX
```sql
/* Example of defining a custom index */
DEFINE INDEX sortable ON person COLUMNS name -- Define a simple index
DEFINE INDEX sortable ON person COLUMNS firstname, lastname -- Define a compound index
DEFINE INDEX sortable ON person COLUMNS firstname, lastname, emails.*.value -- Define a multi compound index
DEFINE INDEX sortable ON person COLUMNS uuid UNIQUE -- Define a unique index
```
```sql
/* Remove the index definition */
REMOVE INDEX sortable ON person
```
### VIEW
```sql
/* Example of defining a custom query */
DEFINE VIEW ages AS SELECT count(*), min(age), max(age) FROM person -- Define a simple view
DEFINE VIEW ages AS SELECT count(*), min(age), max(age) FROM person WHERE age > 18 -- ... with a where clause
DEFINE VIEW ages AS SELECT count(*), min(age), max(age) FROM person WHERE age > 18 GROUP BY nationality -- ... with a group by clause
DEFINE VIEW ages AS SELECT count(*), min(age), max(age) FROM person WHERE age > 18 GROUP BY nationality, gender -- ... with multiple group-by clauses
```
```sql
/* Remove the query definition */
REMOVE VIEW ages
```
### LIVE
```sql
/* Example of defining a custom index */
LIVE SELECT * FROM person -- Define a simple index
LIVE SELECT * FROM person WHERE age > 18 -- ... with a conditional clause
```
```sql
/* Remove the index definition */
KILL $ID
```
### CREATE
```sql
/* Example of creating a table */
CREATE person -- Creates a new person
CREATE person SET age=28, name='Tobie' -- ... and sets some fields
CREATE person CONTENT {"firstname":"Tobie", "lastname":"Morgan Hitchcock"} -- ... and sets some fields
```
```sql
/* Example of creating a specific record */
CREATE @person:id -- Creates a the person if they do not exist
CREATE @person:id SET age = 28, name = 'Tobie' -- ... and sets name+age
CREATE @person:id SET age = 28, name = 'Tobie', tags = [] -- ... and sets tags to an empty set
CREATE @person:id SET age = 28, name = 'Tobie', tags = ['old'] -- ... and sets tags to a set with 1 element
```
```sql
/* Example of multiple records in one statement */
CREATE @person:one, @person:two -- Creates both person records if they do not exist
```
```sql
/* Example of using embedded fields */
CREATE @person:id SET name.first = "Tobie", name.last = "Morgan Hitchcock" -- Creates a the person if they do not exist
```
### UPDATE
```sql
/* Example of updating a table */
UPDATE person -- Updates all person records
UPDATE person SET age=VOID -- ... and removes the age field
UPDATE person SET age=VOID WHERE age < 18 -- ... if the condition matches
```
```sql
/* Example of updating a specific record */
UPDATE @person:id -- Ensures the person record exists
UPDATE @person:id CONTENT {} -- ... and erases the record data
UPDATE @person:id SET age = 28, name = 'Tobie' -- ... and sets name+age
UPDATE @person:id SET age = 28, name = 'Tobie', tags = NULL -- ... and sets tags to NULL
UPDATE @person:id SET age = 28, name = 'Tobie', tags = [] -- ... and sets tags to an empty set
UPDATE @person:id SET age = 28, name = 'Tobie', tags = ['old'] -- ... and sets tags to a set with 1 element
UPDATE @person:id SET age = 28, name = 'Tobie', tags += ['new'], tags -= ['old'] -- ... and adds 'new' to tags and removes 'old' from tags
```
```sql
/* Example of multiple records in one statement */
UPDATE @person:one, @person:two -- Ensures both person records exist
```
```sql
/* Example of using embedded fields */
UPDATE @person:id SET emails = [] -- Creates a the person if they do not exist
UPDATE @person:id SET emails += {type: "work", value: "tobie@abcum.co.uk"}
UPDATE @person:id SET emails.0.value = "tobie@abcum.com"
UPDATE @person:id SET emails -= {type: "work", value: "tobie@abcum.com"}
```
### DELETE
```sql
/* Example of deleting a table */
DELETE person -- Deletes all person records
DELETE person WHERE age < 18 -- ... if the condition matches
```
```sql
/* Example of deleting a specific record */
DELETE @person:id -- Deletes the person record
DELETE @person:id WHERE age < 18 -- ... if the condition matches
```
```sql
/* Example of multiple records in one statement */
DELETE @person:one, @person:two -- Deletes both person records
```
### RELATE
```sql
-- Example of defining graph edges between records
RELATE friend FROM @person:one TO @person:two -- Define a graph edge
RELATE friend FROM @person:one TO @person:two UNIQUE -- ... or ensure only one edge of this type exists
```
### SELECT
```sql
SELECT * FROM person -- select all people
/* Examples of working with sets or arrays */
SELECT * FROM person WHERE tags "tag" -- tags contains "tag"
SELECT * FROM person WHERE tags ~ "tag" -- tags contains "tag"
SELECT * FROM person WHERE tags CONTAINS "tag" -- tags contains "tag"
SELECT * FROM person WHERE "tag" tags -- tags contains "tag"
SELECT * FROM person WHERE "tag" IS IN tags -- tags contains "tag"
SELECT * FROM person WHERE tags "tag" -- tags does not contain "tag"
SELECT * FROM person WHERE tags !~ "tag" -- tags does not contain "tag"
SELECT * FROM person WHERE tags CONTAINS NOT "tag" -- tags does not contain "tag"
SELECT * FROM person WHERE "tag" tags -- tags does not contain "tag"
SELECT * FROM person WHERE "tag" IS NOT IN tags -- tags does not contain "tag"
SELECT * FROM person WHERE tags ["tag1", "tag2"] -- tags contains "tag1" and "tag2"
SELECT * FROM person WHERE tags CONTAINSALL ["tag1", "tag2"] -- tags contains "tag1" and "tag2"
SELECT * FROM person WHERE tags ["tag1", "tag2"] -- tags contains "tag1" or "tag2"
SELECT * FROM person WHERE tags CONTAINSSOME ["tag1", "tag2"] -- tags contains "tag1" or "tag2"
SELECT * FROM person WHERE tags ["tag1", "tag2"] -- tags does not contain "tag1" or "tag2"
SELECT * FROM person WHERE tags CONTAINSNONE ["tag1", "tag2"] -- tags does not contain "tag1" or "tag2"
/* Examples of working with objects and arrays of objects */
SELECT * FROM person WHERE emails.*.value = /gmail.com$/ -- all email addresses end with 'gmail.com'
SELECT * FROM person WHERE emails.*.value != /gmail.com$/ -- no email addresses end with 'gmail.com'
SELECT * FROM person WHERE emails.*.value ?= /gmail.com$/ -- any email addresses end with 'gmail.com'
/* Examples of working with relationship paths */
SELECT ->[friend]->person FROM person
SELECT *, <->friend|follow-
SELECT *, <-likes<-person.id
SELECT *, <-friend<-person[age>=18] AS friends
SELECT * FROM person WHERE ->friend->person->click->@email:1231
SELECT * FROM person WHERE age >= @person:tobie.age - 5
SELECT *, ->friend->person[age>=18] AS acquaintances FROM person WHERE acquaintances IN [@person:test]
SELECT *, ->friend->person[age>=18] AS acquaintances FROM person WHERE acquaintances.firstname IN ['Tobie']
/* Examples of working with relationship paths and embedded objects */
SELECT * FROM person WHERE emails.*.value->to->email->to->@email:{tobie@abcum.com} -- Anybody who has sent an email to tobie@abcum.com
SELECT * FROM person WHERE @email:{tobie@abcum.com}->from->email.id IN emails.?.value -- Anybody who has sent an email to tobie@abcum.com
```