Search code examples
postgresqlcitus

I get error when create distributed table on citus (postgres)


I created a table on Citus: CREATE TABLE myschema.mytable

Then I created function that gets data from table myschema.mytable:

CREATE FUNCTION myschema.myfunction(id INT)
RETURNS INT AS $$
DECLARE approved_count INT;
BEGIN
SELECT COUNT(id) INTO approved_count 
FROM myschema.mytable
WHERE id = $1 AND is_deleted = FALSE AND is_flagged = TRUE;
RETURN approved_count;
END;
$$ LANGUAGE plpgsql

Then I added the constraint on table myschema.mytable:

ALTER TABLE myschema.mytable ADD CONSTRAINT myconstraint CHECK ((myschema.myfunction()=(0)));

All queries above were executed successfully.

Finally, I created a distributed table:

SELECT create_distributed_table('myschema.mytable', 'tenant_id');

And I got the error:

ERROR:  function myschema.myfunction() does not exist
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.
CONTEXT:  while executing command on 10.0.0.***:****
SQL state: 42883

I tried to run queries in the other order. I created a table, distributed table, and function successfully. But I couldn't add constraint and got the same error.

As I understand my Worker does not see my function. How can I resolve this problem?


Solution

  • Citus currently does not propagate CREATE FUNCTION queries to worker nodes. You need to manually create the function in the workers yourself.

    You can also use the following query to manually create your function in your worker nodes:

    SELECT *
    FROM run_command_on_workers($cmd$
      CREATE FUNCTION myschema.myfunction(id INT) RETURNS INT AS
      $$ DECLARE approved_count INT;
        BEGIN 
        SELECT 
          COUNT(id)
        INTO
          approved_count 
        FROM 
          myschema.mytable 
        WHERE 
          id = $1 
          AND is_deleted = FALSE 
          AND is_flagged = TRUE;
        RETURN approved_count;
        END;
      $$ LANGUAGE plpgsql
    $cmd$);
    

    You may need to create myschema on the worker nodes as well (depending on your Citus version). You can also do this using run_command_on_workers() udf with a CREATE SCHEMA IF NOT EXISTS command.

    You can check out the documentation for run_command_on_workers() here.

    FYI: I am currently working on a feature to distribute functions in worker nodes. We plan to ship it in the next Citus major release

    Edit: create_distributed_function UDF is there in Citus >= v9.0 You can see the docs at https://docs.citusdata.com/en/v9.0/develop/api_udf.html#create-distributed-function and some more in https://docs.citusdata.com/en/v9.0/faq/faq.html#how-do-i-create-database-roles-functions-extensions-etc-in-a-citus-cluster