mirror of https://github.com/citusdata/citus.git
Merge pull request #4444 from citusdata/alter-statistics-propagation
Propagate alter statisticspull/4419/head
commit
299d3fcbc5
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "distributed/commands.h"
|
#include "distributed/commands.h"
|
||||||
#include "distributed/deparser.h"
|
#include "distributed/deparser.h"
|
||||||
|
#include "distributed/pg_version_constants.h"
|
||||||
|
|
||||||
static DistributeObjectOps NoDistributeOps = {
|
static DistributeObjectOps NoDistributeOps = {
|
||||||
.deparse = NULL,
|
.deparse = NULL,
|
||||||
|
@ -414,6 +415,29 @@ static DistributeObjectOps Schema_Rename = {
|
||||||
.postprocess = NULL,
|
.postprocess = NULL,
|
||||||
.address = AlterSchemaRenameStmtObjectAddress,
|
.address = AlterSchemaRenameStmtObjectAddress,
|
||||||
};
|
};
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
static DistributeObjectOps Statistics_Alter = {
|
||||||
|
.deparse = DeparseAlterStatisticsStmt,
|
||||||
|
.qualify = QualifyAlterStatisticsStmt,
|
||||||
|
.preprocess = PreprocessAlterStatisticsStmt,
|
||||||
|
.postprocess = NULL,
|
||||||
|
.address = NULL,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
static DistributeObjectOps Statistics_AlterObjectSchema = {
|
||||||
|
.deparse = DeparseAlterStatisticsSchemaStmt,
|
||||||
|
.qualify = QualifyAlterStatisticsSchemaStmt,
|
||||||
|
.preprocess = PreprocessAlterStatisticsSchemaStmt,
|
||||||
|
.postprocess = PostprocessAlterStatisticsSchemaStmt,
|
||||||
|
.address = AlterStatisticsSchemaStmtObjectAddress,
|
||||||
|
};
|
||||||
|
static DistributeObjectOps Statistics_AlterOwner = {
|
||||||
|
.deparse = DeparseAlterStatisticsOwnerStmt,
|
||||||
|
.qualify = QualifyAlterStatisticsOwnerStmt,
|
||||||
|
.preprocess = PreprocessAlterStatisticsOwnerStmt,
|
||||||
|
.postprocess = NULL,
|
||||||
|
.address = NULL,
|
||||||
|
};
|
||||||
static DistributeObjectOps Statistics_Drop = {
|
static DistributeObjectOps Statistics_Drop = {
|
||||||
.deparse = NULL,
|
.deparse = NULL,
|
||||||
.qualify = QualifyDropStatisticsStmt,
|
.qualify = QualifyDropStatisticsStmt,
|
||||||
|
@ -421,6 +445,13 @@ static DistributeObjectOps Statistics_Drop = {
|
||||||
.postprocess = NULL,
|
.postprocess = NULL,
|
||||||
.address = NULL,
|
.address = NULL,
|
||||||
};
|
};
|
||||||
|
static DistributeObjectOps Statistics_Rename = {
|
||||||
|
.deparse = DeparseAlterStatisticsRenameStmt,
|
||||||
|
.qualify = QualifyAlterStatisticsRenameStmt,
|
||||||
|
.preprocess = PreprocessAlterStatisticsRenameStmt,
|
||||||
|
.postprocess = NULL,
|
||||||
|
.address = NULL,
|
||||||
|
};
|
||||||
static DistributeObjectOps Table_AlterTable = {
|
static DistributeObjectOps Table_AlterTable = {
|
||||||
.deparse = NULL,
|
.deparse = NULL,
|
||||||
.qualify = NULL,
|
.qualify = NULL,
|
||||||
|
@ -590,6 +621,11 @@ GetDistributeObjectOps(Node *node)
|
||||||
return &Routine_AlterObjectSchema;
|
return &Routine_AlterObjectSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OBJECT_STATISTIC_EXT:
|
||||||
|
{
|
||||||
|
return &Statistics_AlterObjectSchema;
|
||||||
|
}
|
||||||
|
|
||||||
case OBJECT_TABLE:
|
case OBJECT_TABLE:
|
||||||
{
|
{
|
||||||
return &Table_AlterObjectSchema;
|
return &Table_AlterObjectSchema;
|
||||||
|
@ -637,6 +673,11 @@ GetDistributeObjectOps(Node *node)
|
||||||
return &Routine_AlterOwner;
|
return &Routine_AlterOwner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OBJECT_STATISTIC_EXT:
|
||||||
|
{
|
||||||
|
return &Statistics_AlterOwner;
|
||||||
|
}
|
||||||
|
|
||||||
case OBJECT_TYPE:
|
case OBJECT_TYPE:
|
||||||
{
|
{
|
||||||
return &Type_AlterOwner;
|
return &Type_AlterOwner;
|
||||||
|
@ -664,6 +705,13 @@ GetDistributeObjectOps(Node *node)
|
||||||
return &Any_AlterRoleSet;
|
return &Any_AlterRoleSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
case T_AlterStatsStmt:
|
||||||
|
{
|
||||||
|
return &Statistics_Alter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
case T_AlterTableStmt:
|
case T_AlterTableStmt:
|
||||||
{
|
{
|
||||||
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
|
||||||
|
@ -907,6 +955,11 @@ GetDistributeObjectOps(Node *node)
|
||||||
return &Schema_Rename;
|
return &Schema_Rename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OBJECT_STATISTIC_EXT:
|
||||||
|
{
|
||||||
|
return &Statistics_Rename;
|
||||||
|
}
|
||||||
|
|
||||||
case OBJECT_TYPE:
|
case OBJECT_TYPE:
|
||||||
{
|
{
|
||||||
return &Type_Rename;
|
return &Type_Rename;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "distributed/relation_access_tracking.h"
|
#include "distributed/relation_access_tracking.h"
|
||||||
#include "distributed/resource_lock.h"
|
#include "distributed/resource_lock.h"
|
||||||
#include "distributed/worker_transaction.h"
|
#include "distributed/worker_transaction.h"
|
||||||
|
#include "miscadmin.h"
|
||||||
#include "utils/builtins.h"
|
#include "utils/builtins.h"
|
||||||
#include "utils/fmgroids.h"
|
#include "utils/fmgroids.h"
|
||||||
#include "utils/lsyscache.h"
|
#include "utils/lsyscache.h"
|
||||||
|
@ -45,7 +46,10 @@
|
||||||
|
|
||||||
static List * GetExplicitStatisticsIdList(Oid relationId);
|
static List * GetExplicitStatisticsIdList(Oid relationId);
|
||||||
static Oid GetRelIdByStatsOid(Oid statsOid);
|
static Oid GetRelIdByStatsOid(Oid statsOid);
|
||||||
|
static char * CreateAlterCommandIfOwnerNotDefault(Oid statsOid);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
static char * CreateAlterCommandIfTargetNotDefault(Oid statsOid);
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PreprocessCreateStatisticsStmt is called during the planning phase for
|
* PreprocessCreateStatisticsStmt is called during the planning phase for
|
||||||
|
@ -190,6 +194,213 @@ PreprocessDropStatisticsStmt(Node *node, const char *queryString)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PreprocessAlterStatisticsRenameStmt is called during the planning phase for
|
||||||
|
* ALTER STATISTICS RENAME.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString)
|
||||||
|
{
|
||||||
|
RenameStmt *renameStmt = castNode(RenameStmt, node);
|
||||||
|
Assert(renameStmt->renameType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
Oid statsOid = get_statistics_object_oid((List *) renameStmt->object, false);
|
||||||
|
Oid relationId = GetRelIdByStatsOid(statsOid);
|
||||||
|
|
||||||
|
if (!IsCitusTable(relationId) || !ShouldPropagate())
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureCoordinator();
|
||||||
|
|
||||||
|
QualifyTreeNode((Node *) renameStmt);
|
||||||
|
|
||||||
|
char *ddlCommand = DeparseTreeNode((Node *) renameStmt);
|
||||||
|
|
||||||
|
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
|
||||||
|
|
||||||
|
ddlJob->targetRelationId = relationId;
|
||||||
|
ddlJob->concurrentIndexCmd = false;
|
||||||
|
ddlJob->startNewTransaction = false;
|
||||||
|
ddlJob->commandString = ddlCommand;
|
||||||
|
ddlJob->taskList = DDLTaskList(relationId, ddlCommand);
|
||||||
|
|
||||||
|
List *ddlJobs = list_make1(ddlJob);
|
||||||
|
|
||||||
|
return ddlJobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PreprocessAlterStatisticsSchemaStmt is called during the planning phase for
|
||||||
|
* ALTER STATISTICS SET SCHEMA.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString)
|
||||||
|
{
|
||||||
|
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||||
|
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
Oid statsOid = get_statistics_object_oid((List *) stmt->object, false);
|
||||||
|
Oid relationId = GetRelIdByStatsOid(statsOid);
|
||||||
|
|
||||||
|
if (!IsCitusTable(relationId) || !ShouldPropagate())
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureCoordinator();
|
||||||
|
|
||||||
|
QualifyTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
char *ddlCommand = DeparseTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
|
||||||
|
|
||||||
|
ddlJob->targetRelationId = relationId;
|
||||||
|
ddlJob->concurrentIndexCmd = false;
|
||||||
|
ddlJob->startNewTransaction = false;
|
||||||
|
ddlJob->commandString = ddlCommand;
|
||||||
|
ddlJob->taskList = DDLTaskList(relationId, ddlCommand);
|
||||||
|
|
||||||
|
List *ddlJobs = list_make1(ddlJob);
|
||||||
|
|
||||||
|
return ddlJobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PostprocessAlterStatisticsSchemaStmt is called after a ALTER STATISTICS SCHEMA
|
||||||
|
* command has been executed by standard process utility.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString)
|
||||||
|
{
|
||||||
|
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||||
|
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
Value *statName = llast((List *) stmt->object);
|
||||||
|
Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema),
|
||||||
|
statName), false);
|
||||||
|
Oid relationId = GetRelIdByStatsOid(statsOid);
|
||||||
|
|
||||||
|
if (!IsCitusTable(relationId) || !ShouldPropagate())
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool missingOk = false;
|
||||||
|
ObjectAddress objectAddress = GetObjectAddressFromParseTree((Node *) stmt, missingOk);
|
||||||
|
|
||||||
|
EnsureDependenciesExistOnAllNodes(&objectAddress);
|
||||||
|
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AlterStatisticsSchemaStmtObjectAddress finds the ObjectAddress for the statistics
|
||||||
|
* that is altered by given AlterObjectSchemaStmt. If missingOk is false and if
|
||||||
|
* the statistics does not exist, then it errors out.
|
||||||
|
*
|
||||||
|
* Never returns NULL, but the objid in the address can be invalid if missingOk
|
||||||
|
* was set to true.
|
||||||
|
*/
|
||||||
|
ObjectAddress
|
||||||
|
AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk)
|
||||||
|
{
|
||||||
|
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||||
|
|
||||||
|
ObjectAddress address = { 0 };
|
||||||
|
Value *statName = llast((List *) stmt->object);
|
||||||
|
Oid statsOid = get_statistics_object_oid(list_make2(makeString(stmt->newschema),
|
||||||
|
statName), missingOk);
|
||||||
|
ObjectAddressSet(address, StatisticExtRelationId, statsOid);
|
||||||
|
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PreprocessAlterStatisticsStmt is called during the planning phase for
|
||||||
|
* ALTER STATISTICS .. SET STATISTICS.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
PreprocessAlterStatisticsStmt(Node *node, const char *queryString)
|
||||||
|
{
|
||||||
|
AlterStatsStmt *stmt = castNode(AlterStatsStmt, node);
|
||||||
|
|
||||||
|
Oid statsOid = get_statistics_object_oid(stmt->defnames, false);
|
||||||
|
Oid relationId = GetRelIdByStatsOid(statsOid);
|
||||||
|
|
||||||
|
if (!IsCitusTable(relationId) || !ShouldPropagate())
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureCoordinator();
|
||||||
|
|
||||||
|
QualifyTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
char *ddlCommand = DeparseTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
|
||||||
|
|
||||||
|
ddlJob->targetRelationId = relationId;
|
||||||
|
ddlJob->concurrentIndexCmd = false;
|
||||||
|
ddlJob->startNewTransaction = false;
|
||||||
|
ddlJob->commandString = ddlCommand;
|
||||||
|
ddlJob->taskList = DDLTaskList(relationId, ddlCommand);
|
||||||
|
|
||||||
|
List *ddlJobs = list_make1(ddlJob);
|
||||||
|
|
||||||
|
return ddlJobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PreprocessAlterStatisticsOwnerStmt is called during the planning phase for
|
||||||
|
* ALTER STATISTICS .. OWNER TO.
|
||||||
|
*/
|
||||||
|
List *
|
||||||
|
PreprocessAlterStatisticsOwnerStmt(Node *node, const char *queryString)
|
||||||
|
{
|
||||||
|
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||||
|
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
Oid statsOid = get_statistics_object_oid((List *) stmt->object, false);
|
||||||
|
Oid relationId = GetRelIdByStatsOid(statsOid);
|
||||||
|
|
||||||
|
if (!IsCitusTable(relationId) || !ShouldPropagate())
|
||||||
|
{
|
||||||
|
return NIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureCoordinator();
|
||||||
|
|
||||||
|
QualifyTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
char *ddlCommand = DeparseTreeNode((Node *) stmt);
|
||||||
|
|
||||||
|
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
|
||||||
|
|
||||||
|
ddlJob->targetRelationId = relationId;
|
||||||
|
ddlJob->concurrentIndexCmd = false;
|
||||||
|
ddlJob->startNewTransaction = false;
|
||||||
|
ddlJob->commandString = ddlCommand;
|
||||||
|
ddlJob->taskList = DDLTaskList(relationId, ddlCommand);
|
||||||
|
|
||||||
|
List *ddlJobs = list_make1(ddlJob);
|
||||||
|
|
||||||
|
return ddlJobs;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetExplicitStatisticsCommandList returns the list of DDL commands to create
|
* GetExplicitStatisticsCommandList returns the list of DDL commands to create
|
||||||
* statistics that are explicitly created for the table with relationId. See
|
* statistics that are explicitly created for the table with relationId. See
|
||||||
|
@ -199,6 +410,7 @@ List *
|
||||||
GetExplicitStatisticsCommandList(Oid relationId)
|
GetExplicitStatisticsCommandList(Oid relationId)
|
||||||
{
|
{
|
||||||
List *createStatisticsCommandList = NIL;
|
List *createStatisticsCommandList = NIL;
|
||||||
|
List *alterStatisticsCommandList = NIL;
|
||||||
|
|
||||||
PushOverrideEmptySearchPath(CurrentMemoryContext);
|
PushOverrideEmptySearchPath(CurrentMemoryContext);
|
||||||
|
|
||||||
|
@ -207,16 +419,44 @@ GetExplicitStatisticsCommandList(Oid relationId)
|
||||||
Oid statisticsId = InvalidOid;
|
Oid statisticsId = InvalidOid;
|
||||||
foreach_oid(statisticsId, statisticsIdList)
|
foreach_oid(statisticsId, statisticsIdList)
|
||||||
{
|
{
|
||||||
char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId, false);
|
char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId,
|
||||||
|
false);
|
||||||
|
|
||||||
createStatisticsCommandList = lappend(
|
createStatisticsCommandList =
|
||||||
createStatisticsCommandList,
|
lappend(createStatisticsCommandList,
|
||||||
makeTableDDLCommandString(createStatisticsCommand));
|
makeTableDDLCommandString(createStatisticsCommand));
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
|
||||||
|
/* we need to alter stats' target if it's getting distributed after creation */
|
||||||
|
char *alterStatisticsTargetCommand =
|
||||||
|
CreateAlterCommandIfTargetNotDefault(statisticsId);
|
||||||
|
|
||||||
|
if (alterStatisticsTargetCommand != NULL)
|
||||||
|
{
|
||||||
|
alterStatisticsCommandList =
|
||||||
|
lappend(alterStatisticsCommandList,
|
||||||
|
makeTableDDLCommandString(alterStatisticsTargetCommand));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* we need to alter stats' owner if it's getting distributed after creation */
|
||||||
|
char *alterStatisticsOwnerCommand =
|
||||||
|
CreateAlterCommandIfOwnerNotDefault(statisticsId);
|
||||||
|
|
||||||
|
if (alterStatisticsOwnerCommand != NULL)
|
||||||
|
{
|
||||||
|
alterStatisticsCommandList =
|
||||||
|
lappend(alterStatisticsCommandList,
|
||||||
|
makeTableDDLCommandString(alterStatisticsOwnerCommand));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* revert back to original search_path */
|
/* revert back to original search_path */
|
||||||
PopOverrideSearchPath();
|
PopOverrideSearchPath();
|
||||||
|
|
||||||
|
createStatisticsCommandList = list_concat(createStatisticsCommandList,
|
||||||
|
alterStatisticsCommandList);
|
||||||
|
|
||||||
return createStatisticsCommandList;
|
return createStatisticsCommandList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -332,3 +572,84 @@ GetRelIdByStatsOid(Oid statsOid)
|
||||||
|
|
||||||
return statisticsForm->stxrelid;
|
return statisticsForm->stxrelid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CreateAlterCommandIfOwnerNotDefault returns an ALTER STATISTICS .. OWNER TO
|
||||||
|
* command if the stats object with given id has an owner different than the default one.
|
||||||
|
* Returns NULL otherwise.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
CreateAlterCommandIfOwnerNotDefault(Oid statsOid)
|
||||||
|
{
|
||||||
|
HeapTuple tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid));
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tup))
|
||||||
|
{
|
||||||
|
ereport(WARNING, (errmsg("No stats object found with id: %u", statsOid)));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Form_pg_statistic_ext statisticsForm = (Form_pg_statistic_ext) GETSTRUCT(tup);
|
||||||
|
ReleaseSysCache(tup);
|
||||||
|
|
||||||
|
if (statisticsForm->stxowner == GetUserId())
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *schemaName = get_namespace_name(statisticsForm->stxnamespace);
|
||||||
|
char *statName = NameStr(statisticsForm->stxname);
|
||||||
|
char *ownerName = GetUserNameFromId(statisticsForm->stxowner, false);
|
||||||
|
|
||||||
|
StringInfoData str;
|
||||||
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
appendStringInfo(&str, "ALTER STATISTICS %s OWNER TO %s",
|
||||||
|
NameListToQuotedString(list_make2(makeString(schemaName),
|
||||||
|
makeString(statName))),
|
||||||
|
quote_identifier(ownerName));
|
||||||
|
|
||||||
|
return str.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CreateAlterCommandIfTargetNotDefault returns an ALTER STATISTICS .. SET STATISTICS
|
||||||
|
* command if the stats object with given id has a target different than the default one.
|
||||||
|
* Returns NULL otherwise.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
CreateAlterCommandIfTargetNotDefault(Oid statsOid)
|
||||||
|
{
|
||||||
|
HeapTuple tup = SearchSysCache1(STATEXTOID, ObjectIdGetDatum(statsOid));
|
||||||
|
|
||||||
|
if (!HeapTupleIsValid(tup))
|
||||||
|
{
|
||||||
|
ereport(WARNING, (errmsg("No stats object found with id: %u", statsOid)));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Form_pg_statistic_ext statisticsForm = (Form_pg_statistic_ext) GETSTRUCT(tup);
|
||||||
|
ReleaseSysCache(tup);
|
||||||
|
|
||||||
|
if (statisticsForm->stxstattarget == -1)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
AlterStatsStmt *alterStatsStmt = makeNode(AlterStatsStmt);
|
||||||
|
|
||||||
|
char *schemaName = get_namespace_name(statisticsForm->stxnamespace);
|
||||||
|
char *statName = NameStr(statisticsForm->stxname);
|
||||||
|
|
||||||
|
alterStatsStmt->stxstattarget = statisticsForm->stxstattarget;
|
||||||
|
alterStatsStmt->defnames = list_make2(makeString(schemaName), makeString(statName));
|
||||||
|
|
||||||
|
return DeparseAlterStatisticsStmt((Node *) alterStatsStmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -22,6 +22,12 @@
|
||||||
|
|
||||||
static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt);
|
static void AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt);
|
||||||
static void AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists);
|
static void AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists);
|
||||||
|
static void AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt);
|
||||||
|
static void AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt);
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
static void AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt);
|
||||||
|
#endif
|
||||||
|
static void AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt);
|
||||||
static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt);
|
static void AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt);
|
||||||
static void AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt);
|
static void AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt);
|
||||||
static void AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt);
|
static void AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt);
|
||||||
|
@ -53,6 +59,65 @@ DeparseDropStatisticsStmt(List *nameList, bool ifExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
DeparseAlterStatisticsRenameStmt(Node *node)
|
||||||
|
{
|
||||||
|
RenameStmt *stmt = castNode(RenameStmt, node);
|
||||||
|
|
||||||
|
StringInfoData str;
|
||||||
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
AppendAlterStatisticsRenameStmt(&str, stmt);
|
||||||
|
|
||||||
|
return str.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
DeparseAlterStatisticsSchemaStmt(Node *node)
|
||||||
|
{
|
||||||
|
AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
|
||||||
|
|
||||||
|
StringInfoData str;
|
||||||
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
AppendAlterStatisticsSchemaStmt(&str, stmt);
|
||||||
|
|
||||||
|
return str.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
char *
|
||||||
|
DeparseAlterStatisticsStmt(Node *node)
|
||||||
|
{
|
||||||
|
AlterStatsStmt *stmt = castNode(AlterStatsStmt, node);
|
||||||
|
|
||||||
|
StringInfoData str;
|
||||||
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
AppendAlterStatisticsStmt(&str, stmt);
|
||||||
|
|
||||||
|
return str.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
char *
|
||||||
|
DeparseAlterStatisticsOwnerStmt(Node *node)
|
||||||
|
{
|
||||||
|
AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
|
||||||
|
Assert(stmt->objectType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
StringInfoData str;
|
||||||
|
initStringInfo(&str);
|
||||||
|
|
||||||
|
AppendAlterStatisticsOwnerStmt(&str, stmt);
|
||||||
|
|
||||||
|
return str.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt)
|
AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt)
|
||||||
{
|
{
|
||||||
|
@ -74,8 +139,6 @@ AppendCreateStatisticsStmt(StringInfo buf, CreateStatsStmt *stmt)
|
||||||
appendStringInfoString(buf, " FROM ");
|
appendStringInfoString(buf, " FROM ");
|
||||||
|
|
||||||
AppendTableName(buf, stmt);
|
AppendTableName(buf, stmt);
|
||||||
|
|
||||||
appendStringInfoString(buf, ";");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,6 +156,44 @@ AppendDropStatisticsStmt(StringInfo buf, List *nameList, bool ifExists)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
AppendAlterStatisticsRenameStmt(StringInfo buf, RenameStmt *stmt)
|
||||||
|
{
|
||||||
|
appendStringInfo(buf, "ALTER STATISTICS %s RENAME TO %s",
|
||||||
|
NameListToQuotedString((List *) stmt->object), quote_identifier(
|
||||||
|
stmt->newname));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
AppendAlterStatisticsSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
|
||||||
|
{
|
||||||
|
appendStringInfo(buf, "ALTER STATISTICS %s SET SCHEMA %s",
|
||||||
|
NameListToQuotedString((List *) stmt->object), quote_identifier(
|
||||||
|
stmt->newschema));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
static void
|
||||||
|
AppendAlterStatisticsStmt(StringInfo buf, AlterStatsStmt *stmt)
|
||||||
|
{
|
||||||
|
appendStringInfo(buf, "ALTER STATISTICS %s SET STATISTICS %d", NameListToQuotedString(
|
||||||
|
stmt->defnames), stmt->stxstattarget);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
static void
|
||||||
|
AppendAlterStatisticsOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
|
||||||
|
{
|
||||||
|
List *names = (List *) stmt->object;
|
||||||
|
appendStringInfo(buf, "ALTER STATISTICS %s OWNER TO %s",
|
||||||
|
NameListToQuotedString(names),
|
||||||
|
RoleSpecString(stmt->newowner, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt)
|
AppendStatisticsName(StringInfo buf, CreateStatsStmt *stmt)
|
||||||
{
|
{
|
||||||
|
|
|
@ -78,3 +78,89 @@ QualifyDropStatisticsStmt(Node *node)
|
||||||
|
|
||||||
dropStatisticsStmt->objects = objectNameListWithSchema;
|
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 schemaOid = RangeVarGetCreationNamespace(stat);
|
||||||
|
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 schemaOid = RangeVarGetCreationNamespace(stat);
|
||||||
|
stat->schemaname = get_namespace_name(schemaOid);
|
||||||
|
stmt->object = (Node *) MakeNameListFromRangeVar(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 schemaOid = RangeVarGetCreationNamespace(stat);
|
||||||
|
stat->schemaname = get_namespace_name(schemaOid);
|
||||||
|
stmt->defnames = MakeNameListFromRangeVar(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* QualifyAlterStatisticsStmt 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 schemaOid = RangeVarGetCreationNamespace(stat);
|
||||||
|
stat->schemaname = get_namespace_name(schemaOid);
|
||||||
|
stmt->object = (Node *) MakeNameListFromRangeVar(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -82,17 +82,48 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
{
|
{
|
||||||
AlterObjectSchemaStmt *alterObjectSchemaStmt =
|
AlterObjectSchemaStmt *alterObjectSchemaStmt =
|
||||||
(AlterObjectSchemaStmt *) parseTree;
|
(AlterObjectSchemaStmt *) parseTree;
|
||||||
|
ObjectType objectType = alterObjectSchemaStmt->objectType;
|
||||||
|
|
||||||
|
if (objectType == OBJECT_STATISTIC_EXT)
|
||||||
|
{
|
||||||
|
RangeVar *stat = makeRangeVarFromNameList(
|
||||||
|
(List *) alterObjectSchemaStmt->object);
|
||||||
|
|
||||||
|
/* append shard id */
|
||||||
|
AppendShardIdToName(&stat->relname, shardId);
|
||||||
|
|
||||||
|
alterObjectSchemaStmt->object = (Node *) MakeNameListFromRangeVar(stat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
char **relationName = &(alterObjectSchemaStmt->relation->relname);
|
char **relationName = &(alterObjectSchemaStmt->relation->relname);
|
||||||
char **relationSchemaName = &(alterObjectSchemaStmt->relation->schemaname);
|
char **relationSchemaName =
|
||||||
|
&(alterObjectSchemaStmt->relation->schemaname);
|
||||||
|
|
||||||
/* prefix with schema name if it is not added already */
|
/* prefix with schema name if it is not added already */
|
||||||
SetSchemaNameIfNotExist(relationSchemaName, schemaName);
|
SetSchemaNameIfNotExist(relationSchemaName, schemaName);
|
||||||
|
|
||||||
/* append shardId to base relation name */
|
/* append shardId to base relation name */
|
||||||
AppendShardIdToName(relationName, shardId);
|
AppendShardIdToName(relationName, shardId);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PG_VERSION_NUM >= PG_VERSION_13
|
||||||
|
case T_AlterStatsStmt:
|
||||||
|
{
|
||||||
|
AlterStatsStmt *alterStatsStmt = (AlterStatsStmt *) parseTree;
|
||||||
|
RangeVar *stat = makeRangeVarFromNameList(alterStatsStmt->defnames);
|
||||||
|
|
||||||
|
AppendShardIdToName(&stat->relname, shardId);
|
||||||
|
|
||||||
|
alterStatsStmt->defnames = MakeNameListFromRangeVar(stat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
case T_AlterTableStmt:
|
case T_AlterTableStmt:
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -180,6 +211,22 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case T_AlterOwnerStmt:
|
||||||
|
{
|
||||||
|
AlterOwnerStmt *alterOwnerStmt = castNode(AlterOwnerStmt, parseTree);
|
||||||
|
|
||||||
|
/* we currently extend names in alter owner statements only for statistics */
|
||||||
|
Assert(alterOwnerStmt->objectType == OBJECT_STATISTIC_EXT);
|
||||||
|
|
||||||
|
RangeVar *stat = makeRangeVarFromNameList((List *) alterOwnerStmt->object);
|
||||||
|
|
||||||
|
AppendShardIdToName(&stat->relname, shardId);
|
||||||
|
|
||||||
|
alterOwnerStmt->object = (Node *) MakeNameListFromRangeVar(stat);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case T_ClusterStmt:
|
case T_ClusterStmt:
|
||||||
{
|
{
|
||||||
ClusterStmt *clusterStmt = (ClusterStmt *) parseTree;
|
ClusterStmt *clusterStmt = (ClusterStmt *) parseTree;
|
||||||
|
@ -530,6 +577,17 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
{
|
{
|
||||||
RenamePolicyEventExtendNames(renameStmt, schemaName, shardId);
|
RenamePolicyEventExtendNames(renameStmt, schemaName, shardId);
|
||||||
}
|
}
|
||||||
|
else if (objectType == OBJECT_STATISTIC_EXT)
|
||||||
|
{
|
||||||
|
RangeVar *stat = makeRangeVarFromNameList((List *) renameStmt->object);
|
||||||
|
|
||||||
|
AppendShardIdToName(&stat->relname, shardId);
|
||||||
|
AppendShardIdToName(&renameStmt->newname, shardId);
|
||||||
|
|
||||||
|
SetSchemaNameIfNotExist(&stat->schemaname, schemaName);
|
||||||
|
|
||||||
|
renameStmt->object = (Node *) MakeNameListFromRangeVar(stat);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ereport(WARNING, (errmsg("unsafe object type in rename statement"),
|
ereport(WARNING, (errmsg("unsafe object type in rename statement"),
|
||||||
|
|
|
@ -282,6 +282,12 @@ extern List * PreprocessCreateStatisticsStmt(Node *node, const char *queryString
|
||||||
extern List * PostprocessCreateStatisticsStmt(Node *node, const char *queryString);
|
extern List * PostprocessCreateStatisticsStmt(Node *node, const char *queryString);
|
||||||
extern ObjectAddress CreateStatisticsStmtObjectAddress(Node *node, bool missingOk);
|
extern ObjectAddress CreateStatisticsStmtObjectAddress(Node *node, bool missingOk);
|
||||||
extern List * PreprocessDropStatisticsStmt(Node *node, const char *queryString);
|
extern List * PreprocessDropStatisticsStmt(Node *node, const char *queryString);
|
||||||
|
extern List * PreprocessAlterStatisticsRenameStmt(Node *node, const char *queryString);
|
||||||
|
extern List * PreprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString);
|
||||||
|
extern List * PostprocessAlterStatisticsSchemaStmt(Node *node, const char *queryString);
|
||||||
|
extern ObjectAddress AlterStatisticsSchemaStmtObjectAddress(Node *node, bool missingOk);
|
||||||
|
extern List * PreprocessAlterStatisticsStmt(Node *node, const char *queryString);
|
||||||
|
extern List * PreprocessAlterStatisticsOwnerStmt(Node *node, const char *queryString);
|
||||||
extern List * GetExplicitStatisticsCommandList(Oid relationId);
|
extern List * GetExplicitStatisticsCommandList(Oid relationId);
|
||||||
extern List * GetExplicitStatisticsSchemaIdList(Oid relationId);
|
extern List * GetExplicitStatisticsSchemaIdList(Oid relationId);
|
||||||
|
|
||||||
|
|
|
@ -58,9 +58,17 @@ extern char * DeparseAlterSchemaRenameStmt(Node *stmt);
|
||||||
/* forward declarations for deparse_statistics_stmts.c */
|
/* forward declarations for deparse_statistics_stmts.c */
|
||||||
extern char * DeparseCreateStatisticsStmt(Node *node);
|
extern char * DeparseCreateStatisticsStmt(Node *node);
|
||||||
extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists);
|
extern char * DeparseDropStatisticsStmt(List *nameList, bool ifExists);
|
||||||
|
extern char * DeparseAlterStatisticsRenameStmt(Node *node);
|
||||||
|
extern char * DeparseAlterStatisticsSchemaStmt(Node *node);
|
||||||
|
extern char * DeparseAlterStatisticsStmt(Node *node);
|
||||||
|
extern char * DeparseAlterStatisticsOwnerStmt(Node *node);
|
||||||
|
|
||||||
extern void QualifyCreateStatisticsStmt(Node *node);
|
extern void QualifyCreateStatisticsStmt(Node *node);
|
||||||
extern void QualifyDropStatisticsStmt(Node *node);
|
extern void QualifyDropStatisticsStmt(Node *node);
|
||||||
|
extern void QualifyAlterStatisticsRenameStmt(Node *node);
|
||||||
|
extern void QualifyAlterStatisticsSchemaStmt(Node *node);
|
||||||
|
extern void QualifyAlterStatisticsStmt(Node *node);
|
||||||
|
extern void QualifyAlterStatisticsOwnerStmt(Node *node);
|
||||||
|
|
||||||
/* forward declarations for deparse_type_stmts.c */
|
/* forward declarations for deparse_type_stmts.c */
|
||||||
extern char * DeparseCompositeTypeStmt(Node *stmt);
|
extern char * DeparseCompositeTypeStmt(Node *stmt);
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
SHOW server_version \gset
|
||||||
|
SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve
|
||||||
|
\gset
|
||||||
|
\if :server_version_above_twelve
|
||||||
|
\else
|
||||||
|
\q
|
||||||
|
\endif
|
||||||
|
CREATE SCHEMA "statistics'TestTarget";
|
||||||
|
SET search_path TO "statistics'TestTarget";
|
||||||
|
SET citus.next_shard_id TO 980000;
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
SET citus.shard_count TO 32;
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
CREATE STATISTICS s1 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s2 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s3 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s4 ON a,b FROM t1;
|
||||||
|
-- test altering stats target
|
||||||
|
-- test alter target before distribution
|
||||||
|
ALTER STATISTICS s1 SET STATISTICS 3;
|
||||||
|
-- since max value for target is 10000, this will automatically be lowered
|
||||||
|
ALTER STATISTICS s2 SET STATISTICS 999999;
|
||||||
|
WARNING: lowering statistics target to 10000
|
||||||
|
SELECT create_distributed_table('t1', 'b');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
-- test alter target before distribution
|
||||||
|
ALTER STATISTICS s3 SET STATISTICS 46;
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SELECT stxstattarget, stxrelid::regclass
|
||||||
|
FROM pg_statistic_ext
|
||||||
|
WHERE stxnamespace IN (
|
||||||
|
SELECT oid
|
||||||
|
FROM pg_namespace
|
||||||
|
WHERE nspname IN ('statistics''TestTarget')
|
||||||
|
)
|
||||||
|
ORDER BY stxstattarget, stxrelid::regclass ASC;
|
||||||
|
stxstattarget | stxrelid
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
-1 | "statistics'TestTarget".t1_980000
|
||||||
|
-1 | "statistics'TestTarget".t1_980002
|
||||||
|
-1 | "statistics'TestTarget".t1_980004
|
||||||
|
-1 | "statistics'TestTarget".t1_980006
|
||||||
|
-1 | "statistics'TestTarget".t1_980008
|
||||||
|
-1 | "statistics'TestTarget".t1_980010
|
||||||
|
-1 | "statistics'TestTarget".t1_980012
|
||||||
|
-1 | "statistics'TestTarget".t1_980014
|
||||||
|
-1 | "statistics'TestTarget".t1_980016
|
||||||
|
-1 | "statistics'TestTarget".t1_980018
|
||||||
|
-1 | "statistics'TestTarget".t1_980020
|
||||||
|
-1 | "statistics'TestTarget".t1_980022
|
||||||
|
-1 | "statistics'TestTarget".t1_980024
|
||||||
|
-1 | "statistics'TestTarget".t1_980026
|
||||||
|
-1 | "statistics'TestTarget".t1_980028
|
||||||
|
-1 | "statistics'TestTarget".t1_980030
|
||||||
|
3 | "statistics'TestTarget".t1_980000
|
||||||
|
3 | "statistics'TestTarget".t1_980002
|
||||||
|
3 | "statistics'TestTarget".t1_980004
|
||||||
|
3 | "statistics'TestTarget".t1_980006
|
||||||
|
3 | "statistics'TestTarget".t1_980008
|
||||||
|
3 | "statistics'TestTarget".t1_980010
|
||||||
|
3 | "statistics'TestTarget".t1_980012
|
||||||
|
3 | "statistics'TestTarget".t1_980014
|
||||||
|
3 | "statistics'TestTarget".t1_980016
|
||||||
|
3 | "statistics'TestTarget".t1_980018
|
||||||
|
3 | "statistics'TestTarget".t1_980020
|
||||||
|
3 | "statistics'TestTarget".t1_980022
|
||||||
|
3 | "statistics'TestTarget".t1_980024
|
||||||
|
3 | "statistics'TestTarget".t1_980026
|
||||||
|
3 | "statistics'TestTarget".t1_980028
|
||||||
|
3 | "statistics'TestTarget".t1_980030
|
||||||
|
46 | "statistics'TestTarget".t1_980000
|
||||||
|
46 | "statistics'TestTarget".t1_980002
|
||||||
|
46 | "statistics'TestTarget".t1_980004
|
||||||
|
46 | "statistics'TestTarget".t1_980006
|
||||||
|
46 | "statistics'TestTarget".t1_980008
|
||||||
|
46 | "statistics'TestTarget".t1_980010
|
||||||
|
46 | "statistics'TestTarget".t1_980012
|
||||||
|
46 | "statistics'TestTarget".t1_980014
|
||||||
|
46 | "statistics'TestTarget".t1_980016
|
||||||
|
46 | "statistics'TestTarget".t1_980018
|
||||||
|
46 | "statistics'TestTarget".t1_980020
|
||||||
|
46 | "statistics'TestTarget".t1_980022
|
||||||
|
46 | "statistics'TestTarget".t1_980024
|
||||||
|
46 | "statistics'TestTarget".t1_980026
|
||||||
|
46 | "statistics'TestTarget".t1_980028
|
||||||
|
46 | "statistics'TestTarget".t1_980030
|
||||||
|
10000 | "statistics'TestTarget".t1_980000
|
||||||
|
10000 | "statistics'TestTarget".t1_980002
|
||||||
|
10000 | "statistics'TestTarget".t1_980004
|
||||||
|
10000 | "statistics'TestTarget".t1_980006
|
||||||
|
10000 | "statistics'TestTarget".t1_980008
|
||||||
|
10000 | "statistics'TestTarget".t1_980010
|
||||||
|
10000 | "statistics'TestTarget".t1_980012
|
||||||
|
10000 | "statistics'TestTarget".t1_980014
|
||||||
|
10000 | "statistics'TestTarget".t1_980016
|
||||||
|
10000 | "statistics'TestTarget".t1_980018
|
||||||
|
10000 | "statistics'TestTarget".t1_980020
|
||||||
|
10000 | "statistics'TestTarget".t1_980022
|
||||||
|
10000 | "statistics'TestTarget".t1_980024
|
||||||
|
10000 | "statistics'TestTarget".t1_980026
|
||||||
|
10000 | "statistics'TestTarget".t1_980028
|
||||||
|
10000 | "statistics'TestTarget".t1_980030
|
||||||
|
(64 rows)
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA "statistics'TestTarget" CASCADE;
|
|
@ -0,0 +1,6 @@
|
||||||
|
SHOW server_version \gset
|
||||||
|
SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve
|
||||||
|
\gset
|
||||||
|
\if :server_version_above_twelve
|
||||||
|
\else
|
||||||
|
\q
|
|
@ -70,6 +70,27 @@ DROP STATISTICS IF EXISTS s3, sc2.s4, s6;
|
||||||
DROP STATISTICS s5,s6;
|
DROP STATISTICS s5,s6;
|
||||||
ERROR: statistics object "statistics'Test.s6" does not exist
|
ERROR: statistics object "statistics'Test.s6" does not exist
|
||||||
DROP STATISTICS IF EXISTS s5,s5,s6,s6;
|
DROP STATISTICS IF EXISTS s5,s5,s6,s6;
|
||||||
|
-- test renaming statistics
|
||||||
|
CREATE STATISTICS s6 ON a,b FROM test_stats4;
|
||||||
|
DROP STATISTICS s7;
|
||||||
|
ERROR: statistics object "statistics'Test.s7" does not exist
|
||||||
|
ALTER STATISTICS s6 RENAME TO s7;
|
||||||
|
ALTER STATISTICS sc1.st1 RENAME TO st1_new;
|
||||||
|
-- test altering stats schema
|
||||||
|
CREATE SCHEMA test_alter_schema;
|
||||||
|
ALTER STATISTICS s7 SET SCHEMA test_alter_schema;
|
||||||
|
-- test alter owner
|
||||||
|
ALTER STATISTICS sc2."neW'Stat" OWNER TO pg_monitor;
|
||||||
|
-- test alter owner before distribution
|
||||||
|
CREATE TABLE ownertest(a int, b int);
|
||||||
|
CREATE STATISTICS sc1.s9 ON a,b FROM ownertest;
|
||||||
|
ALTER STATISTICS sc1.s9 OWNER TO pg_signal_backend;
|
||||||
|
SELECT create_distributed_table('ownertest','a');
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT stxname
|
SELECT stxname
|
||||||
FROM pg_statistic_ext
|
FROM pg_statistic_ext
|
||||||
|
@ -129,23 +150,39 @@ ORDER BY stxname ASC;
|
||||||
s2_980058
|
s2_980058
|
||||||
s2_980060
|
s2_980060
|
||||||
s2_980062
|
s2_980062
|
||||||
st1_980064
|
s9_980129
|
||||||
st1_980066
|
s9_980131
|
||||||
st1_980068
|
s9_980133
|
||||||
st1_980070
|
s9_980135
|
||||||
st1_980072
|
s9_980137
|
||||||
st1_980074
|
s9_980139
|
||||||
st1_980076
|
s9_980141
|
||||||
st1_980078
|
s9_980143
|
||||||
st1_980080
|
s9_980145
|
||||||
st1_980082
|
s9_980147
|
||||||
st1_980084
|
s9_980149
|
||||||
st1_980086
|
s9_980151
|
||||||
st1_980088
|
s9_980153
|
||||||
st1_980090
|
s9_980155
|
||||||
st1_980092
|
s9_980157
|
||||||
st1_980094
|
s9_980159
|
||||||
(64 rows)
|
st1_new_980064
|
||||||
|
st1_new_980066
|
||||||
|
st1_new_980068
|
||||||
|
st1_new_980070
|
||||||
|
st1_new_980072
|
||||||
|
st1_new_980074
|
||||||
|
st1_new_980076
|
||||||
|
st1_new_980078
|
||||||
|
st1_new_980080
|
||||||
|
st1_new_980082
|
||||||
|
st1_new_980084
|
||||||
|
st1_new_980086
|
||||||
|
st1_new_980088
|
||||||
|
st1_new_980090
|
||||||
|
st1_new_980092
|
||||||
|
st1_new_980094
|
||||||
|
(80 rows)
|
||||||
|
|
||||||
SELECT count(DISTINCT stxnamespace)
|
SELECT count(DISTINCT stxnamespace)
|
||||||
FROM pg_statistic_ext
|
FROM pg_statistic_ext
|
||||||
|
@ -159,8 +196,21 @@ WHERE stxnamespace IN (
|
||||||
3
|
3
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SELECT COUNT(DISTINCT stxowner)
|
||||||
|
FROM pg_statistic_ext
|
||||||
|
WHERE stxnamespace IN (
|
||||||
|
SELECT oid
|
||||||
|
FROM pg_namespace
|
||||||
|
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
|
||||||
|
);
|
||||||
|
count
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
3
|
||||||
|
(1 row)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA "statistics'Test" CASCADE;
|
DROP SCHEMA "statistics'Test" CASCADE;
|
||||||
|
DROP SCHEMA test_alter_schema CASCADE;
|
||||||
DROP SCHEMA sc1 CASCADE;
|
DROP SCHEMA sc1 CASCADE;
|
||||||
DROP SCHEMA sc2 CASCADE;
|
DROP SCHEMA sc2 CASCADE;
|
||||||
|
|
|
@ -94,6 +94,7 @@ test: tableam
|
||||||
# Tests for statistics propagation
|
# Tests for statistics propagation
|
||||||
# ----------
|
# ----------
|
||||||
test: propagate_statistics
|
test: propagate_statistics
|
||||||
|
test: pg13_propagate_statistics
|
||||||
|
|
||||||
# ----------
|
# ----------
|
||||||
# Miscellaneous tests to check our query planning behavior
|
# Miscellaneous tests to check our query planning behavior
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
SHOW server_version \gset
|
||||||
|
SELECT substring(:'server_version', '\d+')::int > 12 AS server_version_above_twelve
|
||||||
|
\gset
|
||||||
|
\if :server_version_above_twelve
|
||||||
|
\else
|
||||||
|
\q
|
||||||
|
\endif
|
||||||
|
|
||||||
|
CREATE SCHEMA "statistics'TestTarget";
|
||||||
|
SET search_path TO "statistics'TestTarget";
|
||||||
|
SET citus.next_shard_id TO 980000;
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
SET citus.shard_count TO 32;
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
|
||||||
|
CREATE TABLE t1 (a int, b int);
|
||||||
|
CREATE STATISTICS s1 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s2 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s3 ON a,b FROM t1;
|
||||||
|
CREATE STATISTICS s4 ON a,b FROM t1;
|
||||||
|
|
||||||
|
-- test altering stats target
|
||||||
|
-- test alter target before distribution
|
||||||
|
ALTER STATISTICS s1 SET STATISTICS 3;
|
||||||
|
-- since max value for target is 10000, this will automatically be lowered
|
||||||
|
ALTER STATISTICS s2 SET STATISTICS 999999;
|
||||||
|
|
||||||
|
SELECT create_distributed_table('t1', 'b');
|
||||||
|
|
||||||
|
-- test alter target before distribution
|
||||||
|
ALTER STATISTICS s3 SET STATISTICS 46;
|
||||||
|
|
||||||
|
\c - - - :worker_1_port
|
||||||
|
SELECT stxstattarget, stxrelid::regclass
|
||||||
|
FROM pg_statistic_ext
|
||||||
|
WHERE stxnamespace IN (
|
||||||
|
SELECT oid
|
||||||
|
FROM pg_namespace
|
||||||
|
WHERE nspname IN ('statistics''TestTarget')
|
||||||
|
)
|
||||||
|
ORDER BY stxstattarget, stxrelid::regclass ASC;
|
||||||
|
|
||||||
|
\c - - - :master_port
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA "statistics'TestTarget" CASCADE;
|
|
@ -57,6 +57,24 @@ DROP STATISTICS IF EXISTS s3, sc2.s4, s6;
|
||||||
DROP STATISTICS s5,s6;
|
DROP STATISTICS s5,s6;
|
||||||
DROP STATISTICS IF EXISTS s5,s5,s6,s6;
|
DROP STATISTICS IF EXISTS s5,s5,s6,s6;
|
||||||
|
|
||||||
|
-- test renaming statistics
|
||||||
|
CREATE STATISTICS s6 ON a,b FROM test_stats4;
|
||||||
|
DROP STATISTICS s7;
|
||||||
|
ALTER STATISTICS s6 RENAME TO s7;
|
||||||
|
ALTER STATISTICS sc1.st1 RENAME TO st1_new;
|
||||||
|
|
||||||
|
-- test altering stats schema
|
||||||
|
CREATE SCHEMA test_alter_schema;
|
||||||
|
ALTER STATISTICS s7 SET SCHEMA test_alter_schema;
|
||||||
|
|
||||||
|
-- test alter owner
|
||||||
|
ALTER STATISTICS sc2."neW'Stat" OWNER TO pg_monitor;
|
||||||
|
-- test alter owner before distribution
|
||||||
|
CREATE TABLE ownertest(a int, b int);
|
||||||
|
CREATE STATISTICS sc1.s9 ON a,b FROM ownertest;
|
||||||
|
ALTER STATISTICS sc1.s9 OWNER TO pg_signal_backend;
|
||||||
|
SELECT create_distributed_table('ownertest','a');
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT stxname
|
SELECT stxname
|
||||||
FROM pg_statistic_ext
|
FROM pg_statistic_ext
|
||||||
|
@ -75,8 +93,17 @@ WHERE stxnamespace IN (
|
||||||
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
|
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
|
||||||
);
|
);
|
||||||
|
|
||||||
|
SELECT COUNT(DISTINCT stxowner)
|
||||||
|
FROM pg_statistic_ext
|
||||||
|
WHERE stxnamespace IN (
|
||||||
|
SELECT oid
|
||||||
|
FROM pg_namespace
|
||||||
|
WHERE nspname IN ('public', 'statistics''Test', 'sc1', 'sc2')
|
||||||
|
);
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
SET client_min_messages TO WARNING;
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA "statistics'Test" CASCADE;
|
DROP SCHEMA "statistics'Test" CASCADE;
|
||||||
|
DROP SCHEMA test_alter_schema CASCADE;
|
||||||
DROP SCHEMA sc1 CASCADE;
|
DROP SCHEMA sc1 CASCADE;
|
||||||
DROP SCHEMA sc2 CASCADE;
|
DROP SCHEMA sc2 CASCADE;
|
||||||
|
|
Loading…
Reference in New Issue