作为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
前缀。
如果它们返回表类型,则函数可以:
使用所有相同的工具 read filters as Tables and Views (水平/垂直过滤、计数、限制等)。
使用 Resource Embedding 如果返回的表类型与其他表有关系,则返回。
备注
为什么 /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请求正文作为单个参数发送,则可以使用单个未命名的 json
或 jsonb
参数。为此, 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
备注
如果重载函数具有单个 json
或 jsonb
如果没有使用POST请求中发送的参数找到其他重载函数,则PostgREST将调用此函数作为回退。
警告
还可以使用将JSON请求正文作为单个参数发送 Prefer: params=single-object 但这种方法是 deprecated 。
具有单个未命名参数的函数#
您可以使用单个未命名参数向函数发出POST请求以发送RAW bytea
, text
或 xml
数据。
要发送原始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 还将内联 filters , order 和 limits 。
例如,对于以下函数:
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}
]
要手动选择返回格式(如二进制),请参见 媒体类型处理程序 。
非类型化函数#
返回的函数 record
或 SETOF 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"
重要
不支持参数名称相同但类型不同的重载函数。