Skip to content

Commit

Permalink
Docs: Add IF (NOT) EXISTS clause to define statements section and `…
Browse files Browse the repository at this point in the history
…IF EXISTS` to remove statement (#396)
  • Loading branch information
Ekwuno authored Mar 8, 2024
1 parent 90ad577 commit 0603b28
Show file tree
Hide file tree
Showing 14 changed files with 224 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ In the context of a database, an analyzer plays a crucial role in text processin
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE ANALYZER @name [ TOKENIZERS @tokenizers ] [ FILTERS @filters ]
DEFINE ANALYZER [IF NOT EXISTS] @name [ TOKENIZERS @tokenizers ] [ FILTERS @filters ]
```


## Tokenizers
Tokenizers are responsible for breaking down a given text into individual tokens based on a set of instructions. There are a couple of tokenizers that can be used while defining an analyzer as seen below:

Expand Down Expand Up @@ -126,6 +127,15 @@ For example, if you had the text **"Hello World"**, the uppercase filter would c
DEFINE ANALYZER example_uppercase TOKENIZERS class FILTERS uppercase;
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to create an analyzer only if it does not already exist. If the analyzer already exists, the `DEFINE ANALYZER` statement will return an error.

```surql
-- Create a ANALYZER if it does not already exist
DEFINE ANALYZER IF NOT EXISTS example TOKENIZERS blank;
```

## More examples

Examples on application of analyzers to indexes can be found in the documenation on [`DEFINE INDEX`](/docs/surrealdb/nightly/surrealql/statements/define/indexes) statement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,13 @@ Below shows how you can create a database using the DEFINE DATABASE statement.
USE NS abcum;
-- Define database
DEFINE DATABASE app_vitalsense;
```
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a database only if it does not already exist. If the database already exists, the `DEFINE DATABASE` statement will return an error.

```surql
-- Create a DATABASE if it does not already exist
DEFINE DATABASE IF NOT EXISTS app_vitalsense;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Events can be triggered after any change or modification to the data in a record
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE EVENT @name ON [ TABLE ] @table [ WHEN @expression ] THEN @expression
DEFINE EVENT [ IF NOT EXISTS ] @name ON [ TABLE ] @table [ WHEN @expression ] THEN @expression
```

## Example usage
Expand Down Expand Up @@ -72,4 +72,13 @@ DEFINE EVENT user_deleted ON TABLE user WHEN $event = "DELETE" THEN (
DEFINE EVENT user_event ON TABLE user WHEN $event = "CREATE" OR $event = "UPDATE" OR $event = "DELETE" THEN (
CREATE log SET table = "user", event = $event, created_at = time::now()
);
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define an event only if it does not already exist. If the event already exists, the `DEFINE EVENT` statement will return an error.

```surql
-- Create a EVENT if it does not already exist
DEFINE EVENT IF NOT EXISTS example ON example THEN {};
```
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ The `DEFINE FIELD` statement allows you to instantiate a named field on a table,

## Requirements
- You must be authenticated as a root or namespace user before you can use the `DEFINE FIELD` statement.
- [You must select your namespace and database](/docs/surrealdb/surrealql/statements/use) before you can use the `DEFINE FIELD` statement.
- [You must select your namespace and database](/docs/surrealdb/nightly/surrealql/statements/use) before you can use the `DEFINE FIELD` statement.

## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE FIELD @name ON [ TABLE ] @table
DEFINE FIELD [ IF NOT EXISTS ] @name ON [ TABLE ] @table
[ [ FLEXIBLE ] TYPE @type ]
[ DEFAULT @expression ]
[ READONLY ]
Expand All @@ -39,7 +39,7 @@ DEFINE FIELD email ON TABLE user;
```
## Defining data types

The `DEFINE FIELD` statement allows you to set the data type of a field. For a full list of supported data types, see [Data types](/docs/surrealdb/surrealql/datamodel/overview).
The `DEFINE FIELD` statement allows you to set the data type of a field. For a full list of supported data types, see [Data types](/docs/surrealdb/nightly/surrealql/datamodel/overview).

### Simple data types
```surql
Expand All @@ -65,6 +65,9 @@ DEFINE FIELD metadata ON TABLE user FLEXIBLE TYPE object;
```

### Array type

You can also set a field to have the array data type. The array data type can be used to store a list of values. You can also set the data type of the array's contents.

```surql
-- Set a field to have the array data type
DEFINE FIELD roles ON TABLE user TYPE array<string>;
Expand All @@ -80,21 +83,32 @@ DEFINE FIELD posts.* ON TABLE user TYPE record<string>;
```
### Making a field optional

You can make a field optional by wrapping the inner type in an `option`, which allows you to store `NONE` values in the field.

```surql
-- A user may enter a biography, but it is not required.
-- By using the option type you also allow for NONE values.
DEFINE FIELD biography ON TABLE user TYPE option<string>;
```

The example below shows how to define a field `user` on a `POST` table. The field is of type [record](/docs/surrealdb/nightly/surrealql/datamodel/overview). This means that the field can store a `record<user>` or `NONE`.

```surql
DEFINE FIELD user ON TABLE POST TYPE option<record<user>>;
```

### Setting a default value

You can set a default value for a field using the `DEFAULT` clause. The default value will be used if no value is provided for the field.

```surql
-- A user is not locked by default.
DEFINE FIELD locked ON TABLE user TYPE bool
-- Set a default value if empty
DEFAULT false;
```

#### `DEFAULT` inherited from `VALUE`
### `DEFAULT` inherited from `VALUE`

If the `VALUE` clause contains a static query, meaning not depending on any variables, and in case no `DEFAULT` clause is specified, then the `VALUE` clause will be used as the `DEFAULT` clause aswell.

Expand All @@ -104,6 +118,9 @@ DEFINE FIELD updated ON resource VALUE time::now();

### Alter a passed value

You can alter a passed value using the `VALUE` clause. This is useful for altering the value of a field before it is stored in the database.
In the example below, the `VALUE` clause is used to ensure that the email address is always stored in lowercase characters by using the [`string::lowercase`](/docs/surrealdb/nightly/surrealql/functions/string#stringlowercase) function.

```surql
-- Ensure that an email address is always stored in lowercase characters
DEFINE FIELD email ON TABLE user TYPE string
Expand All @@ -112,7 +129,7 @@ DEFINE FIELD email ON TABLE user TYPE string

## Asserting rules on fields

You can take your field definitions even further by using asserts. Assert is a powerful feature that can be used to ensure that your data remains consistent.
You can take your field definitions even further by using asserts. Assert can be used to ensure that your data remains consistent. For example you can use asserts to ensure that a field is always a valid email address, or that a number is always positive.

### Email is required

Expand All @@ -125,12 +142,39 @@ DEFINE FIELD email ON TABLE user TYPE string

### Making a field `READONLY`

The `READONLY` clause can be used to prevent any updates to a field. This is useful for fields that are automatically updated by the system. To make a field `READONLY`, add the `READONLY` clause to the `DEFINE FIELD` statement. As seen in the example below, the `created` field is set to `READONLY`.

```surql
DEFINE FIELD created ON resource VALUE time::now() READONLY;
```

### Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to create a field only if it does not already exist. If the field already exists, the `DEFINE FIELD` statement will not create a new field but return an error.

```surql
-- Create a field if it does not already exist
DEFINE FIELD IF NOT EXISTS email ON TABLE user TYPE string;
```


### Setting permissions on fields

You can set permissions on fields to control who can perform operations on them using the `PERMISSIONS` clause. The `PERMISSIONS` clause can be used to set permissions for `SELECT`, `CREATE`, `UPDATE`, and `DELETE` operations.

```surql
-- Set permissions for the email field
DEFINE FIELD email ON TABLE user
PERMISSIONS
FOR select WHERE published=true OR user=$auth.id
FOR update WHERE user=$auth.id
FOR delete WHERE user=$auth.id OR $auth.role="admin";
```

The `PERMISSIONS` clause can also be used to set permissions for all operations using the `FULL` keyword.

## Array with allowed values
By using an Access Control List as an example we can show how we can restrict what values can be stored in an array.
By using an Access Control List as an example we can show how we can restrict what values can be stored in an array. In this example we are using an array to store the permissions for a user on a resource. The permissions are restricted to a specific set of values.

```surql
-- An ACL can be applied to any kind of resource (record)
Expand Down Expand Up @@ -177,6 +221,8 @@ CREATE acl SET
```
## Using RegEX to validate a string

You can use the `ASSERT` clause to apply a regular expression to a field to ensure that it matches a specific pattern. In the example below, the `ASSERT` clause is used to ensure that the `countrycode` field is always a valid ISO-3166 country code.

```surql
-- Specify a field on the user table
DEFINE FIELD countrycode ON user TYPE string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `DEFINE FUNCTION` statement allows you to define custom functions that can b
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE FUNCTION fn::@name(
DEFINE FUNCTION [ IF NOT EXISTS ] fn::@name(
[ @argument: @type ... ]
) {
[ @query ... ]
Expand Down Expand Up @@ -71,4 +71,13 @@ RETURN fn::last_option(1);
required_present: true,
optional_present: false,
};
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a function only if it does not already exist. If the function already exists, the `DEFINE FUNCTION` statement will return an error.

```surql
-- Create a FUNCTION if it does not already exist
DEFINE FUNCTION IF NOT EXISTS fn::example() {};
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Just like in other databases, SurrealDB uses indexes to help optimize query perf
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE INDEX @name ON [ TABLE ] @table [ FIELDS | COLUMNS ] @fields
DEFINE INDEX [ IF NOT EXISTS ] @name ON [ TABLE ] @table [ FIELDS | COLUMNS ] @fields
[ UNIQUE | SEARCH ANALYZER @analyzer [ BM25 [(@k1, @b)] ] [ HIGHLIGHTS ] ]
```
## Index Types
Expand Down Expand Up @@ -155,6 +155,17 @@ It also reveals details about which `operation` was used by the query planner an
}
]
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a index only if it does not already exist. If the index already exists, the `DEFINE INDEX` statement will return an error.

```surql
-- Create a INDEX if it does not already exist
DEFINE INDEX IF NOT EXISTS example ON example FIELDS example;
```

## Performance Implications

When defining indexes, it's essential to consider the fields most frequently queried or used to optimize performance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Let's say that you're using SurrealDB to create a multi-tenant SaaS application.
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE NAMESPACE @name
DEFINE NAMESPACE [IF NOT EXISTS] @name
```

## Example usage
Expand All @@ -25,4 +25,13 @@ Below shows how you can create a namespace using the `DEFINE NAMESPACE` statemen
```surql
-- Namespace for Abcum Ltd.
DEFINE NAMESPACE abcum;
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a namespace only if it does not already exist. If the namespace already exists, the `DEFINE NAMESPACE` statement will return an error.

```surql
-- Create a NAMESPACE if it does not already exist
DEFINE NAMESPACE IF NOT EXISTS example;
```
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ The DEFINE statement can be used to specify authentication access and behaviour,

```surql title="SurrealQL Syntax"
DEFINE [
NAMESPACE @name
| DATABASE @name
| USER @name ON [ ROOT | NAMESPACE | DATABASE ] [ PASSWORD @pass | PASSHASH @hash ] ROLES @roles
| TOKEN @name ON [ NAMESPACE | DATABASE | SCOPE @scope ] TYPE @type VALUE @value
| SCOPE @name
NAMESPACE [ IF NOT EXISTS ] @name
| DATABASE [ IF NOT EXISTS ] @name
| USER [ IF NOT EXISTS ] @name ON [ ROOT | NAMESPACE | DATABASE ] [ PASSWORD @pass | PASSHASH @hash ] ROLES @roles
| TOKEN [ IF NOT EXISTS ] @name ON [ NAMESPACE | DATABASE | SCOPE @scope ] TYPE @type VALUE @value
| SCOPE [ IF NOT EXISTS ] @name
[ SESSION @duration ]
[ SIGNUP @expression ]
[ SIGNIN @expression ]
| TABLE @name
| TABLE [ IF NOT EXISTS ] @name
[ DROP ]
[ SCHEMAFULL | SCHEMALESS ]
[ AS SELECT @projections
Expand All @@ -32,8 +32,8 @@ DEFINE [
| FOR update @expression
| FOR delete @expression
] ]
| EVENT @name ON [ TABLE ] @table WHEN @expression THEN @expression
| FIELD @name ON [ TABLE ] @table
| EVENT [ IF NOT EXISTS ] @name ON [ TABLE ] @table WHEN @expression THEN @expression
| FIELD [ IF NOT EXISTS ] @name ON [ TABLE ] @table
[ [ FLEXIBLE ] TYPE @type ]
[ VALUE @expression ]
[ ASSERT @expression ]
Expand All @@ -43,10 +43,12 @@ DEFINE [
| FOR update @expression
| FOR delete @expression
] ]
| ANALYZER @name
| PARAM [ IF NOT EXISTS ] $@name VALUE @value
| FUNCTION [ IF NOT EXISTS ] fn::@name ( [ ( @argument:@type ... ) ] ) { [@query] [RETURNS @returned] }
| ANALYZER [ IF NOT EXISTS ] @name
[ TOKENIZERS @tokenizers ]
[ FILTERS @filters ]
| INDEX @name ON [ TABLE ] @table [ FIELDS | COLUMNS ] @fields
| INDEX [ IF NOT EXISTS ] @name ON [ TABLE ] @table [ FIELDS | COLUMNS ] @fields
[ UNIQUE | SEARCH ANALYZER @analyzer [ BM25 [(@k1, @b)] ] [ HIGHLIGHTS ] ]
]
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `DEFINE PARAM` statement allows you to define global (database-wide) paramet
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE PARAM $@name VALUE @value;
DEFINE PARAM [IF NOT EXISTS] $@name VALUE @value;
```

## Example usage
Expand All @@ -28,4 +28,13 @@ Then, simply use the global parameter like you would with any variable.

```surql
RETURN http::get($endpointBase + "/products");
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a param only if it does not already exist. If the param already exists, the `DEFINE PARAM` statement will return an error.

```surql
-- Create a PARAM if it does not already exist
DEFINE PARAM IF NOT EXISTS $example VALUE 123;
```
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Setting scope access allows SurrealDB to operate as a web database. With scopes
## Statement syntax

```surql title="SurrealQL Syntax"
DEFINE SCOPE @name SESSION @duration SIGNUP @expression SIGNIN @expression
DEFINE SCOPE [ IF NOT EXISTS ] @name SESSION @duration SIGNUP @expression SIGNIN @expression
```

## Example usage
Expand All @@ -27,4 +27,13 @@ DEFINE SCOPE account SESSION 24h
SIGNUP ( CREATE user SET email = $email, pass = crypto::argon2::generate($pass) )
SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(pass, $pass) )
;
```

## Using `IF NOT EXISTS` clause

The `IF NOT EXISTS` clause can be used to define a scope only if it does not already exist. If the scope already exists, the `DEFINE SCOPE` statement will return an error.

```surql
-- Create a SCOPE if it does not already exist
DEFINE SCOPE IF NOT EXISTS example;
```
Loading

0 comments on commit 0603b28

Please sign in to comment.