citus/src/backend/distributed/deparser/qualify_statistics_stmt.c

232 lines
5.9 KiB
C

/*-------------------------------------------------------------------------
*
* qualify_statistics_stmt.c
* Functions specialized in fully qualifying all statistics statements.
* These functions are dispatched from qualify.c
*
* Goal would be that the deparser functions for these statements can
* serialize the statement without any external lookups.
*
* Copyright (c) Citus Data, Inc.
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "catalog/namespace.h"
#include "catalog/pg_statistic_ext.h"
#include "distributed/commands.h"
#include "distributed/deparser.h"
#include "distributed/listutils.h"
#include "nodes/parsenodes.h"
#include "nodes/value.h"
#include "utils/syscache.h"
#include "utils/lsyscache.h"
#include "utils/rel.h"
#include "utils/relcache.h"
static Oid GetStatsNamespaceOid(Oid statsOid);
void
QualifyCreateStatisticsStmt(Node *node)
{
CreateStatsStmt *stmt = castNode(CreateStatsStmt, node);
RangeVar *relation = (RangeVar *) linitial(stmt->relations);
if (relation->schemaname == NULL)
{
Oid tableOid = RelnameGetRelid(relation->relname);
Oid schemaOid = get_rel_namespace(tableOid);
relation->schemaname = get_namespace_name(schemaOid);
}
if (list_length(stmt->defnames) < 1)
{
/* no name to qualify */
return;
}
RangeVar *stat = makeRangeVarFromNameList(stmt->defnames);
if (stat->schemaname == NULL)
{
Oid schemaOid = RangeVarGetCreationNamespace(stat);
stat->schemaname = get_namespace_name(schemaOid);
stmt->defnames = MakeNameListFromRangeVar(stat);
}
}
/*
* QualifyDropStatisticsStmt qualifies DropStmt's with schema name for
* DROP STATISTICS statements.
*/
void
QualifyDropStatisticsStmt(Node *node)
{
DropStmt *dropStatisticsStmt = castNode(DropStmt, node);
Assert(dropStatisticsStmt->removeType == OBJECT_STATISTIC_EXT);
List *objectNameListWithSchema = NIL;
List *objectNameList = NULL;
foreach_ptr(objectNameList, dropStatisticsStmt->objects)
{
RangeVar *stat = makeRangeVarFromNameList(objectNameList);
if (stat->schemaname == NULL)
{
Oid statsOid = get_statistics_object_oid(objectNameList,
dropStatisticsStmt->missing_ok);
if (OidIsValid(statsOid))
{
Oid schemaOid = GetStatsNamespaceOid(statsOid);
stat->schemaname = get_namespace_name(schemaOid);
}
}
objectNameListWithSchema = lappend(objectNameListWithSchema,
MakeNameListFromRangeVar(stat));
}
dropStatisticsStmt->objects = objectNameListWithSchema;
}
/*
* QualifyAlterStatisticsRenameStmt qualifies RenameStmt's with schema name for
* ALTER STATISTICS RENAME statements.
*/
void
QualifyAlterStatisticsRenameStmt(Node *node)
{
RenameStmt *renameStmt = castNode(RenameStmt, node);
Assert(renameStmt->renameType == OBJECT_STATISTIC_EXT);
List *nameList = (List *) renameStmt->object;
if (list_length(nameList) == 1)
{
RangeVar *stat = makeRangeVarFromNameList(nameList);
Oid statsOid = get_statistics_object_oid(nameList, renameStmt->missing_ok);
if (!OidIsValid(statsOid))
{
return;
}
Oid schemaOid = GetStatsNamespaceOid(statsOid);
stat->schemaname = get_namespace_name(schemaOid);
renameStmt->object = (Node *) MakeNameListFromRangeVar(stat);
}
}
/*
* QualifyAlterStatisticsSchemaStmt qualifies AlterObjectSchemaStmt's with schema name for
* ALTER STATISTICS RENAME statements.
*/
void
QualifyAlterStatisticsSchemaStmt(Node *node)
{
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
List *nameList = (List *) stmt->object;
if (list_length(nameList) == 1)
{
RangeVar *stat = makeRangeVarFromNameList(nameList);
Oid statsOid = get_statistics_object_oid(nameList, stmt->missing_ok);
if (!OidIsValid(statsOid))
{
return;
}
Oid schemaOid = GetStatsNamespaceOid(statsOid);
stat->schemaname = get_namespace_name(schemaOid);
stmt->object = (Node *) MakeNameListFromRangeVar(stat);
}
}
/*
* QualifyAlterStatisticsStmt qualifies AlterStatsStmt's with schema name for
* ALTER STATISTICS .. SET STATISTICS statements.
*/
void
QualifyAlterStatisticsStmt(Node *node)
{
AlterStatsStmt *stmt = castNode(AlterStatsStmt, node);
if (list_length(stmt->defnames) == 1)
{
RangeVar *stat = makeRangeVarFromNameList(stmt->defnames);
Oid statsOid = get_statistics_object_oid(stmt->defnames, stmt->missing_ok);
if (!OidIsValid(statsOid))
{
return;
}
Oid schemaOid = GetStatsNamespaceOid(statsOid);
stat->schemaname = get_namespace_name(schemaOid);
stmt->defnames = MakeNameListFromRangeVar(stat);
}
}
/*
* QualifyAlterStatisticsOwnerStmt qualifies AlterOwnerStmt's with schema
* name for ALTER STATISTICS .. OWNER TO statements.
*/
void
QualifyAlterStatisticsOwnerStmt(Node *node)
{
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
List *nameList = (List *) stmt->object;
if (list_length(nameList) == 1)
{
RangeVar *stat = makeRangeVarFromNameList(nameList);
Oid statsOid = get_statistics_object_oid(nameList, /* missing_ok */ true);
if (!OidIsValid(statsOid))
{
return;
}
Oid schemaOid = GetStatsNamespaceOid(statsOid);
stat->schemaname = get_namespace_name(schemaOid);
stmt->object = (Node *) MakeNameListFromRangeVar(stat);
}
}
/*
* GetStatsNamespaceOid takes the id of a Statistics object and returns
* the id of the schema that the statistics object belongs to.
* Errors out if the stats object is not found.
*/
static Oid
GetStatsNamespaceOid(Oid statsOid)
{
HeapTuple heapTuple = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid));
if (!HeapTupleIsValid(heapTuple))
{
ereport(ERROR, (errmsg("cache lookup failed for statistics "
"object with oid %u", statsOid)));
}
FormData_pg_statistic_ext *statisticsForm =
(FormData_pg_statistic_ext *) GETSTRUCT(heapTuple);
Oid result = statisticsForm->stxnamespace;
ReleaseSysCache(heapTuple);
return result;
}