mirror of https://github.com/citusdata/citus.git
108 lines
3.3 KiB
C
108 lines
3.3 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* aggregate.c
|
|
* Commands for distributing AGGREGATE statements.
|
|
*
|
|
* Copyright (c) Citus Data, Inc.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "distributed/commands.h"
|
|
#include "distributed/commands/utility_hook.h"
|
|
#include "distributed/deparser.h"
|
|
#include "distributed/listutils.h"
|
|
#include "distributed/metadata/dependency.h"
|
|
#include "distributed/metadata_sync.h"
|
|
#include "distributed/metadata/distobject.h"
|
|
#include "distributed/multi_executor.h"
|
|
#include "nodes/parsenodes.h"
|
|
#include "utils/lsyscache.h"
|
|
|
|
|
|
/*
|
|
* PostprocessDefineAggregateStmt actually creates the plan we need to execute for
|
|
* aggregate propagation.
|
|
* This is the downside of using the locally created aggregate to get the sql statement.
|
|
*
|
|
* If the aggregate depends on any non-distributed relation, Citus can not distribute it.
|
|
* In order to not to prevent users from creating local aggregates on the coordinator,
|
|
* a WARNING message will be sent to the user about the case instead of erroring out.
|
|
*
|
|
* Besides creating the plan we also make sure all (new) dependencies of the aggregate
|
|
* are created on all nodes.
|
|
*/
|
|
List *
|
|
PostprocessDefineAggregateStmt(Node *node, const char *queryString)
|
|
{
|
|
QualifyTreeNode((Node *) node);
|
|
|
|
DefineStmt *stmt = castNode(DefineStmt, node);
|
|
|
|
if (!ShouldPropagate())
|
|
{
|
|
return NIL;
|
|
}
|
|
|
|
if (!ShouldPropagateCreateInCoordinatedTransction())
|
|
{
|
|
return NIL;
|
|
}
|
|
|
|
ObjectAddress address = GetObjectAddressFromParseTree((Node *) stmt, false);
|
|
|
|
EnsureCoordinator();
|
|
|
|
EnsureSequentialMode(OBJECT_AGGREGATE);
|
|
|
|
ObjectAddress *undistributableDependency = GetUndistributableDependency(
|
|
&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 "
|
|
"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;
|
|
#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;
|
|
}
|
|
|
|
EnsureDependenciesExistOnAllNodes(&address);
|
|
|
|
List *commands = CreateFunctionDDLCommandsIdempotent(&address);
|
|
|
|
commands = lcons(DISABLE_DDL_PROPAGATION, commands);
|
|
commands = lappend(commands, ENABLE_DDL_PROPAGATION);
|
|
|
|
return NodeDDLTaskList(NON_COORDINATOR_NODES, commands);
|
|
}
|