mirror of https://github.com/citusdata/citus.git
Merge pull request #5761 from citusdata/velioglu/cyclic_dep
Error out if object has unsupported or circular dependencyfix/subscript-jsonb
commit
76f249a05a
|
@ -57,42 +57,12 @@ PostprocessDefineAggregateStmt(Node *node, const char *queryString)
|
||||||
|
|
||||||
EnsureSequentialMode(OBJECT_AGGREGATE);
|
EnsureSequentialMode(OBJECT_AGGREGATE);
|
||||||
|
|
||||||
ObjectAddress *undistributableDependency = GetUndistributableDependency(
|
/* If the aggregate has any unsupported dependency, create it locally */
|
||||||
&address);
|
DeferredErrorMessage *depError = DeferErrorIfHasUnsupportedDependency(&address);
|
||||||
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 *aggRangeVar = makeRangeVarFromNameList(stmt->defnames);
|
|
||||||
char *aggName = aggRangeVar->relname;
|
|
||||||
char *dependentRelationName =
|
|
||||||
get_rel_name(undistributableDependency->objectId);
|
|
||||||
|
|
||||||
ereport(WARNING, (errmsg("Citus can't distribute aggregate \"%s\" having "
|
if (depError != NULL)
|
||||||
"dependency on non-distributed relation \"%s\"",
|
|
||||||
aggName, dependentRelationName),
|
|
||||||
errdetail("Aggregate will be created only locally"),
|
|
||||||
errhint("To distribute aggregate, distribute dependent "
|
|
||||||
"relations first. Then, re-create the aggregate")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
char *objectType = NULL;
|
RaiseDeferredError(depError, WARNING);
|
||||||
#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 object of type \"%s\"",
|
|
||||||
objectType),
|
|
||||||
errdetail("Aggregate will be created only locally")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,7 +318,6 @@ CreateCitusLocalTable(Oid relationId, bool cascadeViaForeignKeys, bool autoConve
|
||||||
* Ensure dependencies exist as we will create shell table on the other nodes
|
* Ensure dependencies exist as we will create shell table on the other nodes
|
||||||
* in the MX case.
|
* in the MX case.
|
||||||
*/
|
*/
|
||||||
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
|
|
||||||
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -444,7 +444,6 @@ CreateDistributedTable(Oid relationId, char *distributionColumnName,
|
||||||
ObjectAddress tableAddress = { 0 };
|
ObjectAddress tableAddress = { 0 };
|
||||||
ObjectAddressSet(tableAddress, RelationRelationId, relationId);
|
ObjectAddressSet(tableAddress, RelationRelationId, relationId);
|
||||||
|
|
||||||
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
|
|
||||||
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
||||||
|
|
||||||
char replicationModel = DecideReplicationModel(distributionMethod,
|
char replicationModel = DecideReplicationModel(distributionMethod,
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
typedef bool (*AddressPredicate)(const ObjectAddress *);
|
typedef bool (*AddressPredicate)(const ObjectAddress *);
|
||||||
|
|
||||||
|
static void EnsureDependenciesCanBeDistributed(const ObjectAddress *relationAddress);
|
||||||
|
static void ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress);
|
||||||
static int ObjectAddressComparator(const void *a, const void *b);
|
static int ObjectAddressComparator(const void *a, const void *b);
|
||||||
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
|
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
|
||||||
static List * FilterObjectAddressListByPredicate(List *objectAddressList,
|
static List * FilterObjectAddressListByPredicate(List *objectAddressList,
|
||||||
|
@ -56,6 +58,12 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
|
||||||
List *dependenciesWithCommands = NIL;
|
List *dependenciesWithCommands = NIL;
|
||||||
List *ddlCommands = NULL;
|
List *ddlCommands = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there is any unsupported dependency or circular dependency exists, Citus can
|
||||||
|
* not ensure dependencies will exist on all nodes.
|
||||||
|
*/
|
||||||
|
EnsureDependenciesCanBeDistributed(target);
|
||||||
|
|
||||||
/* collect all dependencies in creation order and get their ddl commands */
|
/* collect all dependencies in creation order and get their ddl commands */
|
||||||
List *dependencies = GetDependenciesForObject(target);
|
List *dependencies = GetDependenciesForObject(target);
|
||||||
ObjectAddress *dependency = NULL;
|
ObjectAddress *dependency = NULL;
|
||||||
|
@ -135,6 +143,60 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EnsureDependenciesCanBeDistributed ensures all dependencies of the given object
|
||||||
|
* can be distributed.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
EnsureDependenciesCanBeDistributed(const ObjectAddress *objectAddress)
|
||||||
|
{
|
||||||
|
/* If the object circularcly depends to itself, Citus can not handle it */
|
||||||
|
ErrorIfCircularDependencyExists(objectAddress);
|
||||||
|
|
||||||
|
/* If the object has any unsupported dependency, error out */
|
||||||
|
DeferredErrorMessage *depError = DeferErrorIfHasUnsupportedDependency(objectAddress);
|
||||||
|
|
||||||
|
if (depError != NULL)
|
||||||
|
{
|
||||||
|
RaiseDeferredError(depError, ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ErrorIfCircularDependencyExists checks whether given object has circular dependency
|
||||||
|
* with itself via existing objects of pg_dist_object.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ErrorIfCircularDependencyExists(const ObjectAddress *objectAddress)
|
||||||
|
{
|
||||||
|
List *dependencies = GetAllSupportedDependenciesForObject(objectAddress);
|
||||||
|
|
||||||
|
ObjectAddress *dependency = NULL;
|
||||||
|
foreach_ptr(dependency, dependencies)
|
||||||
|
{
|
||||||
|
if (dependency->classId == objectAddress->classId &&
|
||||||
|
dependency->objectId == objectAddress->objectId &&
|
||||||
|
dependency->objectSubId == objectAddress->objectSubId)
|
||||||
|
{
|
||||||
|
char *objectDescription = NULL;
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||||
|
objectDescription = getObjectDescription(objectAddress, false);
|
||||||
|
#else
|
||||||
|
objectDescription = getObjectDescription(objectAddress);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ereport(ERROR, (errmsg("Citus can not handle circular dependencies "
|
||||||
|
"between distributed objects"),
|
||||||
|
errdetail("\"%s\" circularly depends itself, resolve "
|
||||||
|
"circular dependency first",
|
||||||
|
objectDescription)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copied from PG object_address_comparator function to compare ObjectAddresses.
|
* Copied from PG object_address_comparator function to compare ObjectAddresses.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1365,47 +1365,12 @@ PostprocessCreateFunctionStmt(Node *node, const char *queryString)
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* If the function has any unsupported dependency, create it locally */
|
||||||
* This check should have been valid for all objects not only for functions. Though,
|
DeferredErrorMessage *errMsg = DeferErrorIfHasUnsupportedDependency(&functionAddress);
|
||||||
* 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 = 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 =
|
|
||||||
get_rel_name(undistributableDependency->objectId);
|
|
||||||
|
|
||||||
ereport(WARNING, (errmsg("Citus can't distribute function \"%s\" having "
|
if (errMsg != NULL)
|
||||||
"dependency on non-distributed relation \"%s\"",
|
|
||||||
functionName, dependentRelationName),
|
|
||||||
errdetail("Function will be created only locally"),
|
|
||||||
errhint("To distribute function, distribute dependent "
|
|
||||||
"relations first. Then, re-create the function")));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
char *objectType = NULL;
|
RaiseDeferredError(errMsg, WARNING);
|
||||||
#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 object of type \"%s\"",
|
|
||||||
objectType),
|
|
||||||
errdetail("Function will be created only locally")));
|
|
||||||
}
|
|
||||||
|
|
||||||
return NIL;
|
return NIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1955,7 +1955,6 @@ PostprocessAlterTableStmt(AlterTableStmt *alterTableStatement)
|
||||||
/* changing a relation could introduce new dependencies */
|
/* changing a relation could introduce new dependencies */
|
||||||
ObjectAddress tableAddress = { 0 };
|
ObjectAddress tableAddress = { 0 };
|
||||||
ObjectAddressSet(tableAddress, RelationRelationId, relationId);
|
ObjectAddressSet(tableAddress, RelationRelationId, relationId);
|
||||||
EnsureRelationDependenciesCanBeDistributed(&tableAddress);
|
|
||||||
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
EnsureDependenciesExistOnAllNodes(&tableAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ static void CollectObjectAddress(ObjectAddressCollector *collector,
|
||||||
const ObjectAddress *address);
|
const ObjectAddress *address);
|
||||||
static bool IsObjectAddressCollected(ObjectAddress findAddress,
|
static bool IsObjectAddressCollected(ObjectAddress findAddress,
|
||||||
ObjectAddressCollector *collector);
|
ObjectAddressCollector *collector);
|
||||||
|
static ObjectAddress * GetUndistributableDependency(const ObjectAddress *objectAddress);
|
||||||
static void MarkObjectVisited(ObjectAddressCollector *collector,
|
static void MarkObjectVisited(ObjectAddressCollector *collector,
|
||||||
ObjectAddress target);
|
ObjectAddress target);
|
||||||
static bool TargetObjectVisited(ObjectAddressCollector *collector,
|
static bool TargetObjectVisited(ObjectAddressCollector *collector,
|
||||||
|
@ -742,51 +743,70 @@ SupportedDependencyByCitus(const ObjectAddress *address)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* EnsureRelationDependenciesCanBeDistributed ensures all dependencies of the relation
|
* DeferErrorIfHasUnsupportedDependency returns deferred error message if the given
|
||||||
* can be distributed.
|
* object has any undistributable dependency.
|
||||||
*/
|
*/
|
||||||
void
|
DeferredErrorMessage *
|
||||||
EnsureRelationDependenciesCanBeDistributed(ObjectAddress *relationAddress)
|
DeferErrorIfHasUnsupportedDependency(const ObjectAddress *objectAddress)
|
||||||
{
|
{
|
||||||
ObjectAddress *undistributableDependency =
|
ObjectAddress *undistributableDependency = GetUndistributableDependency(
|
||||||
GetUndistributableDependency(relationAddress);
|
objectAddress);
|
||||||
|
|
||||||
if (undistributableDependency != NULL)
|
if (undistributableDependency == NULL)
|
||||||
{
|
{
|
||||||
char *tableName = get_rel_name(relationAddress->objectId);
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *objectDescription = NULL;
|
||||||
|
char *dependencyDescription = NULL;
|
||||||
|
StringInfo errorInfo = makeStringInfo();
|
||||||
|
StringInfo detailInfo = makeStringInfo();
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_14
|
||||||
|
objectDescription = getObjectDescription(objectAddress, false);
|
||||||
|
dependencyDescription = getObjectDescription(undistributableDependency, false);
|
||||||
|
#else
|
||||||
|
objectDescription = getObjectDescription(objectAddress);
|
||||||
|
dependencyDescription = getObjectDescription(undistributableDependency);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the given object is a procedure, we want to create it locally,
|
||||||
|
* so provide that information in the error detail.
|
||||||
|
*/
|
||||||
|
if (getObjectClass(objectAddress) == OCLASS_PROC)
|
||||||
|
{
|
||||||
|
appendStringInfo(detailInfo, "\"%s\" will be created only locally",
|
||||||
|
objectDescription);
|
||||||
|
}
|
||||||
|
|
||||||
if (SupportedDependencyByCitus(undistributableDependency))
|
if (SupportedDependencyByCitus(undistributableDependency))
|
||||||
{
|
{
|
||||||
/*
|
StringInfo hintInfo = makeStringInfo();
|
||||||
* Citus can't distribute some relations as dependency, although those
|
|
||||||
* types as supported by Citus. So we can use get_rel_name directly
|
|
||||||
*
|
|
||||||
* For now the relations are the only type that is supported by Citus
|
|
||||||
* but can not be distributed as dependency, though we've added an
|
|
||||||
* explicit check below as well to not to break the logic here in case
|
|
||||||
* GetUndistributableDependency changes.
|
|
||||||
*/
|
|
||||||
if (getObjectClass(undistributableDependency) == OCLASS_CLASS)
|
|
||||||
{
|
|
||||||
char *dependentRelationName = get_rel_name(
|
|
||||||
undistributableDependency->objectId);
|
|
||||||
|
|
||||||
ereport(ERROR, (errmsg("Relation \"%s\" has dependency to a table"
|
appendStringInfo(errorInfo, "\"%s\" has dependency to \"%s\" that is not in "
|
||||||
" \"%s\" that is not in Citus' metadata",
|
"Citus' metadata",
|
||||||
tableName, dependentRelationName),
|
objectDescription,
|
||||||
errhint("Distribute dependent relation first.")));
|
dependencyDescription);
|
||||||
}
|
|
||||||
|
appendStringInfo(hintInfo, "Distribute \"%s\" first to distribute \"%s\"",
|
||||||
|
dependencyDescription,
|
||||||
|
objectDescription);
|
||||||
|
|
||||||
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
|
errorInfo->data,
|
||||||
|
strlen(detailInfo->data) == 0 ? NULL : detailInfo->data,
|
||||||
|
hintInfo->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *objectType = NULL;
|
appendStringInfo(errorInfo, "\"%s\" has dependency on unsupported "
|
||||||
#if PG_VERSION_NUM >= PG_VERSION_14
|
"object \"%s\"", objectDescription,
|
||||||
objectType = getObjectDescription(undistributableDependency, false);
|
dependencyDescription);
|
||||||
#else
|
|
||||||
objectType = getObjectDescription(undistributableDependency);
|
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
|
||||||
#endif
|
errorInfo->data,
|
||||||
ereport(ERROR, (errmsg("Relation \"%s\" has dependency on unsupported "
|
strlen(detailInfo->data) == 0 ? NULL : detailInfo->data,
|
||||||
"object \"%s\"", tableName, objectType)));
|
NULL);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -794,8 +814,8 @@ EnsureRelationDependenciesCanBeDistributed(ObjectAddress *relationAddress)
|
||||||
* GetUndistributableDependency checks whether object has any non-distributable
|
* GetUndistributableDependency checks whether object has any non-distributable
|
||||||
* dependency. If any one found, it will be returned.
|
* dependency. If any one found, it will be returned.
|
||||||
*/
|
*/
|
||||||
ObjectAddress *
|
static ObjectAddress *
|
||||||
GetUndistributableDependency(ObjectAddress *objectAddress)
|
GetUndistributableDependency(const ObjectAddress *objectAddress)
|
||||||
{
|
{
|
||||||
List *dependencies = GetAllDependenciesForObject(objectAddress);
|
List *dependencies = GetAllDependenciesForObject(objectAddress);
|
||||||
ObjectAddress *dependency = NULL;
|
ObjectAddress *dependency = NULL;
|
||||||
|
|
|
@ -267,7 +267,6 @@ extern List * PreprocessCreateFunctionStmt(Node *stmt, const char *queryString,
|
||||||
ProcessUtilityContext processUtilityContext);
|
ProcessUtilityContext processUtilityContext);
|
||||||
extern List * PostprocessCreateFunctionStmt(Node *stmt,
|
extern List * PostprocessCreateFunctionStmt(Node *stmt,
|
||||||
const char *queryString);
|
const char *queryString);
|
||||||
extern ObjectAddress * GetUndistributableDependency(ObjectAddress *functionAddress);
|
|
||||||
extern ObjectAddress CreateFunctionStmtObjectAddress(Node *stmt,
|
extern ObjectAddress CreateFunctionStmtObjectAddress(Node *stmt,
|
||||||
bool missing_ok);
|
bool missing_ok);
|
||||||
extern ObjectAddress DefineAggregateStmtObjectAddress(Node *stmt,
|
extern ObjectAddress DefineAggregateStmtObjectAddress(Node *stmt,
|
||||||
|
|
|
@ -15,14 +15,16 @@
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
#include "catalog/objectaddress.h"
|
#include "catalog/objectaddress.h"
|
||||||
|
#include "distributed/errormessage.h"
|
||||||
#include "nodes/pg_list.h"
|
#include "nodes/pg_list.h"
|
||||||
|
|
||||||
extern List * GetUniqueDependenciesList(List *objectAddressesList);
|
extern List * GetUniqueDependenciesList(List *objectAddressesList);
|
||||||
extern List * GetDependenciesForObject(const ObjectAddress *target);
|
extern List * GetDependenciesForObject(const ObjectAddress *target);
|
||||||
extern List * GetAllSupportedDependenciesForObject(const ObjectAddress *target);
|
extern List * GetAllSupportedDependenciesForObject(const ObjectAddress *target);
|
||||||
extern List * GetAllDependenciesForObject(const ObjectAddress *target);
|
extern List * GetAllDependenciesForObject(const ObjectAddress *target);
|
||||||
extern void EnsureRelationDependenciesCanBeDistributed(ObjectAddress *relationAddress);
|
extern DeferredErrorMessage * DeferErrorIfHasUnsupportedDependency(const
|
||||||
extern ObjectAddress * GetUndistributableDependency(ObjectAddress *target);
|
ObjectAddress *
|
||||||
|
objectAddress);
|
||||||
extern List * OrderObjectAddressListInDependencyOrder(List *objectAddressList);
|
extern List * OrderObjectAddressListInDependencyOrder(List *objectAddressList);
|
||||||
extern bool SupportedDependencyByCitus(const ObjectAddress *address);
|
extern bool SupportedDependencyByCitus(const ObjectAddress *address);
|
||||||
extern List * GetPgDependTuplesForDependingObjects(Oid targetObjectClassId,
|
extern List * GetPgDependTuplesForDependingObjects(Oid targetObjectClassId,
|
||||||
|
|
|
@ -1089,14 +1089,14 @@ LEFT JOIN ref_table ON TRUE;
|
||||||
create table dummy_tbl (a int);
|
create table dummy_tbl (a int);
|
||||||
create function dummy_fnc(a dummy_tbl, d double precision) RETURNS dummy_tbl
|
create function dummy_fnc(a dummy_tbl, d double precision) RETURNS dummy_tbl
|
||||||
AS $$SELECT 1;$$ LANGUAGE sql;
|
AS $$SELECT 1;$$ LANGUAGE sql;
|
||||||
WARNING: Citus can't distribute function "dummy_fnc" having dependency on non-distributed relation "dummy_tbl"
|
WARNING: "function dummy_fnc(dummy_tbl,double precision)" has dependency to "table dummy_tbl" that is not in Citus' metadata
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function dummy_fnc(dummy_tbl,double precision)" will be created only locally
|
||||||
HINT: To distribute function, distribute dependent relations first. Then, re-create the function
|
HINT: Distribute "table dummy_tbl" first to distribute "function dummy_fnc(dummy_tbl,double precision)"
|
||||||
-- should give warning and create aggregate local only
|
-- should give warning and create aggregate local only
|
||||||
create aggregate dependent_agg (float8) (stype=dummy_tbl, sfunc=dummy_fnc);
|
create aggregate dependent_agg (float8) (stype=dummy_tbl, sfunc=dummy_fnc);
|
||||||
WARNING: Citus can't distribute aggregate "dependent_agg" having dependency on non-distributed relation "dummy_tbl"
|
WARNING: "function dependent_agg(double precision)" has dependency to "table dummy_tbl" that is not in Citus' metadata
|
||||||
DETAIL: Aggregate will be created only locally
|
DETAIL: "function dependent_agg(double precision)" will be created only locally
|
||||||
HINT: To distribute aggregate, distribute dependent relations first. Then, re-create the aggregate
|
HINT: Distribute "table dummy_tbl" first to distribute "function dependent_agg(double precision)"
|
||||||
-- clear and try again with distributed table
|
-- clear and try again with distributed table
|
||||||
DROP TABLE dummy_tbl CASCADE;
|
DROP TABLE dummy_tbl CASCADE;
|
||||||
NOTICE: drop cascades to 2 other objects
|
NOTICE: drop cascades to 2 other objects
|
||||||
|
|
|
@ -560,6 +560,12 @@ SHOW citus.multi_shard_modify_mode;
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
-- Show that PG does not allow adding a circular dependency btw types
|
||||||
|
-- We added here to make sure we can catch it if PG changes it's behaviour
|
||||||
|
CREATE TYPE circ_type1 AS (a int);
|
||||||
|
CREATE TYPE circ_type2 AS (a int, b circ_type1);
|
||||||
|
ALTER TYPE circ_type1 ADD ATTRIBUTE b circ_type2;
|
||||||
|
ERROR: composite type circ_type1 cannot be made a member of itself
|
||||||
-- clear objects
|
-- clear objects
|
||||||
SET client_min_messages TO error; -- suppress cascading objects dropping
|
SET client_min_messages TO error; -- suppress cascading objects dropping
|
||||||
DROP SCHEMA type_tests CASCADE;
|
DROP SCHEMA type_tests CASCADE;
|
||||||
|
|
|
@ -134,9 +134,9 @@ BEGIN
|
||||||
return 1;
|
return 1;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
WARNING: Citus can't distribute function "func_4" having dependency on non-distributed relation "function_prop_table"
|
WARNING: "function func_4(function_prop_table)" has dependency to "table function_prop_table" that is not in Citus' metadata
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function func_4(function_prop_table)" will be created only locally
|
||||||
HINT: To distribute function, distribute dependent relations first. Then, re-create the function
|
HINT: Distribute "table function_prop_table" first to distribute "function func_4(function_prop_table)"
|
||||||
CREATE OR REPLACE FUNCTION func_5(param_1 int)
|
CREATE OR REPLACE FUNCTION func_5(param_1 int)
|
||||||
RETURNS function_prop_table
|
RETURNS function_prop_table
|
||||||
LANGUAGE plpgsql AS
|
LANGUAGE plpgsql AS
|
||||||
|
@ -145,9 +145,9 @@ BEGIN
|
||||||
return 1;
|
return 1;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
WARNING: Citus can't distribute function "func_5" having dependency on non-distributed relation "function_prop_table"
|
WARNING: "function func_5(integer)" has dependency to "table function_prop_table" that is not in Citus' metadata
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function func_5(integer)" will be created only locally
|
||||||
HINT: To distribute function, distribute dependent relations first. Then, re-create the function
|
HINT: Distribute "table function_prop_table" first to distribute "function func_5(integer)"
|
||||||
-- Functions can be created with distributed table dependency
|
-- Functions can be created with distributed table dependency
|
||||||
SELECT create_distributed_table('function_prop_table', 'a');
|
SELECT create_distributed_table('function_prop_table', 'a');
|
||||||
create_distributed_table
|
create_distributed_table
|
||||||
|
@ -186,8 +186,8 @@ BEGIN
|
||||||
return 1;
|
return 1;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
WARNING: Citus can't distribute functions having dependency on unsupported object of type "view"
|
WARNING: "function func_7(function_prop_view)" has dependency on unsupported object "view function_prop_view"
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function func_7(function_prop_view)" will be created only locally
|
||||||
CREATE OR REPLACE FUNCTION func_8(param_1 int)
|
CREATE OR REPLACE FUNCTION func_8(param_1 int)
|
||||||
RETURNS function_prop_view
|
RETURNS function_prop_view
|
||||||
LANGUAGE plpgsql AS
|
LANGUAGE plpgsql AS
|
||||||
|
@ -196,8 +196,8 @@ BEGIN
|
||||||
return 1;
|
return 1;
|
||||||
END;
|
END;
|
||||||
$$;
|
$$;
|
||||||
WARNING: Citus can't distribute functions having dependency on unsupported object of type "view"
|
WARNING: "function func_8(integer)" has dependency on unsupported object "view function_prop_view"
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function func_8(integer)" will be created only locally
|
||||||
-- Check within transaction
|
-- Check within transaction
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE TYPE type_in_transaction AS (a int, b int);
|
CREATE TYPE type_in_transaction AS (a int, b int);
|
||||||
|
@ -435,8 +435,8 @@ BEGIN;
|
||||||
CREATE TABLE table_to_prop_func_3(id int, col_1 int default func_in_transaction_3(NULL::non_dist_table));
|
CREATE TABLE table_to_prop_func_3(id int, col_1 int default func_in_transaction_3(NULL::non_dist_table));
|
||||||
-- It should error out as there is a non-distributed table dependency
|
-- It should error out as there is a non-distributed table dependency
|
||||||
SELECT create_distributed_table('table_to_prop_func_3','id');
|
SELECT create_distributed_table('table_to_prop_func_3','id');
|
||||||
ERROR: Relation "table_to_prop_func_3" has dependency to a table "non_dist_table" that is not in Citus' metadata
|
ERROR: "table table_to_prop_func_3" has dependency to "table non_dist_table" that is not in Citus' metadata
|
||||||
HINT: Distribute dependent relation first.
|
HINT: Distribute "table non_dist_table" first to distribute "table table_to_prop_func_3"
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- Adding a column with default value should propagate the function
|
-- Adding a column with default value should propagate the function
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -497,8 +497,8 @@ BEGIN;
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER TABLE table_to_dist ADD COLUMN col_1 int default function_propagation_schema.non_dist_func(NULL::non_dist_table_for_function);
|
ALTER TABLE table_to_dist ADD COLUMN col_1 int default function_propagation_schema.non_dist_func(NULL::non_dist_table_for_function);
|
||||||
ERROR: Relation "table_to_dist" has dependency to a table "non_dist_table_for_function" that is not in Citus' metadata
|
ERROR: "table table_to_dist" has dependency to "table non_dist_table_for_function" that is not in Citus' metadata
|
||||||
HINT: Distribute dependent relation first.
|
HINT: Distribute "table non_dist_table_for_function" first to distribute "table table_to_dist"
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- Adding multiple columns with default values should propagate the function
|
-- Adding multiple columns with default values should propagate the function
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -723,8 +723,8 @@ BEGIN;
|
||||||
CREATE TABLE table_to_prop_func_9(id int, col_1 int check (func_in_transaction_11(col_1, NULL::local_table_for_const)));
|
CREATE TABLE table_to_prop_func_9(id int, col_1 int check (func_in_transaction_11(col_1, NULL::local_table_for_const)));
|
||||||
-- It should error out since there is non-distributed table dependency exists
|
-- It should error out since there is non-distributed table dependency exists
|
||||||
SELECT create_distributed_table('table_to_prop_func_9', 'id');
|
SELECT create_distributed_table('table_to_prop_func_9', 'id');
|
||||||
ERROR: Relation "table_to_prop_func_9" has dependency to a table "local_table_for_const" that is not in Citus' metadata
|
ERROR: "table table_to_prop_func_9" has dependency to "table local_table_for_const" that is not in Citus' metadata
|
||||||
HINT: Distribute dependent relation first.
|
HINT: Distribute "table local_table_for_const" first to distribute "table table_to_prop_func_9"
|
||||||
COMMIT;
|
COMMIT;
|
||||||
-- Show that function as a part of generated always is supporte
|
-- Show that function as a part of generated always is supporte
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -1188,6 +1188,95 @@ SELECT distribution_argument_index, colocationid, force_delegation FROM pg_catal
|
||||||
| |
|
| |
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
-- Show that causing circular dependency via functions and default values are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep(id int);
|
||||||
|
select create_distributed_table('table_1_for_circ_dep','id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_1_for_circ_dep(col_1 table_1_for_circ_dep)
|
||||||
|
RETURNS int
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return 1;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
CREATE TABLE table_2_for_circ_dep(id int, col_2 int default func_1_for_circ_dep(NULL::table_1_for_circ_dep));
|
||||||
|
select create_distributed_table('table_2_for_circ_dep','id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_2_for_circ_dep(col_3 table_2_for_circ_dep)
|
||||||
|
RETURNS int
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return 1;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
ALTER TABLE table_1_for_circ_dep ADD COLUMN col_2 int default func_2_for_circ_dep(NULL::table_2_for_circ_dep);
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
DETAIL: "table table_1_for_circ_dep" circularly depends itself, resolve circular dependency first
|
||||||
|
-- Show that causing circular dependency via functions and constraints are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep_2(id int, col_1 int);
|
||||||
|
select create_distributed_table('table_1_for_circ_dep_2','id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_1_for_circ_dep_2(param_1 int, param_2 table_1_for_circ_dep_2)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
CREATE TABLE table_2_for_circ_dep_2(id int, col_1 int check (func_1_for_circ_dep_2(col_1, NULL::table_1_for_circ_dep_2)));
|
||||||
|
select create_distributed_table('table_2_for_circ_dep_2','id');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_2_for_circ_dep_2(param_1 int, param_2 table_2_for_circ_dep_2)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
ALTER TABLE table_1_for_circ_dep_2 ADD CONSTRAINT check_const_for_circ check (func_2_for_circ_dep_2(col_1, NULL::table_2_for_circ_dep_2));
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
DETAIL: "table table_1_for_circ_dep_2" circularly depends itself, resolve circular dependency first
|
||||||
|
-- Show that causing circular dependency via functions and create_distributed_table are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep_3(id int, col_1 int);
|
||||||
|
CREATE OR REPLACE FUNCTION func_for_circ_dep_3(param_1 int, param_2 table_1_for_circ_dep_3)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
WARNING: "function func_for_circ_dep_3(integer,table_1_for_circ_dep_3)" has dependency to "table table_1_for_circ_dep_3" that is not in Citus' metadata
|
||||||
|
DETAIL: "function func_for_circ_dep_3(integer,table_1_for_circ_dep_3)" will be created only locally
|
||||||
|
HINT: Distribute "table table_1_for_circ_dep_3" first to distribute "function func_for_circ_dep_3(integer,table_1_for_circ_dep_3)"
|
||||||
|
CREATE TABLE table_2_for_circ_dep_3(id int, col_1 int check (func_for_circ_dep_3(col_1, NULL::table_1_for_circ_dep_3)));
|
||||||
|
ALTER TABLE table_1_for_circ_dep_3 ADD COLUMN col_2 table_2_for_circ_dep_3;
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
SELECT create_distributed_table('table_1_for_circ_dep_3','id');
|
||||||
|
ERROR: Citus can not handle circular dependencies between distributed objects
|
||||||
|
DETAIL: "table table_1_for_circ_dep_3" circularly depends itself, resolve circular dependency first
|
||||||
RESET search_path;
|
RESET search_path;
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA function_propagation_schema CASCADE;
|
DROP SCHEMA function_propagation_schema CASCADE;
|
||||||
|
|
|
@ -71,7 +71,14 @@ $$);
|
||||||
(localhost,57638,t,"CREATE FOREIGN DATA WRAPPER")
|
(localhost,57638,t,"CREATE FOREIGN DATA WRAPPER")
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
-- Since we are assuming fdw should be part of the extension, add it manually.
|
||||||
|
ALTER EXTENSION citus ADD FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
|
NOTICE: Citus does not propagate adding/dropping member objects
|
||||||
|
HINT: You can add/drop the member objects on the workers as well.
|
||||||
CREATE SERVER fake_fdw_server_1 FOREIGN DATA WRAPPER fake_fdw_1;
|
CREATE SERVER fake_fdw_server_1 FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
|
ALTER EXTENSION citus DROP FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
|
NOTICE: Citus does not propagate adding/dropping member objects
|
||||||
|
HINT: You can add/drop the member objects on the workers as well.
|
||||||
CREATE FOREIGN TABLE foreign_table (
|
CREATE FOREIGN TABLE foreign_table (
|
||||||
key int,
|
key int,
|
||||||
value text
|
value text
|
||||||
|
|
|
@ -8,4 +8,11 @@ RETURNS fdw_handler
|
||||||
AS 'citus'
|
AS 'citus'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler;
|
CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler;
|
||||||
|
-- Since we are assuming fdw should be part of the extension, add and drop it manually.
|
||||||
|
ALTER EXTENSION citus ADD FOREIGN DATA WRAPPER fake_fdw;
|
||||||
|
NOTICE: Citus does not propagate adding/dropping member objects
|
||||||
|
HINT: You can add/drop the member objects on the workers as well.
|
||||||
CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw;
|
CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw;
|
||||||
|
ALTER EXTENSION citus DROP FOREIGN DATA WRAPPER fake_fdw;
|
||||||
|
NOTICE: Citus does not propagate adding/dropping member objects
|
||||||
|
HINT: You can add/drop the member objects on the workers as well.
|
||||||
|
|
|
@ -145,13 +145,13 @@ CREATE TYPE myvarchar;
|
||||||
CREATE FUNCTION myvarcharin(cstring, oid, integer) RETURNS myvarchar
|
CREATE FUNCTION myvarcharin(cstring, oid, integer) RETURNS myvarchar
|
||||||
LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharin';
|
LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharin';
|
||||||
NOTICE: return type myvarchar is only a shell
|
NOTICE: return type myvarchar is only a shell
|
||||||
WARNING: Citus can't distribute functions having dependency on unsupported object of type "type"
|
WARNING: "function myvarcharin(cstring,oid,integer)" has dependency on unsupported object "type myvarchar"
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function myvarcharin(cstring,oid,integer)" will be created only locally
|
||||||
CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring
|
CREATE FUNCTION myvarcharout(myvarchar) RETURNS cstring
|
||||||
LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharout';
|
LANGUAGE internal IMMUTABLE PARALLEL SAFE STRICT AS 'varcharout';
|
||||||
NOTICE: argument type myvarchar is only a shell
|
NOTICE: argument type myvarchar is only a shell
|
||||||
WARNING: Citus can't distribute functions having dependency on unsupported object of type "type"
|
WARNING: "function myvarcharout(myvarchar)" has dependency on unsupported object "type myvarchar"
|
||||||
DETAIL: Function will be created only locally
|
DETAIL: "function myvarcharout(myvarchar)" will be created only locally
|
||||||
CREATE TYPE myvarchar (
|
CREATE TYPE myvarchar (
|
||||||
input = myvarcharin,
|
input = myvarcharin,
|
||||||
output = myvarcharout,
|
output = myvarcharout,
|
||||||
|
@ -164,7 +164,7 @@ CREATE TABLE my_table (a int, b myvarchar);
|
||||||
-- """Add ALTER TYPE options useful for extensions,
|
-- """Add ALTER TYPE options useful for extensions,
|
||||||
-- like TOAST and I/O functions control (Tomas Vondra, Tom Lane)"""
|
-- like TOAST and I/O functions control (Tomas Vondra, Tom Lane)"""
|
||||||
SELECT create_distributed_table('my_table', 'a');
|
SELECT create_distributed_table('my_table', 'a');
|
||||||
ERROR: Relation "my_table" has dependency on unsupported object "type myvarchar"
|
ERROR: "table my_table" has dependency on unsupported object "type myvarchar"
|
||||||
CREATE TABLE test_table(a int, b tsvector);
|
CREATE TABLE test_table(a int, b tsvector);
|
||||||
SELECT create_distributed_table('test_table', 'a');
|
SELECT create_distributed_table('test_table', 'a');
|
||||||
create_distributed_table
|
create_distributed_table
|
||||||
|
|
|
@ -329,6 +329,12 @@ SELECT create_distributed_table('immediate_table', 'a');
|
||||||
SHOW citus.multi_shard_modify_mode;
|
SHOW citus.multi_shard_modify_mode;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
|
-- Show that PG does not allow adding a circular dependency btw types
|
||||||
|
-- We added here to make sure we can catch it if PG changes it's behaviour
|
||||||
|
CREATE TYPE circ_type1 AS (a int);
|
||||||
|
CREATE TYPE circ_type2 AS (a int, b circ_type1);
|
||||||
|
ALTER TYPE circ_type1 ADD ATTRIBUTE b circ_type2;
|
||||||
|
|
||||||
-- clear objects
|
-- clear objects
|
||||||
SET client_min_messages TO error; -- suppress cascading objects dropping
|
SET client_min_messages TO error; -- suppress cascading objects dropping
|
||||||
DROP SCHEMA type_tests CASCADE;
|
DROP SCHEMA type_tests CASCADE;
|
||||||
|
|
|
@ -756,6 +756,82 @@ SELECT create_distributed_function('func_to_colocate(int)');
|
||||||
-- show that the pg_dist_object fields are gone
|
-- show that the pg_dist_object fields are gone
|
||||||
SELECT distribution_argument_index, colocationid, force_delegation FROM pg_catalog.pg_dist_object WHERE objid = 'func_to_colocate'::regproc;
|
SELECT distribution_argument_index, colocationid, force_delegation FROM pg_catalog.pg_dist_object WHERE objid = 'func_to_colocate'::regproc;
|
||||||
|
|
||||||
|
|
||||||
|
-- Show that causing circular dependency via functions and default values are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep(id int);
|
||||||
|
select create_distributed_table('table_1_for_circ_dep','id');
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_1_for_circ_dep(col_1 table_1_for_circ_dep)
|
||||||
|
RETURNS int
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return 1;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE TABLE table_2_for_circ_dep(id int, col_2 int default func_1_for_circ_dep(NULL::table_1_for_circ_dep));
|
||||||
|
select create_distributed_table('table_2_for_circ_dep','id');
|
||||||
|
CREATE OR REPLACE FUNCTION func_2_for_circ_dep(col_3 table_2_for_circ_dep)
|
||||||
|
RETURNS int
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return 1;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
ALTER TABLE table_1_for_circ_dep ADD COLUMN col_2 int default func_2_for_circ_dep(NULL::table_2_for_circ_dep);
|
||||||
|
|
||||||
|
|
||||||
|
-- Show that causing circular dependency via functions and constraints are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep_2(id int, col_1 int);
|
||||||
|
select create_distributed_table('table_1_for_circ_dep_2','id');
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_1_for_circ_dep_2(param_1 int, param_2 table_1_for_circ_dep_2)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE TABLE table_2_for_circ_dep_2(id int, col_1 int check (func_1_for_circ_dep_2(col_1, NULL::table_1_for_circ_dep_2)));
|
||||||
|
|
||||||
|
select create_distributed_table('table_2_for_circ_dep_2','id');
|
||||||
|
CREATE OR REPLACE FUNCTION func_2_for_circ_dep_2(param_1 int, param_2 table_2_for_circ_dep_2)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
ALTER TABLE table_1_for_circ_dep_2 ADD CONSTRAINT check_const_for_circ check (func_2_for_circ_dep_2(col_1, NULL::table_2_for_circ_dep_2));
|
||||||
|
|
||||||
|
|
||||||
|
-- Show that causing circular dependency via functions and create_distributed_table are not allowed
|
||||||
|
CREATE TABLE table_1_for_circ_dep_3(id int, col_1 int);
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION func_for_circ_dep_3(param_1 int, param_2 table_1_for_circ_dep_3)
|
||||||
|
RETURNS boolean
|
||||||
|
LANGUAGE plpgsql AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
return param_1 > 5;
|
||||||
|
END;
|
||||||
|
$$;
|
||||||
|
|
||||||
|
CREATE TABLE table_2_for_circ_dep_3(id int, col_1 int check (func_for_circ_dep_3(col_1, NULL::table_1_for_circ_dep_3)));
|
||||||
|
ALTER TABLE table_1_for_circ_dep_3 ADD COLUMN col_2 table_2_for_circ_dep_3;
|
||||||
|
|
||||||
|
-- It should error out due to circular dependency
|
||||||
|
SELECT create_distributed_table('table_1_for_circ_dep_3','id');
|
||||||
|
|
||||||
RESET search_path;
|
RESET search_path;
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA function_propagation_schema CASCADE;
|
DROP SCHEMA function_propagation_schema CASCADE;
|
||||||
|
|
|
@ -43,7 +43,10 @@ CREATE FOREIGN DATA WRAPPER fake_fdw_1 HANDLER fake_fdw_handler;
|
||||||
SELECT run_command_on_workers($$
|
SELECT run_command_on_workers($$
|
||||||
CREATE FOREIGN DATA WRAPPER fake_fdw_1 HANDLER fake_fdw_handler;
|
CREATE FOREIGN DATA WRAPPER fake_fdw_1 HANDLER fake_fdw_handler;
|
||||||
$$);
|
$$);
|
||||||
|
-- Since we are assuming fdw should be part of the extension, add it manually.
|
||||||
|
ALTER EXTENSION citus ADD FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
CREATE SERVER fake_fdw_server_1 FOREIGN DATA WRAPPER fake_fdw_1;
|
CREATE SERVER fake_fdw_server_1 FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
|
ALTER EXTENSION citus DROP FOREIGN DATA WRAPPER fake_fdw_1;
|
||||||
|
|
||||||
CREATE FOREIGN TABLE foreign_table (
|
CREATE FOREIGN TABLE foreign_table (
|
||||||
key int,
|
key int,
|
||||||
|
|
|
@ -13,4 +13,8 @@ AS 'citus'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
||||||
CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler;
|
CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler;
|
||||||
|
|
||||||
|
-- Since we are assuming fdw should be part of the extension, add and drop it manually.
|
||||||
|
ALTER EXTENSION citus ADD FOREIGN DATA WRAPPER fake_fdw;
|
||||||
CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw;
|
CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw;
|
||||||
|
ALTER EXTENSION citus DROP FOREIGN DATA WRAPPER fake_fdw;
|
||||||
|
|
Loading…
Reference in New Issue