作为RPC的功能#

"A single resource can be the equivalent of a database function, with the power to abstract state changes over any number of storage items" -- Roy T. Fielding

函数可以执行PostgreSQL允许的任何操作(读取数据、修改数据、 raise errors ,甚至DDL操作)。中的每个函数 exposed schema 并可由 active database role 是可在 /rpc 前缀。

如果它们返回表类型,则函数可以:

备注

为什么 /rpc 前缀?PostgreSQL允许表或视图与函数同名。前缀使我们可以避免路由冲突。

警告

Stored Procedures 不受支持。

以邮寄方式呼叫#

要在API调用中提供参数,请在请求有效负载中包含一个JSON对象。对象的每个键/值都将成为一个参数。

例如,假设我们已经在数据库中创建了此函数。

CREATE FUNCTION add_them(a integer, b integer)
RETURNS integer AS $$
 SELECT a + b;
$$ LANGUAGE SQL IMMUTABLE;

重要

无论何时创建或更改函数,都必须刷新PostgREST的模式缓存。请参阅小节 架构缓存重新加载

客户端可以通过发布如下对象来调用它

curl "http://localhost:3000/rpc/add_them" \
  -X POST -H "Content-Type: application/json" \
  -d '{ "a": 1, "b": 2 }'
3

备注

PostgreSQL会将标识符名转换为小写,除非您将它们引用为如下形式:

CREATE FUNCTION "someFunc"("someParam" text) ...

使用GET调用#

如果该函数不修改数据库,它也将在GET方法下运行(请参见 访问模式 )。

curl "http://localhost:3000/rpc/add_them?a=1&b=2"

函数参数名称与POST用例中的JSON对象键匹配,对于GET用例,它们与查询参数匹配 ?a=1&b=2

具有单个未命名JSON参数的函数#

如果希望将JSON请求正文作为单个参数发送,则可以使用单个未命名的 jsonjsonb 参数。为此, Content-Type: application/json 请求中必须包含标头。

CREATE FUNCTION mult_them(json) RETURNS int AS $$
  SELECT ($1->>'x')::int * ($1->>'y')::int
$$ LANGUAGE SQL;
curl "http://localhost:3000/rpc/mult_them" \
  -X POST -H "Content-Type: application/json" \
  -d '{ "x": 4, "y": 2 }'
8

备注

如果重载函数具有单个 jsonjsonb 如果没有使用POST请求中发送的参数找到其他重载函数,则PostgREST将调用此函数作为回退。

警告

还可以使用将JSON请求正文作为单个参数发送 Prefer: params=single-object 但这种方法是 deprecated

具有单个未命名参数的函数#

您可以使用单个未命名参数向函数发出POST请求以发送RAW byteatextxml 数据。

要发送原始XML,参数类型必须为 xml 和页眉 Content-Type: text/xml 必须包括在请求中。

要发送原始二进制文件,参数类型必须为 bytea 和页眉 Content-Type: application/octet-stream 必须包括在请求中。

CREATE TABLE files(blob bytea);

CREATE FUNCTION upload_binary(bytea) RETURNS void AS $$
  INSERT INTO files(blob) VALUES ($1);
$$ LANGUAGE SQL;
curl "http://localhost:3000/rpc/upload_binary" \
  -X POST -H "Content-Type: application/octet-stream" \
  --data-binary "@file_name.ext"
HTTP/1.1 200 OK

[ ... ]

要发送原始文本,参数类型必须为 text 和页眉 Content-Type: text/plain 必须包括在请求中。

带有数组参数的函数#

您可以调用接受数组参数的函数:

create function plus_one(arr int[]) returns int[] as $$
   SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
curl "http://localhost:3000/rpc/plus_one" \
  -X POST -H "Content-Type: application/json" \
  -d '{"arr": [1,2,3,4]}'
[2,3,4,5]

要使用GET调用函数,可以将数组作为 array literal ,如中 {1,2,3,4} 。请注意,必须对花括号进行urlended ({%7B}%7D )。

