API
Each table is mapped to an entity
named after the table's name. In the following reference, we'll use some placeholders, but let's start with an example:
Example
Given this SQL executed against your database:
CREATE TABLE pages (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
body TEXT NOT NULL
);
[PLURAL_ENTITY_NAME]
ispages
[SINGULAR_ENTITY_NAME]
ispage
[PRIMARY_KEY]
isid
fields
areid
,title
,body
GET and POST parameters
Some APIs need the GET
method, where parameters must be defined in the URL, or POST/PUT
methods, where parameters can be defined in the HTTP
request payload.
Fields
Every API can define a fields
parameter, representing the entity fields you want to get back for each row of the table. If not specified all fields are returned.
The fields
parameter is always sent in the query string, even for POST
, PUT
and DELETE
requests, as a comma-separated value.
GET /[PLURAL_ENTITY_NAME]
Returns all entities matching where
clause
Where Clause
You can define many WHERE
clauses in REST API, each clause includes a field, an operator and a value.
- Field: One of the fields found in the schema.
- Operator follows this table:
Platformatic operator | SQL operator |
---|---|
eq | '=' |
in | 'IN' |
nin | 'NOT IN' |
neq | '<>' |
gt | '>' |
gte | '>=' |
lt | '<' |
lte | '<=' |
- Value: The value you want to compare the field to.
For GET requests all these clauses are specified in the query string using the format where.[FIELD].[OPERATOR]=[VALUE]
Example
To get the title
and the body
of every page
where id < 15
, make an HTTP request like this:
$ curl -X 'GET' \
'http://localhost:3042/pages/?fields=body,title&where.id.lt=15' \
-H 'accept: application/json'
Combining Where Clauses
Where clause operations are by default combined with the AND
operator. To create an OR
condition, use the where.or
query parameter.
Each where.or
query parameter can contain multiple conditions separated by a |
(pipe).
Example
To get the posts
where counter = 10
OR
counter > 30
, make an HTTP request like this:
$ curl -X 'GET' \
'http://localhost:3042/pages/?where.or=(counter.eq=10|counter.gte=30)' \
-H 'accept: application/json'
OrderBy clause
You can define the ordering of the returned rows within your REST API calls with the orderby
clause using the following pattern:
?orderby.[field]=[asc | desc]
- Field: One of the fields found in the schema.
- Value: can be
asc
ordesc
.
Example
To get the pages
ordered alphabetically by their titles
, make an HTTP request like this:
$ curl -X 'GET' \
'http://localhost:3042/pages?orderby.title=asc' \
-H 'accept: application/json'
Total Count
If totalCount
boolean is true
in query, the GET returns the total number of elements in the X-Total-Count
header ignoring limit
and offset
(if specified).
$ curl -v -X 'GET' \
'http://localhost:3042/pages/?limit=2&offset=0&totalCount=true' \
-H 'accept: application/json'
(...)
> HTTP/1.1 200 OK
> x-total-count: 18
(...)
[{"id":1,"title":"Movie1"},{"id":2,"title":"Movie2"}]%
POST [PLURAL_ENTITY_NAME]
Creates a new row in table. Expects fields to be sent in a JSON formatted request body.
Example
$ curl -X 'POST' \
'http://localhost:3042/pages/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"title": "Hello World",
"body": "Welcome to Platformatic!"
}'
{
"id": 1,
"title": "Hello World",
"body": "Welcome to Platformatic"
}
GET [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
Returns a single row, identified by PRIMARY_KEY
.
Example
$ curl -X 'GET' 'http://localhost:3042/pages/1?fields=title,body
{
"title": "Hello World",
"body": "Welcome to Platformatic"
}
POST [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
Updates a row identified by PRIMARY_KEY
.
Example
$ curl -X 'POST' \
'http://localhost:3042/pages/1' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic!"
}'
{
"id": 1,
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic"
}
PUT [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
Same as POST [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
.
PUT [PLURAL_ENTITY_NAME]
Updates all entities matching the where
clause
Example
$ curl -X 'PUT' \
'http://localhost:3042/pages?where.id.in=1,2' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"title": "Updated title!",
"body": "Updated body!"
}'
[{
"id": 1,
"title": "Updated title!",
"body": "Updated body!"
},{
"id": 2,
"title": "Updated title!",
"body": "Updated body!"
}]
DELETE [PLURAL_ENTITY_NAME]/[PRIMARY_KEY]
Deletes a row identified by the PRIMARY_KEY
.
Example
$ curl -X 'DELETE' 'http://localhost:3042/pages/1?fields=title'
{
"title": "Hello Platformatic!"
}
Nested Relationships
Let's consider the following SQL:
CREATE TABLE IF NOT EXISTS movies (
movie_id INTEGER PRIMARY KEY,
title TEXT NOT NULL
);
CREATE TABLE IF NOT EXISTS quotes (
id INTEGER PRIMARY KEY,
quote TEXT NOT NULL,
movie_id INTEGER NOT NULL REFERENCES movies(movie_id)
);
[P_PARENT_ENTITY]
ismovies
[S_PARENT_ENTITY]
ismovie
[P_CHILDREN_ENTITY]
isquotes
[S_CHILDREN_ENTITY]
isquote
In this case, more APIs are available:
GET [P_PARENT_ENTITY]/[PARENT_PRIMARY_KEY]/[P_CHILDREN_ENTITY]
Given a 1-to-many relationship, where a parent entity can have many children, you can query for the children directly.
Example
$ curl -X 'GET' 'http://localhost:3042/movies/1/quotes?fields=quote
[
{
"quote": "I'll be back"
},
{
"quote": "Hasta la vista, baby"
}
]
GET [P_CHILDREN_ENTITY]/[CHILDREN_PRIMARY_KEY]/[S_PARENT_ENTITY]
You can query for the parent directly, e.g.:
$ curl -X 'GET' 'http://localhost:3042/quotes/1/movie?fields=title
{
"title": "Terminator"
}
Many-to-Many Relationships
Many-to-Many relationships let you relate each row in one table to many rows in another table and vice versa.
Many-to-many relationships are implemented in SQL via a "join table", a table whose primary key is composed by the identifier of the two parts of the many-to-many relationship.
Platformatic DB fully support many-to-many relationships on all supported database.
Let's consider the following SQL:
CREATE TABLE pages (
id INTEGER PRIMARY KEY,
the_title VARCHAR(42)
);
CREATE TABLE users (
id INTEGER PRIMARY KEY,
username VARCHAR(255) NOT NULL
);
CREATE TABLE editors (
page_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
role VARCHAR(255) NOT NULL,
CONSTRAINT fk_editor_pages FOREIGN KEY (page_id) REFERENCES pages(id),
CONSTRAINT fk_editor_users FOREIGN KEY (user_id) REFERENCES users(id),
PRIMARY KEY (page_id, user_id)
);
[P_ENTITY]
iseditors
[P_REL_1]
ispages
[S_REL_1]
ispage
[KEY_REL_1]
ispages
PRIMARY KEY:pages(id)
[P_REL_2]
isusers
[S_REL_2]
isuser
[KEY_REL_2]
isusers
PRIMARY KEY:users(id)
Available APIs for the Join Table
GET [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
This returns the entity in the "join table", e.g. GET /editors/page/1/user/1
.
POST [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
Creates a new entity in the "join table", e.g. POST /editors/page/1/user/1
.
PUT [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
Updates an entity in the "join table", e.g. PUT /editors/page/1/user/1
.
DELETE [P_ENTITY]/[S_REL_1]/[KEY_REL_1]/[S_REL_2]/[KEY_REL_2]
Delete the entity in the "join table", e.g. DELETE /editors/page/1/user/1
.
GET /[P_ENTITY]
See the above.
Offset only accepts values >= 0
. Otherwise, an error is returned.
Pagination
Platformatic DB supports result pagination through input parameters: limit
and offset
Example
$ curl -X 'GET' 'http://localhost:3042/movies?limit=5&offset=10
[
{
"title": "Star Wars",
"movie_id": 10
},
...
{
"title": "007",
"movie_id": 14
}
]
This returns 5 movies starting from position 10. The TotalCount functionality can be used in order to evaluate if there are more pages.
Limit
By default, a limit value (10
) is applied to each request. Clients can override this behavior by passing a value. In this case the server validates the input, and an error is return if exceeds the max
accepted value (100
).
Limit's values can be customized through configuration:
{
...
"db": {
...
"limit": {
"default": 50,
"max": 1000
}
}
}
Limit only accepts values >= 0
. Otherwise, an error is returned.
Offset
By default, offset is not applied to the request. Clients can override this behavior by passing a value.
Offset only accepts values >= 0
. Otherwise, an error is returned.
Allow the primary keys in the input
@platformatic/sql-openapi
allows for specifying if to accept the table primary keys
in the inputs to the various routes.
Configuration
app.register(require('@platformatic/sql-openapi'), {
allowPrimaryKeysInInput: false
})
Example
If allowPrimaryKeysInInput
is set to false
:
$ curl -X 'POST' \
'http://localhost:3042/pages/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 42,
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic!"
}'
{
"id": 1,
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic"
"statusCode": 400,
"code": 'FST_ERR_VALIDATION',
"error:" 'Bad Request',
"message": 'body/id must NOT be valid'
}
If allowPrimaryKeysInInput
is set to true
or left undefined
:
$ curl -X 'POST' \
'http://localhost:3042/pages/' \
-H 'accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"id": 42,
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic!"
}'
{
"id": 42,
"title": "Hello Platformatic!",
"body": "Welcome to Platformatic"
}