feat: regular expression and array filters, GET procedures; 0.3.0
This commit is contained in:
+1
-1
@@ -9,7 +9,7 @@ A dialect is the package that knows one database: how to read its catalog, how t
|
||||
| `@crudy/restloom-mssql` | SQL Server 2022+ | `JSON_OBJECT`, `STRING_AGG` | `OUTPUT` | no | security policies | scalar and table functions |
|
||||
| `@crudy/restloom-sqlite` | SQLite 3.44+ (better-sqlite3) | `json_object`, `json_group_array` | `RETURNING` | no | no | none |
|
||||
|
||||
Every dialect passes the same conformance suite, so a request answers the same rows on each. Where they differ, the sections below say how.
|
||||
Every dialect passes the same conformance suite, so a request answers the same rows on each. Regular expressions (`match`, `imatch`) need Postgres or MySQL, and array filters (`ov`, `cs`, `cd`) Postgres array columns; elsewhere they answer `unsupported`. Where else the dialects differ, the sections below say how.
|
||||
|
||||
## Postgres
|
||||
|
||||
|
||||
+3
-1
@@ -16,7 +16,7 @@ A message never contains SQL or database text.
|
||||
| `method_not_allowed` | 405 | the resource does not allow this method, or a procedure was not called with POST |
|
||||
| `unknown_column` | 400 | the column does not exist or is hidden |
|
||||
| `unknown_relation` | 400 | the relation does not exist |
|
||||
| `unknown_operator` | 400 | the operator is not one of `eq neq gt gte lt lte in like ilike is` |
|
||||
| `unknown_operator` | 400 | the operator is not one of `eq neq gt gte lt lte in like ilike match imatch is ov cs cd` |
|
||||
| `bad_operator` | 400 | the operator does not apply to the column's type |
|
||||
| `invalid_value` | 400 | the value does not fit the column's type |
|
||||
| `bad_filter` | 400 | a filter is not `operator.value` |
|
||||
@@ -37,6 +37,7 @@ A message never contains SQL or database text.
|
||||
| `bad_limit`, `bad_offset` | 400 | not a whole number |
|
||||
| `limit_exceeded` | 400 | a limit over `limits.maxPage` |
|
||||
| `bad_count` | 400 | `count` is not `exact` or `estimated` |
|
||||
| `unsupported` | 400 | the database cannot do what was asked, e.g. a regular expression on SQLite |
|
||||
|
||||
## Writes and procedures
|
||||
|
||||
@@ -50,6 +51,7 @@ A message never contains SQL or database text.
|
||||
| `out_of_scope` | 403 | a value contradicts the host's scope |
|
||||
| `unknown_argument` | 400 | the procedure's function takes no argument of that name |
|
||||
| `missing_argument` | 400 | an argument without a default is missing |
|
||||
| `bad_argument` | 400 | a GET procedure's argument is given twice |
|
||||
|
||||
## The database
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ A filter is `column=operator.value`. Every filter must hold.
|
||||
| `gt`, `gte`, `lt`, `lte` | greater or less than | text, numbers, dates and times |
|
||||
| `in.(a,b,c)` | one of the list; quote an item holding a comma: `in.("a,b",c)` | any comparable column |
|
||||
| `like`, `ilike` | pattern, `*` for any text; `ilike` ignores case | text |
|
||||
| `match`, `imatch` | regular expression; `imatch` ignores case | text, where the database has them (Postgres, MySQL) |
|
||||
| `ov.{a,b}`, `cs.{a,b}`, `cd.{a,b}` | the array overlaps, contains, or is contained by the list | array columns (Postgres) |
|
||||
| `is.null`, `is.true`, `is.false` | null, or a boolean value | `null` any column, `true` and `false` booleans |
|
||||
|
||||
`not.` before the operator negates it: `status=not.in.(retired,lost)`.
|
||||
|
||||
+3
-1
@@ -160,7 +160,9 @@ POST /incidents
|
||||
|
||||
## Procedures
|
||||
|
||||
A procedure calls a database function at a path you choose. A `{name}` in the path passes that segment as the argument of the same name; the body's keys pass the others. Arguments are checked by name and type, and one with a default may be left out. A procedure is always a POST.
|
||||
A procedure calls a database function at a path you choose. A `{name}` in the path passes that segment as the argument of the same name; the body's keys pass the others. Arguments are checked by name and type, and one with a default may be left out.
|
||||
|
||||
A procedure is a POST unless declared `method: 'GET'`. A GET procedure takes its arguments from the query string (`/search?q=vpn&limit=10`), each once, and runs in a read-only transaction: use it for a function without side effects.
|
||||
|
||||
```http
|
||||
POST /assets/3/retire
|
||||
|
||||
@@ -40,6 +40,8 @@ The core decides everything else from the logical types: which operators a colum
|
||||
| `nested(expr)` | a nested JSON subquery, unchanged |
|
||||
| `like(expr, pattern, insensitive)` | `LIKE` or `ILIKE ... ESCAPE '\'` |
|
||||
| `isBoolean(expr, value)` | `IS TRUE`, `IS FALSE` |
|
||||
| `regex(expr, pattern, insensitive)` | `~`, `~*`; throw `RestError(400, 'unsupported')` without regular expressions |
|
||||
| `arrayCompare(expr, op, array)` | `&&`, `@>`, `<@` |
|
||||
| `orderBy(expr, desc, nulls)` | `ASC`/`DESC NULLS FIRST`/`LAST` |
|
||||
| `page(limit, offset)` | `LIMIT n OFFSET m` |
|
||||
| `first(select)` | `... LIMIT 1` |
|
||||
|
||||
Reference in New Issue
Block a user