Starting with V3.1, Hologres supports remote calls to user-defined functions in Function Compute (FC) to process complex business logic or perform advanced data operations. This topic describes how to use Remote UDFs in Hologres.
Overview
Remote functions extend the data processing and analysis capabilities of Hologres by integrating external functions from services like Alibaba Cloud Function Compute (FC). This integration allows you to dynamically call FC functions when querying Hologres data to process complex business logic or perform advanced data operations.
Remote functions support the following use cases:
-
Real-time data processing: Call external functions during data queries to perform data cleansing, format conversion, or complex calculations.
-
Third-party service integration: Use Function Compute to interact with other Alibaba Cloud services or third-party APIs, using your Hologres data.
-
Advanced analytics: Use Function Compute to run advanced analytics algorithms, such as model inference and machine learning, and write the results directly back to Hologres.
Prerequisites
-
You have a Hologres instance of V3.1 or later. For more information, see Purchase a Hologres instance.
-
You have activated Function Compute and are using a V3.0 instance. To activate the service, log on to the Function Compute console.
-
The
AliyunServiceRoleForHologresRemoteUDFservice-linked role is authorized.-
Log on to the Hologres console. In the left-side navigation pane, click Create a Service-linked Role.
-
Select
AliyunServiceRoleForHologresRemoteUDFand click Authorize Now.
-
-
The Hologres instance and Function Compute service must be in the same region.
-
Activate Alibaba Cloud Function Compute, and develop and deploy the function to be called by Hologres. For details, see Code development overview.
Limitations
-
Only scalar UDFs and user-defined table-valued functions (UDTFs) are supported. User-defined aggregate functions (UDAFs) are not supported.
-
Only the following data types and their corresponding array types are supported:
BOOLEAN,INTEGER,BIGINT,REAL,DOUBLE PRECISION, andTEXT. -
Remote functions do not support constant input parameters.
-
This feature incurs costs in Function Compute (FC). For more information, see Billing.
-
This feature does not incur extra costs in Hologres.
-
Remote UDFs can be executed only in the Hologres query engine (HQE). They cannot be used in the same SQL statement with built-in functions that are executed only in the PostgreSQL-compatible query engine (PQE), such as encryption and decryption (PGCRYPTO) extension functions. Using them together causes an engine execution conflict and returns the following error.
ERROR: ORCA failed to produce a plan : No plan has been computed for required propertiesTo use a Remote UDF and a PQE-only built-in function at the same time, split the operations into separate SQL statements and execute them individually.
Manage remote UDFs
Create an extension
To use remote functions, you must first create an extension by running the following command:
CREATE EXTENSION [ IF NOT EXISTS ] function_compute;
Create a function
Syntax
CREATE [ OR REPLACE ] FUNCTION <function_name>
( [ [ argmode ] [ argname ] <argtype> [ { DEFAULT | = } default_expr ] [, ...] ] )
[ RETURNS [SETOF] rettype | RETURNS TABLE ( column_name column_type) ]
LANGUAGE function_compute
AS '<fc_endpoint>/<func_name>'
{
{ CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT }
| SET function_compute.qualifier TO <qualifier>
| SET function_compute.compression TO <compression>
| SET function_compute.max_batch_size TO <max_batch_size>
} ...
Parameters
|
Category |
Parameter |
Required |
Description |
|
Function name |
function_name |
Yes |
The name of the function.
|
|
Function parameters |
argtype |
Yes |
The data type of the parameter. |
|
argmode |
No |
Valid values are IN, OUT, and INOUT. The default is IN. To avoid ambiguity, we recommend that you do not use INOUT. A function can have only one OUT or INOUT parameter. |
|
|
argname |
No |
The name of the parameter.
|
|
|
default_expr |
No |
The default value. This applies only to input parameters. If a parameter has a default value, all subsequent parameters must also have default values. |
|
|
FC endpoint |
LANGUAGE function_compute |
Yes |
Specifies that the function uses the Function Compute service. |
|
fc_endpoint |
Yes |
The internal endpoint for Function Compute. For more information, see Endpoints. |
|
|
func_name |
Yes |
The name of the target function, which must be created in the Function Compute console in advance. |
|
|
Return type |
rettype |
No |
The data type of the return value. If you use OUT or INOUT parameters, you can omit the RETURNS clause. If specified, this clause must be consistent with the result type implied by the output parameters. |
|
column_name |
No |
In the RETURNS TABLE syntax, this is the name of an output column. This is another way to declare named OUT parameters. The difference is that RETURNS TABLE also implies RETURNS SETOF, meaning the function returns a set. |
|
|
column_type |
No |
In the RETURNS TABLE syntax, this is the data type of an output column. |
|
|
Null-handling policy |
CALLED ON NULL INPUT |
No |
The default behavior. The function is called even for NULL inputs and must handle the null logic itself. |
|
RETURNS NULL ON NULL INPUT |
No |
Returns NULL immediately if any input is NULL. |
|
|
STRICT |
No |
An alias for RETURNS NULL ON NULL INPUT. |
|
|
Function version control |
qualifier |
No |
Specifies the function version or alias to call. The default value is |
|
Request compression algorithm |
compression |
No |
Specifies the compression algorithm for the function call request and response. Valid values:
|
|
Maximum batch size per request |
max_batch_size |
No |
Specifies the maximum number of rows to send to FC in each batch. Use this setting to cap the batch size for FC functions that have memory limits or other constraints. If you do not specify this parameter, Hologres automatically calculates and uses the optimal batch size. In most cases, you do not need to set this parameter. |
Examples
-
Create a scalar UDF.
CREATE OR REPLACE FUNCTION rf_add ( a INTEGER, b INTEGER DEFAULT 1 ) RETURNS BIGINT LANGUAGE function_compute AS 'xxxxxxxxxxxxx.cn-shanghai-internal.fc.aliyuncs.com/add' ; -
Create a UDTF.
-- Method 1 CREATE OR REPLACE FUNCTION rf_unnest(TEXT []) RETURNS TABLE (item TEXT ) LANGUAGE function_compute AS 'xxxxxxxxxxxxxx.cn-hangzhou-internal.fc.aliyuncs.com/unnest' STRICT SET function_compute.max_batch_size TO 1024; -- Method 2 CREATE OR REPLACE FUNCTION rf_unnest(TEXT []) RETURNS SETOF TEXT LANGUAGE function_compute AS 'xxxxxxxxxxxxxx.cn-hangzhou-internal.fc.aliyuncs.com/unnest' STRICT SET function_compute.max_batch_size TO 1024;
View functions
View the created remote functions.
SELECT
CASE
WHEN p.proretset = 'f' THEN 'scalar UDF'
WHEN p.proretset = 't' THEN 'UDTF'
END AS function_type,
n.nspname AS schema_name,
p.proname AS function_name,
pg_get_function_arguments(p.oid) AS arguments,
pg_get_function_result(p.oid) AS return_type,
p.proisstrict AS is_strict,
p.proconfig AS config,
pg_get_functiondef(p.oid) AS definition
FROM
pg_proc p
JOIN pg_language l ON p.prolang = l.oid
JOIN pg_namespace n ON p.pronamespace = n.oid
WHERE
l.lanname = 'function_compute'
AND p.prokind != 'p'
ORDER BY
function_type,
schema_name,
function_name;
Delete a function
Syntax
DROP FUNCTION [ IF EXISTS ] <function_name> [ ( [ [ argmode ] [ argname ] <argtype> [, ...] ] ) ] [, ...]
Parameters
|
Parameter |
Required |
Description |
|
function_name |
Yes |
The name of the function to delete. |
|
argtype |
Yes |
The data type of the parameter. |
|
argmode |
No |
Valid values are IN, OUT, and INOUT. The default is IN. To avoid ambiguity, we recommend that you do not use INOUT. A function can have only one OUT or INOUT parameter. |
|
argname |
No |
The name of the parameter. For input parameters, the name is for documentation purposes only. For output parameters, the name determines the column name in the result set. If omitted, the system generates a default name. |
Example
DROP FUNCTION rf_add(INTEGER, INTEGER);
Data exchange format
Request format: Hologres to FC
Hologres calls the InvokeFunction API of Function Compute by sending a POST request. The request body is a JSON object. This object contains a single key named data. Its value is a two-dimensional array, where each inner array represents a row of data in the batch and contains the parameters for the function call.
Data serialization rules
-
BOOLEANis serialized to a JSON boolean. -
INTEGERandBIGINTare serialized to a JSON number. -
REALandDOUBLE PRECISIONare serialized to a JSON number. -
TEXTis serialized to a JSON string. -
A SQL
NULLvalue is serialized to a JSONnull.
Example
The following code shows a sample serialized request for a remote function with the signature rf_demo(TEXT, INTEGER, BOOLEAN).
{
"data": [
["foo", 100, true],
[null, null, false],
["bar", 200, false]
]
}
Response format: FC to Hologres
After Function Compute processes a batch of data, it must return the results to Hologres in JSON format as follows:
-
Scalar UDF
-
The top-level object must contain a
resultsfield. Its value must be an array, where each element corresponds to the result for a row of input data. -
Each row result must be an array, and the order of results must match the order of input rows. For example, the Nth element in the results array corresponds to the Nth input row.
The following code shows a sample response for a batch of four rows:
{ "results": [ ["Beijing"], ["Shanghai"], ["Shenzhen"], ["Guangzhou"] ] } -
-
A user-defined table-valued function (UDTF) supports single-row input to generate multi-row output. A row number (row_num) is required to identify the relationship with the original input row.
-
The top-level object must contain a
resultsfield. Its value must be an array, where each element corresponds to one row of output data. -
Each row result must be an array that contains two elements:
-
row_num(first element): The 0-based index of the original input row, used to associate input with output. The row_num values must be returned in ascending order. -
result (second element): The value of a single output row.
-
Example:
{ "results": [ [0, "Beijing"], [1, "Shanghai"], [3, "Shenzhen"], [3, "Guangzhou"], ] } -
Example
This example uses the unnest function.
-
Activate Function Compute.
Log on to the Function Compute console. You can also claim a free resource package based on the on-screen prompts. For more information, see Free Tier.
-
Create an FC Event Function.
-
In the left-side navigation pane, click Functions. Switch to the region where your Hologres instance resides.
-
On the Functions page, click Create Function. The Create Function page opens.
-
Select Event Function and configure the following parameters. Retain the default settings for other parameters. For more information, see Create an event-triggered function.
Parameter
Description
Function name
A custom name. For example,
unnest.Runtime
Select Built-in Runtimes / Python / Python 3.10.
Code upload method
Select Upload ZIP.
Code package
Upload the code package.
Save the following code as unnest.py and compress it into a file named unnest.zip.
import json def unnest(event, context): evt = json.loads(event) data = evt.get('data', None) if data is None: raise ValueError('no "data" key in event.') if not isinstance(data, list): raise ValueError('data is not a list.') res = list() for i in range(len(data)): if len(data[i]) != 1 or not isinstance(data[i], list): raise ValueError('the item in data is not a list.') for item in data[i][0]: res.append([i, item]) return json.dumps({'results': res})Handler
Enter
unnest.unnest.
-
-
Create a Hologres remote function.
NotePerform the following steps in HoloWeb. For more information, see Connect to HoloWeb.
CREATE EXTENSION IF NOT EXISTS function_compute; CREATE OR REPLACE FUNCTION rf_unnest(INTEGER []) RETURNS SETOF INTEGER STRICT LANGUAGE function_compute AS 'xxxxxxxxxxxxxxxxx.cn-shanghai-internal.fc.aliyuncs.com/unnest'; -
Prepare test data.
CREATE TABLE test_array ( numbers INTEGER[] ); INSERT INTO test_array (numbers) VALUES (ARRAY[1, 3]), (ARRAY[2, 4]), ('{}'), (ARRAY[]::INTEGER[]), (NULL); -
Call the remote function.
SELECT numbers, rf_unnest(numbers) FROM test_array; numbers | rf_unnest ---------+----------- {2,4} | 2 {2,4} | 4 {1,3} | 1 {1,3} | 3 (4 rows)