diff --git a/src/backend/distributed/commands/function.c b/src/backend/distributed/commands/function.c index 9532befab..4b6dfa731 100644 --- a/src/backend/distributed/commands/function.c +++ b/src/backend/distributed/commands/function.c @@ -82,8 +82,7 @@ static void EnsureFunctionCanBeColocatedWithTable(Oid functionOid, Oid static bool ShouldPropagateCreateFunction(CreateFunctionStmt *stmt); static bool ShouldPropagateAlterFunction(const ObjectAddress *address); static bool ShouldAddFunctionSignature(FunctionParameterMode mode); -static ObjectAddress * GetUndistributableRelationDependency( - ObjectAddress *functionAddress); +static ObjectAddress * GetUndistributableDependency(ObjectAddress *functionAddress); static ObjectAddress FunctionToObjectAddress(ObjectType objectType, ObjectWithArgs *objectWithArgs, bool missing_ok); @@ -1295,19 +1294,20 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString) } /* - * This check should have been - * (a) valid for all objects not only for functions - * (b) should check for all types of objects no only for relations. - * - * We do this limited check for now as functions are more likely to be used with - * (a) and (b), and we want to scope it for now + * This check should have been valid for all objects not only for functions. Though, + * we do this limited check for now as functions are more likely to be used with + * such dependencies, and we want to scope it for now */ - ObjectAddress *undistributableDependency = GetUndistributableRelationDependency( + ObjectAddress *undistributableDependency = GetUndistributableDependency( &functionAddress); if (undistributableDependency != NULL) { if (SupportedDependencyByCitus(undistributableDependency)) { + /* + * Citus can't distribute some relations as dependency, although those + * types as supported by Citus. So we can use get_rel_name directly + */ RangeVar *functionRangeVar = makeRangeVarFromNameList(stmt->funcname); char *functionName = functionRangeVar->relname; char *dependentRelationName = @@ -1322,10 +1322,15 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString) } else { + char *objectType = NULL; + #if PG_VERSION_NUM >= PG_VERSION_14 + objectType = getObjectTypeDescription(undistributableDependency, false); + #else + objectType = getObjectTypeDescription(undistributableDependency); + #endif ereport(WARNING, (errmsg("Citus can't distribute functions having " - "dependency on unsupported relation with relkind %c", - get_rel_relkind( - undistributableDependency->objectId)), + "dependency on unsupported object of type \"%s\"", + objectType), errdetail("Function will be created only locally"))); } @@ -1344,11 +1349,11 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString) /* - * GetUndistributableRelationDependency checks whether object has any non-distributable - * relation dependency. If any one found, it will be returned. + * GetUndistributableDependency checks whether object has any non-distributable + * dependency. If any one found, it will be returned. */ static ObjectAddress * -GetUndistributableRelationDependency(ObjectAddress *objectAddress) +GetUndistributableDependency(ObjectAddress *objectAddress) { List *dependencies = GetAllDependenciesForObject(objectAddress); ObjectAddress *dependency = NULL; @@ -1359,22 +1364,32 @@ GetUndistributableRelationDependency(ObjectAddress *objectAddress) continue; } - if (getObjectClass(dependency) != OCLASS_CLASS) + if (!SupportedDependencyByCitus(dependency)) { - continue; + /* + * Although languages are not supported by Citus, all must be created + * with the postgres itself, so skip them. Since roles should also be + * handled manually with Citus community, skip them as well. + */ + if (getObjectClass(dependency) != OCLASS_LANGUAGE && + getObjectClass(dependency) != OCLASS_ROLE) + { + return dependency; + } } - /* - * Citus can only distribute dependent non-distributed sequence and composite - * types. - */ - char relKind = get_rel_relkind(dependency->objectId); - if (relKind == RELKIND_SEQUENCE || relKind == RELKIND_COMPOSITE_TYPE) + if (getObjectClass(dependency) == OCLASS_CLASS) { - continue; + /* + * Citus can only distribute dependent non-distributed sequence + * and composite types. + */ + char relKind = get_rel_relkind(dependency->objectId); + if (relKind != RELKIND_SEQUENCE && relKind != RELKIND_COMPOSITE_TYPE) + { + return dependency; + } } - - return dependency; } return NULL; diff --git a/src/test/regress/expected/forcedelegation_functions.out b/src/test/regress/expected/forcedelegation_functions.out index f1b28cb28..0b266234e 100644 --- a/src/test/regress/expected/forcedelegation_functions.out +++ b/src/test/regress/expected/forcedelegation_functions.out @@ -358,14 +358,16 @@ PL/pgSQL function func_calls_forcepush_func() line XX at SQL statement 101 (1 row) +-- Block distributing that function as distributing it causes +-- different test output on PG 14. +SET citus.enable_metadata_sync TO OFF; CREATE OR REPLACE FUNCTION get_val() RETURNS INT AS $$ BEGIN RETURN 100::INT; END; $$ LANGUAGE plpgsql; -DEBUG: switching to sequential query execution mode -DETAIL: A command for a distributed function is run. To make sure subsequent commands see the function correctly we need to make sure to use only one connection for all future commands +RESET citus.enable_metadata_sync; -- -- UDF calling another UDF in a FROM clause -- fn() @@ -387,9 +389,6 @@ DEBUG: switching to sequential query execution mode DETAIL: A command for a distributed function is run. To make sure subsequent commands see the function correctly we need to make sure to use only one connection for all future commands SELECT func_calls_forcepush_func_infrom(); DEBUG: function does not have co-located tables -DEBUG: not pushing down function calls in a multi-statement transaction -CONTEXT: SQL statement "SELECT get_val()" -PL/pgSQL function func_calls_forcepush_func_infrom() line XX at assignment DEBUG: pushing down function call in a multi-statement transaction CONTEXT: SQL statement "SELECT inner_force_delegation_function FROM inner_force_delegation_function(add_val + 100)" PL/pgSQL function func_calls_forcepush_func_infrom() line XX at SQL statement @@ -445,9 +444,6 @@ DEBUG: switching to sequential query execution mode DETAIL: A command for a distributed function is run. To make sure subsequent commands see the function correctly we need to make sure to use only one connection for all future commands SELECT func_calls_forcepush_func_intarget(); DEBUG: function does not have co-located tables -DEBUG: not pushing down function calls in a multi-statement transaction -CONTEXT: SQL statement "SELECT get_val()" -PL/pgSQL function func_calls_forcepush_func_intarget() line XX at assignment DEBUG: pushing down function call in a multi-statement transaction CONTEXT: SQL statement "SELECT inner_force_delegation_function(100 + 100) OFFSET 0" PL/pgSQL function func_calls_forcepush_func_intarget() line XX at SQL statement diff --git a/src/test/regress/expected/function_propagation.out b/src/test/regress/expected/function_propagation.out index 068007ce4..5e6819944 100644 --- a/src/test/regress/expected/function_propagation.out +++ b/src/test/regress/expected/function_propagation.out @@ -186,7 +186,7 @@ BEGIN return 1; END; $$; -WARNING: Citus can't distribute functions having dependency on unsupported relation with relkind v +WARNING: Citus can't distribute functions having dependency on unsupported object of type "view" DETAIL: Function will be created only locally CREATE OR REPLACE FUNCTION func_8(param_1 int) RETURNS function_prop_view @@ -196,7 +196,7 @@ BEGIN return 1; END; $$; -WARNING: Citus can't distribute functions having dependency on unsupported relation with relkind v +WARNING: Citus can't distribute functions having dependency on unsupported object of type "view" DETAIL: Function will be created only locally -- Check within transaction BEGIN; diff --git a/src/test/regress/expected/multi_extension.out b/src/test/regress/expected/multi_extension.out index 1c12e7fc6..12d6998d5 100644 --- a/src/test/regress/expected/multi_extension.out +++ b/src/test/regress/expected/multi_extension.out @@ -77,7 +77,7 @@ END $func$ LANGUAGE plpgsql; CREATE SCHEMA test; :create_function_test_maintenance_worker -WARNING: Citus can't distribute functions having dependency on unsupported relation with relkind v +WARNING: Citus can't distribute functions having dependency on unsupported object of type "view" DETAIL: Function will be created only locally -- check maintenance daemon is started SELECT datname, current_database(), @@ -1200,7 +1200,7 @@ HINT: You can manually create a database and its extensions on workers. CREATE EXTENSION citus; CREATE SCHEMA test; :create_function_test_maintenance_worker -WARNING: Citus can't distribute functions having dependency on unsupported relation with relkind v +WARNING: Citus can't distribute functions having dependency on unsupported object of type "view" DETAIL: Function will be created only locally -- see that the daemon started SELECT datname, current_database(), diff --git a/src/test/regress/expected/pg13.out b/src/test/regress/expected/pg13.out index e8c55bb21..2ba782aaf 100644 --- a/src/test/regress/expected/pg13.out +++ b/src/test/regress/expected/pg13.out @@ -145,9 +145,13 @@ CREATE TYPE myvarchar; CREATE FUNCTION myvarcharin(cstring, oid, integer) RETURNS myvarchar LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharin'; NOTICE: return type myvarchar is only a shell +WARNING: Citus can't distribute functions having dependency on unsupported object of type "type" +DETAIL: Function will be created only locally CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharout'; NOTICE: argument type myvarchar is only a shell +WARNING: Citus can't distribute functions having dependency on unsupported object of type "type" +DETAIL: Function will be created only locally CREATE TYPE myvarchar ( input = myvarcharin, output = myvarcharout, @@ -160,7 +164,7 @@ CREATE TABLE my_table (a int, b myvarchar); -- """Add ALTER TYPE options useful for extensions, -- like TOAST and I/O functions control (Tomas Vondra, Tom Lane)""" SELECT create_distributed_table('my_table', 'a'); -ERROR: type "test_pg13.myvarchar" is only a shell +ERROR: type "test_pg13.myvarchar" does not exist CONTEXT: while executing command on localhost:xxxxx CREATE TABLE test_table(a int, b tsvector); SELECT create_distributed_table('test_table', 'a'); diff --git a/src/test/regress/sql/forcedelegation_functions.sql b/src/test/regress/sql/forcedelegation_functions.sql index 6f62c41d5..19390c4d8 100644 --- a/src/test/regress/sql/forcedelegation_functions.sql +++ b/src/test/regress/sql/forcedelegation_functions.sql @@ -189,12 +189,16 @@ COMMIT; SELECT func_calls_forcepush_func(); +-- Block distributing that function as distributing it causes +-- different test output on PG 14. +SET citus.enable_metadata_sync TO OFF; CREATE OR REPLACE FUNCTION get_val() RETURNS INT AS $$ BEGIN RETURN 100::INT; END; $$ LANGUAGE plpgsql; +RESET citus.enable_metadata_sync; -- -- UDF calling another UDF in a FROM clause