curl "http://localhost:3000/rpc/plus_one?arr=%7B1,2,3,4%7D'"

备注

对于PostgreSQL 10之前的版本,要在POST有效负载上传递PostgreSQL原生数组,您需要引用它并使用数组文字:

curl "http://localhost:3000/rpc/plus_one" \
  -X POST -H "Content-Type: application/json" \
  -d '{ "arr": "{1,2,3,4}" }'

在这些版本中,我们建议使用JSON类型的函数参数来接受来自客户端的数组。

变分函数#

您可以通过在POST请求中传递JSON数组来调用变量函数:

create function plus_one(variadic v int[]) returns int[] as $$
   SELECT array_agg(n + 1) FROM unnest($1) AS n;
$$ language sql;
curl "http://localhost:3000/rpc/plus_one" \
  -X POST -H "Content-Type: application/json" \
  -d '{"v": [1,2,3,4]}'
[2,3,4,5]

在GET请求中,您可以重复相同的参数名称:

curl "http://localhost:3000/rpc/plus_one?v=1&v=2&v=3&v=4"

重复也适用于POST请求 Content-Type: application/x-www-form-urlencoded

curl "http://localhost:3000/rpc/plus_one" \
  -X POST -H "Content-Type: application/x-www-form-urlencoded" \
  -d 'v=1&v=2&v=3&v=4'

表值函数#

可以使用与相同的筛选器筛选返回表类型的函数 tables and views 。他们还可以使用 Resource Embedding

CREATE FUNCTION best_films_2017() RETURNS SETOF films ..
curl "http://localhost:3000/rpc/best_films_2017?select=title,director:directors(*)"
curl "http://localhost:3000/rpc/best_films_2017?rating=gt.8&order=title.desc"

函数内联#

方法之后的函数 rules for inlining 还将内联 filtersorderlimits

例如,对于以下函数:

create function getallprojects() returns setof projects
language sql stable
as $$
  select * from projects;
$$;

我们去买它的吧 执行计划 在应用了筛选器的情况下调用它时:

curl "http://localhost:3000/rpc/getallprojects?id=eq.1" \
  -H "Accept: application/vnd.pgrst.plan"
Aggregate  (cost=8.18..8.20 rows=1 width=112)
  ->  Index Scan using projects_pkey on projects  (cost=0.15..8.17 rows=1 width=40)
        Index Cond: (id = 1)

请注意,计划中没有“函数扫描”节点,这告诉我们它已被内联。

标量函数#

PostgREST将检测函数是标量函数还是表值函数,并相应地塑造响应格式:

curl "http://localhost:3000/rpc/add_them?a=1&b=2"
3
curl "http://localhost:3000/rpc/best_films_2017"
[
  { "title": "Okja", "rating": 7.4},
  { "title": "Call me by your name", "rating": 8},
  { "title": "Blade Runner 2049", "rating": 8.1}
]

要手动选择返回格式(如二进制),请参见 媒体类型处理程序

非类型化函数#

返回的函数 recordSETOF record 支持:

create function projects_setof_record() returns setof record as $$
  select * from projects;
$$ language sql;
curl "http://localhost:3000/rpc/projects_setof_record"
[{"id":1,"name":"Windows 7","client_id":1},
 {"id":2,"name":"Windows 10","client_id":1},
 {"id":3,"name":"IOS","client_id":2}]

但是,请注意,在尝试使用 垂直过滤水平滤波 在他们身上。

因此,虽然它们可以用于快速测试,但建议始终为函数选择严格的返回类型。

Overloaded functions#

您可以使用不同数量的参数调用重载函数。

CREATE FUNCTION rental_duration(customer_id integer) ..

CREATE FUNCTION rental_duration(customer_id integer, from_date date) ..
curl "http://localhost:3000/rpc/rental_duration?customer_id=232"
curl "http://localhost:3000/rpc/rental_duration?customer_id=232&from_date=2018-07-01"

重要

不支持参数名称相同但类型不同的重载函数。