mirror of https://github.com/citusdata/citus.git
Deparse ALTER TABLE commands if ADD COLUMN is the only subcommand (#7032)
Some clients send ALTER TABLE .. ADD COLUMN .. commands together with some other DDLs and this makes it impossible to directly send the original DDL command to the workers. For this reason, this commit adds support for deparsing such ALTER TABLE commands so that we can avoid from directly sending the original one to the workers. Partially fixes https://github.com/citusdata/citus/issues/690. Fixes #3678pull/7013/merge
commit
2c11e4d7f9
|
@ -76,6 +76,8 @@ static void DistributePartitionUsingParent(Oid parentRelationId,
|
||||||
static void ErrorIfMultiLevelPartitioning(Oid parentRelationId, Oid partitionRelationId);
|
static void ErrorIfMultiLevelPartitioning(Oid parentRelationId, Oid partitionRelationId);
|
||||||
static void ErrorIfAttachCitusTableToPgLocalTable(Oid parentRelationId,
|
static void ErrorIfAttachCitusTableToPgLocalTable(Oid parentRelationId,
|
||||||
Oid partitionRelationId);
|
Oid partitionRelationId);
|
||||||
|
static bool DeparserSupportsAlterTableAddColumn(AlterTableStmt *alterTableStatement,
|
||||||
|
AlterTableCmd *addColumnSubCommand);
|
||||||
static bool ATDefinesFKeyBetweenPostgresAndCitusLocalOrRef(
|
static bool ATDefinesFKeyBetweenPostgresAndCitusLocalOrRef(
|
||||||
AlterTableStmt *alterTableStatement);
|
AlterTableStmt *alterTableStatement);
|
||||||
static bool ShouldMarkConnectedRelationsNotAutoConverted(Oid leftRelationId,
|
static bool ShouldMarkConnectedRelationsNotAutoConverted(Oid leftRelationId,
|
||||||
|
@ -120,7 +122,8 @@ static void SetInterShardDDLTaskRelationShardList(Task *task,
|
||||||
static Oid get_attrdef_oid(Oid relationId, AttrNumber attnum);
|
static Oid get_attrdef_oid(Oid relationId, AttrNumber attnum);
|
||||||
|
|
||||||
static char * GetAddColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId,
|
static char * GetAddColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId,
|
||||||
char *colname, TypeName *typeName);
|
char *colname, TypeName *typeName,
|
||||||
|
bool ifNotExists);
|
||||||
static void ErrorIfAlterTableDropTableNameFromPostgresFdw(List *optionList, Oid
|
static void ErrorIfAlterTableDropTableNameFromPostgresFdw(List *optionList, Oid
|
||||||
relationId);
|
relationId);
|
||||||
|
|
||||||
|
@ -1028,30 +1031,7 @@ PreprocessAlterTableAddConstraint(AlterTableStmt *alterTableStatement, Oid
|
||||||
relationId,
|
relationId,
|
||||||
Constraint *constraint)
|
Constraint *constraint)
|
||||||
{
|
{
|
||||||
/*
|
PrepareAlterTableStmtForConstraint(alterTableStatement, relationId, constraint);
|
||||||
* We should only preprocess an ADD CONSTRAINT command if we have empty conname
|
|
||||||
* This only happens when we have to create a constraint name in citus since the client does
|
|
||||||
* not specify a name.
|
|
||||||
* indexname should also be NULL to make sure this is not an
|
|
||||||
* ADD {PRIMARY KEY, UNIQUE} USING INDEX command
|
|
||||||
* which doesn't need a conname since the indexname will be used
|
|
||||||
*/
|
|
||||||
Assert(constraint->conname == NULL && constraint->indexname == NULL);
|
|
||||||
|
|
||||||
Relation rel = RelationIdGetRelation(relationId);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Change the alterTableCommand so that the standard utility
|
|
||||||
* hook runs it with the name we created.
|
|
||||||
*/
|
|
||||||
|
|
||||||
constraint->conname = GenerateConstraintName(RelationGetRelationName(rel),
|
|
||||||
RelationGetNamespace(rel),
|
|
||||||
constraint);
|
|
||||||
|
|
||||||
RelationClose(rel);
|
|
||||||
|
|
||||||
SwitchToSequentialAndLocalExecutionIfConstraintNameTooLong(relationId, constraint);
|
|
||||||
|
|
||||||
char *ddlCommand = DeparseTreeNode((Node *) alterTableStatement);
|
char *ddlCommand = DeparseTreeNode((Node *) alterTableStatement);
|
||||||
|
|
||||||
|
@ -1067,11 +1047,6 @@ PreprocessAlterTableAddConstraint(AlterTableStmt *alterTableStatement, Oid
|
||||||
Oid rightRelationId = RangeVarGetRelid(constraint->pktable, NoLock,
|
Oid rightRelationId = RangeVarGetRelid(constraint->pktable, NoLock,
|
||||||
false);
|
false);
|
||||||
|
|
||||||
if (IsCitusTableType(rightRelationId, REFERENCE_TABLE))
|
|
||||||
{
|
|
||||||
EnsureSequentialModeForAlterTableOperation();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If one of the relations involved in the FOREIGN KEY constraint is not a distributed table, citus errors out eventually.
|
* If one of the relations involved in the FOREIGN KEY constraint is not a distributed table, citus errors out eventually.
|
||||||
* PreprocessAlterTableStmt function returns an empty tasklist in those cases.
|
* PreprocessAlterTableStmt function returns an empty tasklist in those cases.
|
||||||
|
@ -1099,6 +1074,47 @@ PreprocessAlterTableAddConstraint(AlterTableStmt *alterTableStatement, Oid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PrepareAlterTableStmtForConstraint assigns a name to the constraint if it
|
||||||
|
* does not have one and switches to sequential and local execution if the
|
||||||
|
* constraint name is too long.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PrepareAlterTableStmtForConstraint(AlterTableStmt *alterTableStatement,
|
||||||
|
Oid relationId,
|
||||||
|
Constraint *constraint)
|
||||||
|
{
|
||||||
|
if (constraint->conname == NULL && constraint->indexname == NULL)
|
||||||
|
{
|
||||||
|
Relation rel = RelationIdGetRelation(relationId);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change the alterTableCommand so that the standard utility
|
||||||
|
* hook runs it with the name we created.
|
||||||
|
*/
|
||||||
|
|
||||||
|
constraint->conname = GenerateConstraintName(RelationGetRelationName(rel),
|
||||||
|
RelationGetNamespace(rel),
|
||||||
|
constraint);
|
||||||
|
|
||||||
|
RelationClose(rel);
|
||||||
|
}
|
||||||
|
|
||||||
|
SwitchToSequentialAndLocalExecutionIfConstraintNameTooLong(relationId, constraint);
|
||||||
|
|
||||||
|
if (constraint->contype == CONSTR_FOREIGN)
|
||||||
|
{
|
||||||
|
Oid rightRelationId = RangeVarGetRelid(constraint->pktable, NoLock,
|
||||||
|
false);
|
||||||
|
|
||||||
|
if (IsCitusTableType(rightRelationId, REFERENCE_TABLE))
|
||||||
|
{
|
||||||
|
EnsureSequentialModeForAlterTableOperation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PreprocessAlterTableStmt determines whether a given ALTER TABLE statement
|
* PreprocessAlterTableStmt determines whether a given ALTER TABLE statement
|
||||||
* involves a distributed table. If so (and if the statement does not use
|
* involves a distributed table. If so (and if the statement does not use
|
||||||
|
@ -1267,6 +1283,7 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
* we also set skip_validation to true to prevent PostgreSQL to verify validity
|
* we also set skip_validation to true to prevent PostgreSQL to verify validity
|
||||||
* of the foreign constraint in master. Validity will be checked in workers
|
* of the foreign constraint in master. Validity will be checked in workers
|
||||||
* anyway.
|
* anyway.
|
||||||
|
* - an ADD COLUMN .. that is the only subcommand in the list OR
|
||||||
* - an ADD COLUMN .. DEFAULT nextval('..') OR
|
* - an ADD COLUMN .. DEFAULT nextval('..') OR
|
||||||
* an ADD COLUMN .. SERIAL pseudo-type OR
|
* an ADD COLUMN .. SERIAL pseudo-type OR
|
||||||
* an ALTER COLUMN .. SET DEFAULT nextval('..'). If there is we set
|
* an ALTER COLUMN .. SET DEFAULT nextval('..'). If there is we set
|
||||||
|
@ -1396,13 +1413,6 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
}
|
}
|
||||||
else if (alterTableType == AT_AddColumn)
|
else if (alterTableType == AT_AddColumn)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* TODO: This code path is nothing beneficial since we do not
|
|
||||||
* support ALTER TABLE %s ADD COLUMN %s [constraint] for foreign keys.
|
|
||||||
* However, the code is kept in case we fix the constraint
|
|
||||||
* creation without a name and allow foreign key creation with the mentioned
|
|
||||||
* command.
|
|
||||||
*/
|
|
||||||
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
||||||
List *columnConstraints = columnDefinition->constraints;
|
List *columnConstraints = columnDefinition->constraints;
|
||||||
|
|
||||||
|
@ -1426,12 +1436,36 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DeparserSupportsAlterTableAddColumn(alterTableStatement, command))
|
||||||
|
{
|
||||||
|
deparseAT = true;
|
||||||
|
|
||||||
|
constraint = NULL;
|
||||||
|
foreach_ptr(constraint, columnConstraints)
|
||||||
|
{
|
||||||
|
if (ConstrTypeCitusCanDefaultName(constraint->contype))
|
||||||
|
{
|
||||||
|
PrepareAlterTableStmtForConstraint(alterTableStatement,
|
||||||
|
leftRelationId,
|
||||||
|
constraint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy the constraints to the new subcommand because now we
|
||||||
|
* might have assigned names to some of them.
|
||||||
|
*/
|
||||||
|
ColumnDef *newColumnDef = (ColumnDef *) newCmd->def;
|
||||||
|
newColumnDef->constraints = copyObject(columnConstraints);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We check for ADD COLUMN .. DEFAULT expr
|
* We check for ADD COLUMN .. DEFAULT expr
|
||||||
* if expr contains nextval('user_defined_seq')
|
* if expr contains nextval('user_defined_seq')
|
||||||
* we should deparse the statement
|
* we should deparse the statement
|
||||||
*/
|
*/
|
||||||
constraint = NULL;
|
constraint = NULL;
|
||||||
|
int constraintIdx = 0;
|
||||||
foreach_ptr(constraint, columnConstraints)
|
foreach_ptr(constraint, columnConstraints)
|
||||||
{
|
{
|
||||||
if (constraint->contype == CONSTR_DEFAULT)
|
if (constraint->contype == CONSTR_DEFAULT)
|
||||||
|
@ -1447,14 +1481,19 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
deparseAT = true;
|
deparseAT = true;
|
||||||
useInitialDDLCommandString = false;
|
useInitialDDLCommandString = false;
|
||||||
|
|
||||||
/* the new column definition will have no constraint */
|
/* drop the default expression from new subcomand */
|
||||||
ColumnDef *newColDef = copyObject(columnDefinition);
|
ColumnDef *newColumnDef = (ColumnDef *) newCmd->def;
|
||||||
newColDef->constraints = NULL;
|
newColumnDef->constraints =
|
||||||
|
list_delete_nth_cell(newColumnDef->constraints,
|
||||||
newCmd->def = (Node *) newColDef;
|
constraintIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* there can only be one DEFAULT constraint that can be used per column */
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constraintIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1638,6 +1677,49 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DeparserSupportsAlterTableAddColumn returns true if it's safe to deparse
|
||||||
|
* the given ALTER TABLE statement that is known to contain given ADD COLUMN
|
||||||
|
* subcommand.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
DeparserSupportsAlterTableAddColumn(AlterTableStmt *alterTableStatement,
|
||||||
|
AlterTableCmd *addColumnSubCommand)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We support deparsing for ADD COLUMN only of it's the only
|
||||||
|
* subcommand.
|
||||||
|
*/
|
||||||
|
if (list_length(alterTableStatement->cmds) == 1 &&
|
||||||
|
alterTableStatement->objtype == OBJECT_TABLE)
|
||||||
|
{
|
||||||
|
ColumnDef *columnDefinition = (ColumnDef *) addColumnSubCommand->def;
|
||||||
|
Constraint *constraint = NULL;
|
||||||
|
foreach_ptr(constraint, columnDefinition->constraints)
|
||||||
|
{
|
||||||
|
if (constraint->contype == CONSTR_CHECK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Given that we're in the preprocess, any reference to the
|
||||||
|
* column that we're adding would break the deparser. This
|
||||||
|
* can only be the case with CHECK constraints. For this
|
||||||
|
* reason, we skip deparsing the command and fall back to
|
||||||
|
* legacy behavior that we follow for ADD COLUMN subcommands.
|
||||||
|
*
|
||||||
|
* For other constraint types, we prepare the constraint to
|
||||||
|
* make sure that we can deparse it.
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ATDefinesFKeyBetweenPostgresAndCitusLocalOrRef returns true if given
|
* ATDefinesFKeyBetweenPostgresAndCitusLocalOrRef returns true if given
|
||||||
* alter table command defines foreign key between a postgres table and a
|
* alter table command defines foreign key between a postgres table and a
|
||||||
|
@ -2637,7 +2719,9 @@ PostprocessAlterTableStmt(AlterTableStmt *alterTableStatement)
|
||||||
columnDefinition
|
columnDefinition
|
||||||
->colname,
|
->colname,
|
||||||
columnDefinition
|
columnDefinition
|
||||||
->typeName);
|
->typeName,
|
||||||
|
command->
|
||||||
|
missing_ok);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2902,7 +2986,7 @@ GetAlterColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId, char *colna
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
GetAddColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId, char *colname,
|
GetAddColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId, char *colname,
|
||||||
TypeName *typeName)
|
TypeName *typeName, bool ifNotExists)
|
||||||
{
|
{
|
||||||
char *qualifiedSequenceName = generate_qualified_relation_name(sequenceOid);
|
char *qualifiedSequenceName = generate_qualified_relation_name(sequenceOid);
|
||||||
char *qualifiedRelationName = generate_qualified_relation_name(relationId);
|
char *qualifiedRelationName = generate_qualified_relation_name(relationId);
|
||||||
|
@ -2927,8 +3011,9 @@ GetAddColumnWithNextvalDefaultCmd(Oid sequenceOid, Oid relationId, char *colname
|
||||||
StringInfoData str = { 0 };
|
StringInfoData str = { 0 };
|
||||||
initStringInfo(&str);
|
initStringInfo(&str);
|
||||||
appendStringInfo(&str,
|
appendStringInfo(&str,
|
||||||
"ALTER TABLE %s ADD COLUMN %s %s "
|
"ALTER TABLE %s ADD COLUMN %s %s %s "
|
||||||
"DEFAULT %s(%s::regclass)", qualifiedRelationName, colname,
|
"DEFAULT %s(%s::regclass)", qualifiedRelationName,
|
||||||
|
ifNotExists ? "IF NOT EXISTS" : "", colname,
|
||||||
format_type_extended(typeOid, typmod, formatFlags),
|
format_type_extended(typeOid, typmod, formatFlags),
|
||||||
quote_qualified_identifier("pg_catalog", nextvalFunctionName),
|
quote_qualified_identifier("pg_catalog", nextvalFunctionName),
|
||||||
quote_literal_cstr(qualifiedSequenceName));
|
quote_literal_cstr(qualifiedSequenceName));
|
||||||
|
@ -3676,13 +3761,6 @@ SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command)
|
||||||
}
|
}
|
||||||
else if (alterTableType == AT_AddColumn)
|
else if (alterTableType == AT_AddColumn)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* TODO: This code path will never be executed since we do not
|
|
||||||
* support foreign constraint creation via
|
|
||||||
* ALTER TABLE %s ADD COLUMN %s [constraint]. However, the code
|
|
||||||
* is kept in case we fix the constraint creation without a name
|
|
||||||
* and allow foreign key creation with the mentioned command.
|
|
||||||
*/
|
|
||||||
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
||||||
List *columnConstraints = columnDefinition->constraints;
|
List *columnConstraints = columnDefinition->constraints;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
*/
|
*/
|
||||||
#include "postgres.h"
|
#include "postgres.h"
|
||||||
|
|
||||||
|
#include "catalog/heap.h"
|
||||||
|
#include "commands/defrem.h"
|
||||||
#include "distributed/commands.h"
|
#include "distributed/commands.h"
|
||||||
#include "distributed/deparser.h"
|
#include "distributed/deparser.h"
|
||||||
#include "distributed/version_compat.h"
|
#include "distributed/version_compat.h"
|
||||||
|
@ -30,7 +32,8 @@ static void AppendAlterTableSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *st
|
||||||
static void AppendAlterTableStmt(StringInfo buf, AlterTableStmt *stmt);
|
static void AppendAlterTableStmt(StringInfo buf, AlterTableStmt *stmt);
|
||||||
static void AppendAlterTableCmd(StringInfo buf, AlterTableCmd *alterTableCmd,
|
static void AppendAlterTableCmd(StringInfo buf, AlterTableCmd *alterTableCmd,
|
||||||
AlterTableStmt *stmt);
|
AlterTableStmt *stmt);
|
||||||
static void AppendAlterTableCmdAddColumn(StringInfo buf, AlterTableCmd *alterTableCmd);
|
static void AppendAlterTableCmdAddColumn(StringInfo buf, AlterTableCmd *alterTableCmd,
|
||||||
|
AlterTableStmt *stmt);
|
||||||
static void AppendAlterTableCmdDropConstraint(StringInfo buf,
|
static void AppendAlterTableCmdDropConstraint(StringInfo buf,
|
||||||
AlterTableCmd *alterTableCmd);
|
AlterTableCmd *alterTableCmd);
|
||||||
|
|
||||||
|
@ -142,13 +145,19 @@ AppendColumnNameList(StringInfo buf, List *columns)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AppendAlterTableCmdAddConstraint builds the add constraint command for index constraints
|
* AppendAlterTableCmdConstraint builds a string required to create given
|
||||||
* in the ADD CONSTRAINT <conname> {PRIMARY KEY, UNIQUE, EXCLUSION} form and appends it to the buf.
|
* constraint as part of an ADD CONSTRAINT or an ADD COLUMN subcommand,
|
||||||
|
* and appends it to the buf.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
AppendAlterTableCmdConstraint(StringInfo buf, Constraint *constraint,
|
||||||
AlterTableStmt *stmt)
|
AlterTableStmt *stmt, AlterTableType subtype)
|
||||||
{
|
{
|
||||||
|
if (subtype != AT_AddConstraint && subtype != AT_AddColumn)
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("Unsupported alter table subtype: %d", (int) subtype)));
|
||||||
|
}
|
||||||
|
|
||||||
/* Need to deparse the alter table constraint command only if we are adding a constraint name.*/
|
/* Need to deparse the alter table constraint command only if we are adding a constraint name.*/
|
||||||
if (constraint->conname == NULL)
|
if (constraint->conname == NULL)
|
||||||
{
|
{
|
||||||
|
@ -156,7 +165,15 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
"Constraint name can not be NULL when deparsing the constraint.")));
|
"Constraint name can not be NULL when deparsing the constraint.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
appendStringInfoString(buf, " ADD CONSTRAINT ");
|
if (subtype == AT_AddConstraint)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " ADD CONSTRAINT ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " CONSTRAINT ");
|
||||||
|
}
|
||||||
|
|
||||||
appendStringInfo(buf, "%s ", quote_identifier(constraint->conname));
|
appendStringInfo(buf, "%s ", quote_identifier(constraint->conname));
|
||||||
|
|
||||||
/* postgres version >= PG15
|
/* postgres version >= PG15
|
||||||
|
@ -184,7 +201,10 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
AppendColumnNameList(buf, constraint->keys);
|
if (subtype == AT_AddConstraint)
|
||||||
|
{
|
||||||
|
AppendColumnNameList(buf, constraint->keys);
|
||||||
|
}
|
||||||
|
|
||||||
if (constraint->including != NULL)
|
if (constraint->including != NULL)
|
||||||
{
|
{
|
||||||
|
@ -192,6 +212,24 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
|
|
||||||
AppendColumnNameList(buf, constraint->including);
|
AppendColumnNameList(buf, constraint->including);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (constraint->options != NIL)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " WITH(");
|
||||||
|
|
||||||
|
ListCell *defListCell;
|
||||||
|
foreach(defListCell, constraint->options)
|
||||||
|
{
|
||||||
|
DefElem *def = (DefElem *) lfirst(defListCell);
|
||||||
|
|
||||||
|
bool first = (defListCell == list_head(constraint->options));
|
||||||
|
appendStringInfo(buf, "%s%s=%s", first ? "" : ",",
|
||||||
|
quote_identifier(def->defname),
|
||||||
|
quote_literal_cstr(defGetString(def)));
|
||||||
|
}
|
||||||
|
|
||||||
|
appendStringInfoChar(buf, ')');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (constraint->contype == CONSTR_EXCLUSION)
|
else if (constraint->contype == CONSTR_EXCLUSION)
|
||||||
{
|
{
|
||||||
|
@ -240,6 +278,18 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
}
|
}
|
||||||
else if (constraint->contype == CONSTR_CHECK)
|
else if (constraint->contype == CONSTR_CHECK)
|
||||||
{
|
{
|
||||||
|
if (subtype == AT_AddColumn)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Preprocess should've rejected deparsing such an ALTER TABLE
|
||||||
|
* command but be on the safe side.
|
||||||
|
*/
|
||||||
|
ereport(ERROR, (errmsg("cannot add check constraint to column by "
|
||||||
|
"using ADD COLUMN command"),
|
||||||
|
errhint("Consider using ALTER TABLE ... ADD CONSTRAINT "
|
||||||
|
"... CHECK command after adding the column")));
|
||||||
|
}
|
||||||
|
|
||||||
LOCKMODE lockmode = AlterTableGetLockLevel(stmt->cmds);
|
LOCKMODE lockmode = AlterTableGetLockLevel(stmt->cmds);
|
||||||
Oid leftRelationId = AlterTableLookupRelation(stmt, lockmode);
|
Oid leftRelationId = AlterTableLookupRelation(stmt, lockmode);
|
||||||
|
|
||||||
|
@ -275,9 +325,12 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
}
|
}
|
||||||
else if (constraint->contype == CONSTR_FOREIGN)
|
else if (constraint->contype == CONSTR_FOREIGN)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, " FOREIGN KEY");
|
if (subtype == AT_AddConstraint)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " FOREIGN KEY");
|
||||||
|
|
||||||
AppendColumnNameList(buf, constraint->fk_attrs);
|
AppendColumnNameList(buf, constraint->fk_attrs);
|
||||||
|
}
|
||||||
|
|
||||||
appendStringInfoString(buf, " REFERENCES");
|
appendStringInfoString(buf, " REFERENCES");
|
||||||
|
|
||||||
|
@ -379,12 +432,32 @@ AppendAlterTableCmdAddConstraint(StringInfo buf, Constraint *constraint,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FOREIGN KEY and CHECK constraints migth have NOT VALID option */
|
/*
|
||||||
if (constraint->skip_validation)
|
* For ADD CONSTRAINT subcommand, FOREIGN KEY and CHECK constraints migth
|
||||||
|
* have NOT VALID option.
|
||||||
|
*
|
||||||
|
* Note that skip_validation might be true for an ADD COLUMN too but this
|
||||||
|
* is not because Postgres supports this but because Citus sets this flag
|
||||||
|
* to true for foreign key constraints added via ADD COLUMN. So we don't
|
||||||
|
* check for skip_validation for ADD COLUMN subcommand.
|
||||||
|
*/
|
||||||
|
if (subtype == AT_AddConstraint && constraint->skip_validation)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, " NOT VALID ");
|
appendStringInfoString(buf, " NOT VALID ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (subtype == AT_AddColumn &&
|
||||||
|
(constraint->deferrable || constraint->initdeferred))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For ADD COLUMN subcommand, the fact that whether given constraint
|
||||||
|
* is deferrable or initially deferred is indicated by another Constraint
|
||||||
|
* object, not via deferrable / initdeferred fields.
|
||||||
|
*/
|
||||||
|
ereport(ERROR, (errmsg("unexpected value set for deferrable/initdeferred "
|
||||||
|
"field for an ADD COLUMN subcommand")));
|
||||||
|
}
|
||||||
|
|
||||||
if (constraint->deferrable)
|
if (constraint->deferrable)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, " DEFERRABLE");
|
appendStringInfoString(buf, " DEFERRABLE");
|
||||||
|
@ -409,7 +482,7 @@ AppendAlterTableCmd(StringInfo buf, AlterTableCmd *alterTableCmd, AlterTableStmt
|
||||||
{
|
{
|
||||||
case AT_AddColumn:
|
case AT_AddColumn:
|
||||||
{
|
{
|
||||||
AppendAlterTableCmdAddColumn(buf, alterTableCmd);
|
AppendAlterTableCmdAddColumn(buf, alterTableCmd, stmt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,7 +502,7 @@ AppendAlterTableCmd(StringInfo buf, AlterTableCmd *alterTableCmd, AlterTableStmt
|
||||||
*/
|
*/
|
||||||
if (ConstrTypeCitusCanDefaultName(constraint->contype))
|
if (ConstrTypeCitusCanDefaultName(constraint->contype))
|
||||||
{
|
{
|
||||||
AppendAlterTableCmdAddConstraint(buf, constraint, stmt);
|
AppendAlterTableCmdConstraint(buf, constraint, stmt, AT_AddConstraint);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -445,28 +518,81 @@ AppendAlterTableCmd(StringInfo buf, AlterTableCmd *alterTableCmd, AlterTableStmt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GeneratedWhenStr returns the char representation of given generated_when
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
GeneratedWhenStr(char generatedWhen)
|
||||||
|
{
|
||||||
|
switch (generatedWhen)
|
||||||
|
{
|
||||||
|
case 'a':
|
||||||
|
{
|
||||||
|
return "ALWAYS";
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'd':
|
||||||
|
{
|
||||||
|
return "BY DEFAULT";
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ereport(ERROR, (errmsg("unrecognized generated_when: %d",
|
||||||
|
generatedWhen)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DeparseRawExprForColumnDefault returns string representation of given
|
||||||
|
* rawExpr based on given column type information.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
DeparseRawExprForColumnDefault(Oid relationId, Oid columnTypeId, int32 columnTypeMod,
|
||||||
|
char *columnName, char attgenerated, Node *rawExpr)
|
||||||
|
{
|
||||||
|
ParseState *pstate = make_parsestate(NULL);
|
||||||
|
Relation relation = RelationIdGetRelation(relationId);
|
||||||
|
AddRangeTableEntryToQueryCompat(pstate, relation);
|
||||||
|
|
||||||
|
Node *defaultExpr = cookDefault(pstate, rawExpr,
|
||||||
|
columnTypeId, columnTypeMod,
|
||||||
|
columnName, attgenerated);
|
||||||
|
|
||||||
|
List *deparseContext = deparse_context_for(get_rel_name(relationId), relationId);
|
||||||
|
|
||||||
|
PushOverrideEmptySearchPath(CurrentMemoryContext);
|
||||||
|
char *defaultExprStr = deparse_expression(defaultExpr, deparseContext, false, false);
|
||||||
|
PopOverrideSearchPath();
|
||||||
|
|
||||||
|
RelationClose(relation);
|
||||||
|
|
||||||
|
return defaultExprStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AppendAlterTableCmd builds and appends to the given buffer an AT_AddColumn command
|
* AppendAlterTableCmd builds and appends to the given buffer an AT_AddColumn command
|
||||||
* from given AlterTableCmd object in the form ADD COLUMN ...
|
* from given AlterTableCmd object in the form ADD COLUMN ...
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
AppendAlterTableCmdAddColumn(StringInfo buf, AlterTableCmd *alterTableCmd)
|
AppendAlterTableCmdAddColumn(StringInfo buf, AlterTableCmd *alterTableCmd,
|
||||||
|
AlterTableStmt *stmt)
|
||||||
{
|
{
|
||||||
Assert(alterTableCmd->subtype == AT_AddColumn);
|
Assert(alterTableCmd->subtype == AT_AddColumn);
|
||||||
|
|
||||||
|
Oid relationId = AlterTableLookupRelation(stmt, NoLock);
|
||||||
|
|
||||||
appendStringInfoString(buf, " ADD COLUMN ");
|
appendStringInfoString(buf, " ADD COLUMN ");
|
||||||
|
|
||||||
ColumnDef *columnDefinition = (ColumnDef *) alterTableCmd->def;
|
if (alterTableCmd->missing_ok)
|
||||||
|
|
||||||
/*
|
|
||||||
* the way we use the deparser now, constraints are always NULL
|
|
||||||
* adding this check for ColumnDef consistency
|
|
||||||
*/
|
|
||||||
if (columnDefinition->constraints != NULL)
|
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errmsg("Constraints are not supported for AT_AddColumn")));
|
appendStringInfoString(buf, "IF NOT EXISTS ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ColumnDef *columnDefinition = (ColumnDef *) alterTableCmd->def;
|
||||||
|
|
||||||
if (columnDefinition->colname)
|
if (columnDefinition->colname)
|
||||||
{
|
{
|
||||||
appendStringInfo(buf, "%s ", quote_identifier(columnDefinition->colname));
|
appendStringInfo(buf, "%s ", quote_identifier(columnDefinition->colname));
|
||||||
|
@ -478,23 +604,87 @@ AppendAlterTableCmdAddColumn(StringInfo buf, AlterTableCmd *alterTableCmd)
|
||||||
typenameTypeIdAndMod(NULL, columnDefinition->typeName, &typeOid, &typmod);
|
typenameTypeIdAndMod(NULL, columnDefinition->typeName, &typeOid, &typmod);
|
||||||
appendStringInfo(buf, "%s", format_type_extended(typeOid, typmod,
|
appendStringInfo(buf, "%s", format_type_extended(typeOid, typmod,
|
||||||
formatFlags));
|
formatFlags));
|
||||||
if (columnDefinition->is_not_null)
|
|
||||||
|
if (columnDefinition->compression)
|
||||||
{
|
{
|
||||||
appendStringInfoString(buf, " NOT NULL");
|
appendStringInfo(buf, " COMPRESSION %s",
|
||||||
|
quote_identifier(columnDefinition->compression));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* the way we use the deparser now, collation is never used
|
|
||||||
* since the data type of columns that use sequences for default
|
|
||||||
* are only int,smallint and bigint (never text, varchar, char)
|
|
||||||
* Adding this part only for ColumnDef consistency
|
|
||||||
*/
|
|
||||||
Oid collationOid = GetColumnDefCollation(NULL, columnDefinition, typeOid);
|
Oid collationOid = GetColumnDefCollation(NULL, columnDefinition, typeOid);
|
||||||
if (OidIsValid(collationOid))
|
if (OidIsValid(collationOid))
|
||||||
{
|
{
|
||||||
const char *identifier = FormatCollateBEQualified(collationOid);
|
const char *identifier = FormatCollateBEQualified(collationOid);
|
||||||
appendStringInfo(buf, " COLLATE %s", identifier);
|
appendStringInfo(buf, " COLLATE %s", identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ListCell *constraintCell = NULL;
|
||||||
|
foreach(constraintCell, columnDefinition->constraints)
|
||||||
|
{
|
||||||
|
Constraint *constraint = (Constraint *) lfirst(constraintCell);
|
||||||
|
|
||||||
|
if (constraint->contype == CONSTR_NOTNULL)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " NOT NULL");
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_DEFAULT)
|
||||||
|
{
|
||||||
|
char attgenerated = '\0';
|
||||||
|
appendStringInfo(buf, " DEFAULT %s",
|
||||||
|
DeparseRawExprForColumnDefault(relationId, typeOid, typmod,
|
||||||
|
columnDefinition->colname,
|
||||||
|
attgenerated,
|
||||||
|
constraint->raw_expr));
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_IDENTITY)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Citus doesn't support adding identity columns via ALTER TABLE,
|
||||||
|
* so we don't bother teaching the deparser about them.
|
||||||
|
*/
|
||||||
|
ereport(ERROR, (errmsg("unexpectedly found identity column "
|
||||||
|
"definition in ALTER TABLE command")));
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_GENERATED)
|
||||||
|
{
|
||||||
|
char attgenerated = 's';
|
||||||
|
appendStringInfo(buf, " GENERATED %s AS (%s) STORED",
|
||||||
|
GeneratedWhenStr(constraint->generated_when),
|
||||||
|
DeparseRawExprForColumnDefault(relationId, typeOid, typmod,
|
||||||
|
columnDefinition->colname,
|
||||||
|
attgenerated,
|
||||||
|
constraint->raw_expr));
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_CHECK ||
|
||||||
|
constraint->contype == CONSTR_PRIMARY ||
|
||||||
|
constraint->contype == CONSTR_UNIQUE ||
|
||||||
|
constraint->contype == CONSTR_EXCLUSION ||
|
||||||
|
constraint->contype == CONSTR_FOREIGN)
|
||||||
|
{
|
||||||
|
AppendAlterTableCmdConstraint(buf, constraint, stmt, AT_AddColumn);
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_ATTR_DEFERRABLE)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " DEFERRABLE");
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_ATTR_NOT_DEFERRABLE)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " NOT DEFERRABLE");
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_ATTR_DEFERRED)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " INITIALLY DEFERRED");
|
||||||
|
}
|
||||||
|
else if (constraint->contype == CONSTR_ATTR_IMMEDIATE)
|
||||||
|
{
|
||||||
|
appendStringInfoString(buf, " INITIALLY IMMEDIATE");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ereport(ERROR, (errmsg("unsupported constraint type"),
|
||||||
|
errdetail("constraint type: %d", constraint->contype)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,9 @@
|
||||||
#include "utils/relcache.h"
|
#include "utils/relcache.h"
|
||||||
|
|
||||||
/* Local functions forward declarations */
|
/* Local functions forward declarations */
|
||||||
|
static void RelayEventExtendConstraintAndIndexNames(AlterTableStmt *alterTableStmt,
|
||||||
|
Constraint *constraint,
|
||||||
|
uint64 shardId);
|
||||||
static bool UpdateWholeRowColumnReferencesWalker(Node *node, uint64 *shardId);
|
static bool UpdateWholeRowColumnReferencesWalker(Node *node, uint64 *shardId);
|
||||||
|
|
||||||
/* exports for SQL callable functions */
|
/* exports for SQL callable functions */
|
||||||
|
@ -150,43 +153,17 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
if (command->subtype == AT_AddConstraint)
|
if (command->subtype == AT_AddConstraint)
|
||||||
{
|
{
|
||||||
Constraint *constraint = (Constraint *) command->def;
|
Constraint *constraint = (Constraint *) command->def;
|
||||||
char **constraintName = &(constraint->conname);
|
RelayEventExtendConstraintAndIndexNames(alterTableStmt, constraint,
|
||||||
const bool missingOk = false;
|
shardId);
|
||||||
relationId = RangeVarGetRelid(alterTableStmt->relation,
|
}
|
||||||
AccessShareLock,
|
else if (command->subtype == AT_AddColumn)
|
||||||
missingOk);
|
{
|
||||||
|
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
||||||
if (constraint->indexname)
|
Constraint *constraint = NULL;
|
||||||
|
foreach_ptr(constraint, columnDefinition->constraints)
|
||||||
{
|
{
|
||||||
char **indexName = &(constraint->indexname);
|
RelayEventExtendConstraintAndIndexNames(alterTableStmt,
|
||||||
AppendShardIdToName(indexName, shardId);
|
constraint, shardId);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Append shardId to constraint names if
|
|
||||||
* - table is not partitioned or
|
|
||||||
* - constraint is not a CHECK constraint
|
|
||||||
*
|
|
||||||
* We do not want to append shardId to partitioned table shards because
|
|
||||||
* the names of constraints will be inherited, and the shardId will no
|
|
||||||
* longer be valid for the child table.
|
|
||||||
*
|
|
||||||
* See MergeConstraintsIntoExisting function in Postgres that requires
|
|
||||||
* inherited check constraints in child tables to have the same name
|
|
||||||
* with those in parent tables.
|
|
||||||
*/
|
|
||||||
if (!PartitionedTable(relationId) ||
|
|
||||||
constraint->contype != CONSTR_CHECK)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* constraint->conname could be empty in the case of
|
|
||||||
* ADD {PRIMARY KEY, UNIQUE} USING INDEX.
|
|
||||||
* In this case, already extended index name will be used by postgres.
|
|
||||||
*/
|
|
||||||
if (constraint->conname != NULL)
|
|
||||||
{
|
|
||||||
AppendShardIdToName(constraintName, shardId);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (command->subtype == AT_DropConstraint ||
|
else if (command->subtype == AT_DropConstraint ||
|
||||||
|
@ -622,6 +599,56 @@ RelayEventExtendNames(Node *parseTree, char *schemaName, uint64 shardId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RelayEventExtendConstraintAndIndexNames extends the names of constraints
|
||||||
|
* and indexes in given constraint with the shardId.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
RelayEventExtendConstraintAndIndexNames(AlterTableStmt *alterTableStmt,
|
||||||
|
Constraint *constraint,
|
||||||
|
uint64 shardId)
|
||||||
|
{
|
||||||
|
char **constraintName = &(constraint->conname);
|
||||||
|
const bool missingOk = false;
|
||||||
|
Oid relationId = RangeVarGetRelid(alterTableStmt->relation,
|
||||||
|
AccessShareLock,
|
||||||
|
missingOk);
|
||||||
|
|
||||||
|
if (constraint->indexname)
|
||||||
|
{
|
||||||
|
char **indexName = &(constraint->indexname);
|
||||||
|
AppendShardIdToName(indexName, shardId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append shardId to constraint names if
|
||||||
|
* - table is not partitioned or
|
||||||
|
* - constraint is not a CHECK constraint
|
||||||
|
*
|
||||||
|
* We do not want to append shardId to partitioned table shards because
|
||||||
|
* the names of constraints will be inherited, and the shardId will no
|
||||||
|
* longer be valid for the child table.
|
||||||
|
*
|
||||||
|
* See MergeConstraintsIntoExisting function in Postgres that requires
|
||||||
|
* inherited check constraints in child tables to have the same name
|
||||||
|
* with those in parent tables.
|
||||||
|
*/
|
||||||
|
if (!PartitionedTable(relationId) ||
|
||||||
|
constraint->contype != CONSTR_CHECK)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* constraint->conname could be empty in the case of
|
||||||
|
* ADD {PRIMARY KEY, UNIQUE} USING INDEX.
|
||||||
|
* In this case, already extended index name will be used by postgres.
|
||||||
|
*/
|
||||||
|
if (constraint->conname != NULL)
|
||||||
|
{
|
||||||
|
AppendShardIdToName(constraintName, shardId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelayEventExtendNamesForInterShardCommands extends relation names in the given parse
|
* RelayEventExtendNamesForInterShardCommands extends relation names in the given parse
|
||||||
* tree for certain utility commands. The function more specifically extends table, index
|
* tree for certain utility commands. The function more specifically extends table, index
|
||||||
|
@ -660,13 +687,6 @@ RelayEventExtendNamesForInterShardCommands(Node *parseTree, uint64 leftShardId,
|
||||||
}
|
}
|
||||||
else if (command->subtype == AT_AddColumn)
|
else if (command->subtype == AT_AddColumn)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* TODO: This code path will never be executed since we do not
|
|
||||||
* support foreign constraint creation via
|
|
||||||
* ALTER TABLE %s ADD COLUMN %s [constraint]. However, the code
|
|
||||||
* is kept in case we fix the constraint creation without a name
|
|
||||||
* and allow foreign key creation with the mentioned command.
|
|
||||||
*/
|
|
||||||
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
ColumnDef *columnDefinition = (ColumnDef *) command->def;
|
||||||
List *columnConstraints = columnDefinition->constraints;
|
List *columnConstraints = columnDefinition->constraints;
|
||||||
|
|
||||||
|
|
|
@ -582,6 +582,8 @@ extern bool ShouldEnableLocalReferenceForeignKeys(void);
|
||||||
extern List * PreprocessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement,
|
extern List * PreprocessAlterTableStmtAttachPartition(AlterTableStmt *alterTableStatement,
|
||||||
const char *queryString);
|
const char *queryString);
|
||||||
extern List * PostprocessAlterTableSchemaStmt(Node *node, const char *queryString);
|
extern List * PostprocessAlterTableSchemaStmt(Node *node, const char *queryString);
|
||||||
|
extern void PrepareAlterTableStmtForConstraint(AlterTableStmt *alterTableStatement,
|
||||||
|
Oid relationId, Constraint *constraint);
|
||||||
extern List * PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
extern List * PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
|
||||||
ProcessUtilityContext processUtilityContext);
|
ProcessUtilityContext processUtilityContext);
|
||||||
extern List * PreprocessAlterTableMoveAllStmt(Node *node, const char *queryString,
|
extern List * PreprocessAlterTableMoveAllStmt(Node *node, const char *queryString,
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
CREATE SCHEMA alter_table_add_column;
|
||||||
|
SET search_path TO alter_table_add_column;
|
||||||
|
SET citus.next_shard_id TO 1830000;
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SET client_min_messages TO NOTICE;
|
||||||
|
CREATE TABLE referenced (int_col integer PRIMARY KEY);
|
||||||
|
CREATE TABLE referencing (text_col text);
|
||||||
|
SELECT create_distributed_table('referenced', null);
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT create_distributed_table('referencing', null);
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
CREATE SCHEMA alter_table_add_column_other_schema;
|
||||||
|
CREATE OR REPLACE FUNCTION alter_table_add_column_other_schema.my_random(numeric)
|
||||||
|
RETURNS numeric AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN 7 * $1;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
CREATE COLLATION caseinsensitive (
|
||||||
|
provider = icu,
|
||||||
|
locale = 'und-u-ks-level2'
|
||||||
|
);
|
||||||
|
CREATE TYPE "simple_!\'custom_type" AS (a integer, b integer);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_1 integer DEFAULT (alter_table_add_column_other_schema.my_random(7) + random() + 5) NOT NULL CONSTRAINT fkey REFERENCES referenced(int_col) ON UPDATE SET DEFAULT ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_2 integer UNIQUE REFERENCES referenced(int_col) ON UPDATE CASCADE ON DELETE SET DEFAULT NOT DEFERRABLE INITIALLY IMMEDIATE;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_3 integer GENERATED ALWAYS AS (test_1 * alter_table_add_column_other_schema.my_random(1)) STORED UNIQUE REFERENCES referenced(int_col) MATCH FULL;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_4 integer PRIMARY KEY WITH (fillfactor=70) NOT NULL REFERENCES referenced(int_col) MATCH SIMPLE ON UPDATE CASCADE ON DELETE SET DEFAULT;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_5 integer CONSTRAINT unique_c UNIQUE WITH (fillfactor=50);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_6 text COMPRESSION pglz COLLATE caseinsensitive NOT NULL;
|
||||||
|
ALTER TABLE referencing ADD COLUMN "test_\'!7" "simple_!\'custom_type";
|
||||||
|
-- we give up deparsing ALTER TABLE command if it needs to create a check constraint, and we fallback to legacy behavior
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_8 integer CHECK (test_8 > 0);
|
||||||
|
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
||||||
|
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
||||||
|
HINT: You can issue each command separately such as ALTER TABLE referencing ADD COLUMN test_8 data_type; ALTER TABLE referencing ADD CONSTRAINT constraint_name CHECK (check_expression);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
||||||
|
-- try to add test_6 again, but with IF NOT EXISTS
|
||||||
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
||||||
|
NOTICE: column "test_6" of relation "referencing" already exists, skipping
|
||||||
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 integer;
|
||||||
|
NOTICE: column "test_6" of relation "referencing" already exists, skipping
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('alter_table_add_column.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"deferred": true, "deferable": true, "on_delete": "c", "on_update": "d", "match_type": "s", "constraint_names": ["fkey"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "f", "constraint_names": ["referencing__fkey1"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_3"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey2"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_4"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": true, "deferable": true, "on_delete": "c", "on_update": "d", "match_type": "s", "constraint_names": ["fkey", "fkey_xxxxxxx"], "referenced_tables": ["alter_table_add_column.referenced", "alter_table_add_column.referenced_1830000"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing", "alter_table_add_column.referencing_1830001"], "referencing_columns": ["test_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey", "referencing__fkey_1830001"], "referenced_tables": ["alter_table_add_column.referenced", "alter_table_add_column.referenced_1830000"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing", "alter_table_add_column.referencing_1830001"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "f", "constraint_names": ["referencing__fkey1", "referencing__fkey1_1830001"], "referenced_tables": ["alter_table_add_column.referenced", "alter_table_add_column.referenced_1830000"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing", "alter_table_add_column.referencing_1830001"], "referencing_columns": ["test_3"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey2", "referencing__fkey2_1830001"], "referenced_tables": ["alter_table_add_column.referenced", "alter_table_add_column.referenced_1830000"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing", "alter_table_add_column.referencing_1830001"], "referencing_columns": ["test_4"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": true, "deferable": true, "on_delete": "c", "on_update": "d", "match_type": "s", "constraint_names": ["fkey"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "f", "constraint_names": ["referencing__fkey1"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_3"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "d", "on_update": "c", "match_type": "s", "constraint_names": ["referencing__fkey2"], "referenced_tables": ["alter_table_add_column.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["alter_table_add_column.referencing"], "referencing_columns": ["test_4"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('alter_table_add_column', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON alter_table_add_column.referencing USING btree (test_2)"], "indexnames": ["referencing__key"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON alter_table_add_column.referencing USING btree (test_3)"], "indexnames": ["referencing__key1"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing_pkey ON alter_table_add_column.referencing USING btree (test_4) WITH (fillfactor='70')"], "indexnames": ["referencing_pkey"]}, {"indexdefs": ["CREATE UNIQUE INDEX unique_c ON alter_table_add_column.referencing USING btree (test_5) WITH (fillfactor='50')"], "indexnames": ["unique_c"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON alter_table_add_column.referencing USING btree (test_2)", "CREATE UNIQUE INDEX referencing__key_1830001 ON alter_table_add_column.referencing_1830001 USING btree (test_2)"], "indexnames": ["referencing__key", "referencing__key_1830001"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON alter_table_add_column.referencing USING btree (test_3)", "CREATE UNIQUE INDEX referencing__key1_1830001 ON alter_table_add_column.referencing_1830001 USING btree (test_3)"], "indexnames": ["referencing__key1", "referencing__key1_1830001"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing_pkey ON alter_table_add_column.referencing USING btree (test_4) WITH (fillfactor='70')", "CREATE UNIQUE INDEX referencing_pkey_1830001 ON alter_table_add_column.referencing_1830001 USING btree (test_4) WITH (fillfactor='70')"], "indexnames": ["referencing_pkey", "referencing_pkey_1830001"]}, {"indexdefs": ["CREATE UNIQUE INDEX unique_c ON alter_table_add_column.referencing USING btree (test_5) WITH (fillfactor='50')", "CREATE UNIQUE INDEX unique_c_1830001 ON alter_table_add_column.referencing_1830001 USING btree (test_5) WITH (fillfactor='50')"], "indexnames": ["unique_c", "unique_c_1830001"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON alter_table_add_column.referencing USING btree (test_2)"], "indexnames": ["referencing__key"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON alter_table_add_column.referencing USING btree (test_3)"], "indexnames": ["referencing__key1"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing_pkey ON alter_table_add_column.referencing USING btree (test_4) WITH (fillfactor='70')"], "indexnames": ["referencing_pkey"]}, {"indexdefs": ["CREATE UNIQUE INDEX unique_c ON alter_table_add_column.referencing USING btree (test_5) WITH (fillfactor='50')"], "indexnames": ["unique_c"]}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_column_defaults FROM get_column_defaults('alter_table_add_column', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"column_name": "test_1", "column_default": "(((alter_table_add_column_other_schema.my_random((7)::numeric))::double precision + random()) + (5)::double precision)", "generation_expression": null}, {"column_name": "test_3", "column_default": null, "generation_expression": "((test_1)::numeric * alter_table_add_column_other_schema.my_random((1)::numeric))"}]
|
||||||
|
f | [{"column_name": "test_1", "column_default": "(((alter_table_add_column_other_schema.my_random((7)::numeric))::double precision + random()) + (5)::double precision)", "generation_expression": null}, {"column_name": "test_3", "column_default": null, "generation_expression": "((test_1)::numeric * alter_table_add_column_other_schema.my_random((1)::numeric))"}, {"column_name": "test_3", "column_default": null, "generation_expression": "((test_1)::numeric * alter_table_add_column_other_schema.my_random((1)::numeric))"}]
|
||||||
|
f | [{"column_name": "test_1", "column_default": "(((alter_table_add_column_other_schema.my_random((7)::numeric))::double precision + random()) + (5)::double precision)", "generation_expression": null}, {"column_name": "test_3", "column_default": null, "generation_expression": "((test_1)::numeric * alter_table_add_column_other_schema.my_random((1)::numeric))"}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_column_attrs FROM get_column_attrs('alter_table_add_column.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | {"relnames": ["alter_table_add_column.referencing"], "column_attrs": [{"not_null": true, "type_name": "int4", "column_name": "test_1", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_2", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_3", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "int4", "column_name": "test_4", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_5", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "text", "column_name": "test_6", "collation_name": "caseinsensitive", "compression_method": "p"}, {"not_null": false, "type_name": "int4", "column_name": "test_8", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "simple_!\\'custom_type", "column_name": "test_\\'!7", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "text", "column_name": "text_col", "collation_name": "default", "compression_method": ""}]}
|
||||||
|
f | {"relnames": ["alter_table_add_column.referencing"], "column_attrs": [{"not_null": true, "type_name": "int4", "column_name": "test_1", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_2", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_3", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "int4", "column_name": "test_4", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_5", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "text", "column_name": "test_6", "collation_name": "caseinsensitive", "compression_method": "p"}, {"not_null": false, "type_name": "int4", "column_name": "test_8", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "simple_!\\'custom_type", "column_name": "test_\\'!7", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "text", "column_name": "text_col", "collation_name": "default", "compression_method": ""}]}
|
||||||
|
f | {"relnames": ["alter_table_add_column.referencing_1830001", "alter_table_add_column.referencing"], "column_attrs": [{"not_null": true, "type_name": "int4", "column_name": "test_1", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_2", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_3", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "int4", "column_name": "test_4", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "int4", "column_name": "test_5", "collation_name": null, "compression_method": ""}, {"not_null": true, "type_name": "text", "column_name": "test_6", "collation_name": "caseinsensitive", "compression_method": "p"}, {"not_null": false, "type_name": "int4", "column_name": "test_8", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "simple_!\\'custom_type", "column_name": "test_\\'!7", "collation_name": null, "compression_method": ""}, {"not_null": false, "type_name": "text", "column_name": "text_col", "collation_name": "default", "compression_method": ""}]}
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA alter_table_add_column, alter_table_add_column_other_schema CASCADE;
|
|
@ -494,7 +494,7 @@ CREATE TABLE local_table_4 (
|
||||||
b int references local_table_4(a));
|
b int references local_table_4(a));
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (xxxxx, 'citus_local_tables_test_schema', xxxxx, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_tables_test_schema.local_table_4 ADD CONSTRAINT local_table_4_a_fkey FOREIGN KEY (a) REFERENCES citus_local_tables_test_schema.citus_local_table_1(a)')
|
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (xxxxx, 'citus_local_tables_test_schema', xxxxx, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_tables_test_schema.local_table_4 ADD CONSTRAINT local_table_4_a_fkey FOREIGN KEY (a) REFERENCES citus_local_tables_test_schema.citus_local_table_1(a)')
|
||||||
ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;
|
ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504014, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD COLUMN b int NOT NULL;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1504014, 'citus_local_tables_test_schema', 'ALTER TABLE citus_local_table_1 ADD COLUMN b integer NOT NULL;')
|
||||||
-- show that we added column with NOT NULL
|
-- show that we added column with NOT NULL
|
||||||
SELECT table_name, column_name, is_nullable
|
SELECT table_name, column_name, is_nullable
|
||||||
FROM INFORMATION_SCHEMA.COLUMNS
|
FROM INFORMATION_SCHEMA.COLUMNS
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA IF EXISTS columnar_test_helpers CASCADE;
|
||||||
|
RESET client_min_messages;
|
||||||
CREATE SCHEMA columnar_test_helpers;
|
CREATE SCHEMA columnar_test_helpers;
|
||||||
SET search_path TO columnar_test_helpers;
|
SET search_path TO columnar_test_helpers;
|
||||||
CREATE OR REPLACE FUNCTION columnar_storage_info(
|
CREATE OR REPLACE FUNCTION columnar_storage_info(
|
||||||
|
|
|
@ -11,7 +11,7 @@ SELECT pg_reload_conf();
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- Add some helper functions for sending commands to mitmproxy
|
-- Add some helper functions for sending commands to mitmproxy
|
||||||
CREATE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
CREATE OR REPLACE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
command ALIAS FOR $1;
|
command ALIAS FOR $1;
|
||||||
BEGIN
|
BEGIN
|
||||||
|
@ -26,52 +26,13 @@ BEGIN
|
||||||
RETURN QUERY SELECT * FROM mitmproxy_result;
|
RETURN QUERY SELECT * FROM mitmproxy_result;
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
CREATE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
CREATE OR REPLACE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
PERFORM citus.mitmproxy('recorder.reset()');
|
PERFORM citus.mitmproxy('recorder.reset()');
|
||||||
RETURN; -- return void
|
RETURN; -- return void
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
CREATE FUNCTION citus.dump_network_traffic()
|
CREATE OR REPLACE FUNCTION citus.dump_network_traffic()
|
||||||
RETURNS TABLE(conn int, source text, message text) AS $$
|
|
||||||
BEGIN
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_result (
|
|
||||||
conn int, source text, message text
|
|
||||||
) ON COMMIT DROP;
|
|
||||||
|
|
||||||
INSERT INTO mitmproxy_command VALUES ('recorder.dump()');
|
|
||||||
|
|
||||||
EXECUTE format('COPY mitmproxy_command TO %L', current_setting('citus.mitmfifo'));
|
|
||||||
EXECUTE format('COPY mitmproxy_result FROM %L', current_setting('citus.mitmfifo'));
|
|
||||||
|
|
||||||
RETURN QUERY SELECT * FROM mitmproxy_result;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
-- Add some helper functions for sending commands to mitmproxy
|
|
||||||
CREATE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
|
||||||
DECLARE
|
|
||||||
command ALIAS FOR $1;
|
|
||||||
BEGIN
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_result (res text) ON COMMIT DROP;
|
|
||||||
|
|
||||||
INSERT INTO mitmproxy_command VALUES (command);
|
|
||||||
|
|
||||||
EXECUTE format('COPY mitmproxy_command TO %L', current_setting('citus.mitmfifo'));
|
|
||||||
EXECUTE format('COPY mitmproxy_result FROM %L', current_setting('citus.mitmfifo'));
|
|
||||||
|
|
||||||
RETURN QUERY SELECT * FROM mitmproxy_result;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
CREATE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
|
||||||
BEGIN
|
|
||||||
PERFORM citus.mitmproxy('recorder.reset()');
|
|
||||||
RETURN; -- return void
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
CREATE FUNCTION citus.dump_network_traffic()
|
|
||||||
RETURNS TABLE(conn int, source text, message text) AS $$
|
RETURNS TABLE(conn int, source text, message text) AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
||||||
|
|
|
@ -123,10 +123,16 @@ BEGIN;
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- this actually attempts to convert local tables to citus local tables but errors out
|
BEGIN;
|
||||||
-- as citus doesn't support defining foreign keys via add column commands
|
ALTER TABLE local_table_1 ADD COLUMN col_3 INT REFERENCES reference_table_1(col_1);
|
||||||
ALTER TABLE local_table_1 ADD COLUMN col_3 INT REFERENCES reference_table_1(col_1);
|
-- show that we converted all 4 local tables in this schema to citus local tables
|
||||||
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
SELECT COUNT(*)=4 FROM citus_local_tables_in_schema;
|
||||||
|
?column?
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ROLLBACK;
|
||||||
BEGIN;
|
BEGIN;
|
||||||
-- define a foreign key so that all 4 local tables become citus local tables
|
-- define a foreign key so that all 4 local tables become citus local tables
|
||||||
ALTER TABLE local_table_1 ADD CONSTRAINT fkey_11 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1);
|
ALTER TABLE local_table_1 ADD CONSTRAINT fkey_11 FOREIGN KEY (col_1) REFERENCES reference_table_1(col_1);
|
||||||
|
|
|
@ -250,13 +250,10 @@ SELECT create_distributed_table('referencing_table', 'ref_id');
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER TABLE referencing_table ADD COLUMN referencing int REFERENCES referenced_table(id) ON UPDATE CASCADE;
|
ALTER TABLE referencing_table ADD COLUMN referencing int REFERENCES referenced_table(id) ON UPDATE CASCADE;
|
||||||
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
|
||||||
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
|
||||||
HINT: You can issue each command separately such as ALTER TABLE referencing_table ADD COLUMN referencing data_type; ALTER TABLE referencing_table ADD CONSTRAINT constraint_name FOREIGN KEY (referencing) REFERENCES referenced_table(id) ON UPDATE CASCADE;
|
|
||||||
SELECT COUNT(*) FROM table_fkeys_in_workers WHERE relid SIMILAR TO 'fkey_reference_table.%\d{2,}' AND refd_relid SIMILAR TO 'fkey_reference_table.%\d{2,}';
|
SELECT COUNT(*) FROM table_fkeys_in_workers WHERE relid SIMILAR TO 'fkey_reference_table.%\d{2,}' AND refd_relid SIMILAR TO 'fkey_reference_table.%\d{2,}';
|
||||||
count
|
count
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
0
|
8
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
DROP TABLE referencing_table;
|
DROP TABLE referencing_table;
|
||||||
|
|
|
@ -44,20 +44,12 @@ query |citus_nodename_for_nodeid|citus_n
|
||||||
step s3-view-worker:
|
step s3-view-worker:
|
||||||
SELECT query, citus_nodename_for_nodeid(citus_nodeid_for_gpid(global_pid)), citus_nodeport_for_nodeid(citus_nodeid_for_gpid(global_pid)), state, wait_event_type, wait_event, usename, datname FROM citus_stat_activity WHERE query NOT ILIKE ALL(VALUES('%pg_prepared_xacts%'), ('%COMMIT%'), ('%csa_from_one_node%')) AND is_worker_query = true AND backend_type = 'client backend' ORDER BY query DESC;
|
SELECT query, citus_nodename_for_nodeid(citus_nodeid_for_gpid(global_pid)), citus_nodeport_for_nodeid(citus_nodeid_for_gpid(global_pid)), state, wait_event_type, wait_event, usename, datname FROM citus_stat_activity WHERE query NOT ILIKE ALL(VALUES('%pg_prepared_xacts%'), ('%COMMIT%'), ('%csa_from_one_node%')) AND is_worker_query = true AND backend_type = 'client backend' ORDER BY query DESC;
|
||||||
|
|
||||||
query |citus_nodename_for_nodeid|citus_nodeport_for_nodeid|state |wait_event_type|wait_event|usename |datname
|
query |citus_nodename_for_nodeid|citus_nodeport_for_nodeid|state |wait_event_type|wait_event|usename |datname
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
SELECT worker_apply_shard_ddl_command (1300004, 'public', '
|
SELECT worker_apply_shard_ddl_command (1300004, 'public', 'ALTER TABLE test_table ADD COLUMN x integer;')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
||||||
ALTER TABLE test_table ADD COLUMN x INT;
|
SELECT worker_apply_shard_ddl_command (1300003, 'public', 'ALTER TABLE test_table ADD COLUMN x integer;')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
||||||
')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
SELECT worker_apply_shard_ddl_command (1300002, 'public', 'ALTER TABLE test_table ADD COLUMN x integer;')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
||||||
SELECT worker_apply_shard_ddl_command (1300003, 'public', '
|
SELECT worker_apply_shard_ddl_command (1300001, 'public', 'ALTER TABLE test_table ADD COLUMN x integer;')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
||||||
ALTER TABLE test_table ADD COLUMN x INT;
|
|
||||||
')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
|
||||||
SELECT worker_apply_shard_ddl_command (1300002, 'public', '
|
|
||||||
ALTER TABLE test_table ADD COLUMN x INT;
|
|
||||||
')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
|
||||||
SELECT worker_apply_shard_ddl_command (1300001, 'public', '
|
|
||||||
ALTER TABLE test_table ADD COLUMN x INT;
|
|
||||||
')|localhost | 57636|idle in transaction|Client |ClientRead|postgres|regression
|
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
step s2-rollback:
|
step s2-rollback:
|
||||||
|
|
|
@ -509,7 +509,7 @@ NOTICE: executing the command locally: DELETE FROM local_commands_test_schema.r
|
||||||
-- add another column to dist_table
|
-- add another column to dist_table
|
||||||
-- note that we execute below DDL locally as well
|
-- note that we execute below DDL locally as well
|
||||||
ALTER TABLE ref_table ADD b int;
|
ALTER TABLE ref_table ADD b int;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500035, 'local_commands_test_schema', 'ALTER TABLE ref_table ADD b int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500035, 'local_commands_test_schema', 'ALTER TABLE ref_table ADD COLUMN b integer;')
|
||||||
-- define self reference
|
-- define self reference
|
||||||
ALTER TABLE ref_table ADD CONSTRAINT fkey2 FOREIGN KEY(b) REFERENCES ref_table(a);
|
ALTER TABLE ref_table ADD CONSTRAINT fkey2 FOREIGN KEY(b) REFERENCES ref_table(a);
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1500035, 'local_commands_test_schema', 1500035, 'local_commands_test_schema', 'ALTER TABLE ref_table ADD CONSTRAINT fkey2 FOREIGN KEY(b) REFERENCES ref_table(a);')
|
NOTICE: executing the command locally: SELECT worker_apply_inter_shard_ddl_command (1500035, 'local_commands_test_schema', 1500035, 'local_commands_test_schema', 'ALTER TABLE ref_table ADD CONSTRAINT fkey2 FOREIGN KEY(b) REFERENCES ref_table(a);')
|
||||||
|
@ -629,17 +629,17 @@ NOTICE: executing the command locally: SELECT count(*) AS count FROM local_comm
|
||||||
|
|
||||||
-- execute bunch of DDL & DROP commands succesfully
|
-- execute bunch of DDL & DROP commands succesfully
|
||||||
ALTER TABLE dist_table ADD column c int;
|
ALTER TABLE dist_table ADD column c int;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500100, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500100, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500103, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500103, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500106, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500106, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500109, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500109, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500112, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500112, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500115, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500115, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500118, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500118, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500121, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500121, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500124, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500124, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500127, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500127, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500130, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500130, 'local_commands_test_schema', 'ALTER TABLE dist_table ADD COLUMN c integer;')
|
||||||
ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;
|
ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500100, 'local_commands_test_schema', 'ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500100, 'local_commands_test_schema', 'ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500103, 'local_commands_test_schema', 'ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500103, 'local_commands_test_schema', 'ALTER TABLE dist_table ALTER COLUMN c SET NOT NULL;')
|
||||||
|
@ -758,17 +758,17 @@ NOTICE: executing the command locally: SELECT count(*) AS count FROM local_comm
|
||||||
|
|
||||||
-- execute bunch of DDL & DROP commands succesfully
|
-- execute bunch of DDL & DROP commands succesfully
|
||||||
ALTER TABLE partitioning_test ADD column c int;
|
ALTER TABLE partitioning_test ADD column c int;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500165, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500165, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500168, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500168, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500171, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500171, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500174, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500174, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500177, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500177, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500180, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500180, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500183, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500183, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500186, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500186, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500189, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500189, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500192, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500192, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500195, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD column c int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1500195, 'local_commands_test_schema', 'ALTER TABLE partitioning_test ADD COLUMN c integer;')
|
||||||
TRUNCATE partitioning_test;
|
TRUNCATE partitioning_test;
|
||||||
NOTICE: executing the command locally: TRUNCATE TABLE local_commands_test_schema.partitioning_test_xxxxx CASCADE
|
NOTICE: executing the command locally: TRUNCATE TABLE local_commands_test_schema.partitioning_test_xxxxx CASCADE
|
||||||
NOTICE: executing the command locally: TRUNCATE TABLE local_commands_test_schema.partitioning_test_xxxxx CASCADE
|
NOTICE: executing the command locally: TRUNCATE TABLE local_commands_test_schema.partitioning_test_xxxxx CASCADE
|
||||||
|
|
|
@ -671,6 +671,27 @@ SELECT create_distributed_table('alter_add_unique', 'x');
|
||||||
ALTER TABLE alter_add_unique ADD CONSTRAINT unique_constraint_test UNIQUE USING INDEX alter_unique_idx;
|
ALTER TABLE alter_add_unique ADD CONSTRAINT unique_constraint_test UNIQUE USING INDEX alter_unique_idx;
|
||||||
NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "alter_unique_idx" to "unique_constraint_test"
|
NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "alter_unique_idx" to "unique_constraint_test"
|
||||||
ALTER TABLE alter_add_unique DROP CONSTRAINT unique_constraint_test;
|
ALTER TABLE alter_add_unique DROP CONSTRAINT unique_constraint_test;
|
||||||
|
CREATE TABLE unique_test_table_single_shard(id int, name varchar(20));
|
||||||
|
SELECT create_distributed_table('unique_test_table_single_shard', 'id', shard_count=>1);
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
ALTER TABLE unique_test_table_single_shard ADD UNIQUE(id, name) WITH (fillfactor=20);
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('sc3', 'unique_test_table_single_shard')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"indexdefs": ["CREATE UNIQUE INDEX unique_test_table_single_shard_id_name_key ON sc3.unique_test_table_single_shard USING btree (id, name) WITH (fillfactor='20')"], "indexnames": ["unique_test_table_single_shard_id_name_key"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX unique_test_table_single_shard_id_name_key ON sc3.unique_test_table_single_shard USING btree (id, name) WITH (fillfactor='20')", "CREATE UNIQUE INDEX unique_test_table_single_shard_id_name_key_1450242 ON sc3.unique_test_table_single_shard_1450242 USING btree (id, name) WITH (fillfactor='20')"], "indexnames": ["unique_test_table_single_shard_id_name_key", "unique_test_table_single_shard_id_name_key_1450242"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX unique_test_table_single_shard_id_name_key ON sc3.unique_test_table_single_shard USING btree (id, name) WITH (fillfactor='20')", "CREATE UNIQUE INDEX unique_test_table_single_shard_id_name_key_1450242 ON sc3.unique_test_table_single_shard_1450242 USING btree (id, name) WITH (fillfactor='20')"], "indexnames": ["unique_test_table_single_shard_id_name_key", "unique_test_table_single_shard_id_name_key_1450242"]}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
DROP TABLE unique_test_table_single_shard;
|
||||||
SET search_path TO 'public';
|
SET search_path TO 'public';
|
||||||
DROP SCHEMA sc1 CASCADE;
|
DROP SCHEMA sc1 CASCADE;
|
||||||
NOTICE: drop cascades to table sc1.alter_add_prim_key
|
NOTICE: drop cascades to table sc1.alter_add_prim_key
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
--
|
--
|
||||||
-- MULTI_ALTER_TABLE_STATEMENTS
|
-- MULTI_ALTER_TABLE_STATEMENTS
|
||||||
--
|
--
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 220000;
|
CREATE SCHEMA multi_alter_table_statements;
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 220000;
|
||||||
-- Check that we can run ALTER TABLE statements on distributed tables.
|
-- Check that we can run ALTER TABLE statements on distributed tables.
|
||||||
-- We set the shardid sequence here so that the shardids in this test
|
-- We set the shardid sequence here so that the shardids in this test
|
||||||
-- aren't affected by changes to the previous tests.
|
-- aren't affected by changes to the previous tests.
|
||||||
|
@ -48,6 +50,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' OR
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 221000;
|
||||||
-- Verify that we can add columns
|
-- Verify that we can add columns
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT;
|
ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT;
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN date_column DATE;
|
ALTER TABLE lineitem_alter ADD COLUMN date_column DATE;
|
||||||
|
@ -93,7 +97,9 @@ ORDER BY attnum;
|
||||||
(27 rows)
|
(27 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 222000;
|
||||||
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -153,7 +159,7 @@ SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
||||||
|
|
||||||
-- Verify that SET NOT NULL works
|
-- Verify that SET NOT NULL works
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -191,7 +197,7 @@ DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02,
|
||||||
END;
|
END;
|
||||||
-- Verify that DROP NOT NULL works
|
-- Verify that DROP NOT NULL works
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -235,7 +241,7 @@ SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP B
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -299,7 +305,7 @@ SELECT SUM(l_orderkey) FROM lineitem_alter;
|
||||||
53620791
|
53620791
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -324,7 +330,7 @@ SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineite
|
||||||
-- Verify that we can execute commands with multiple subcommands
|
-- Verify that we can execute commands with multiple subcommands
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER,
|
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER,
|
||||||
ADD COLUMN int_column2 INTEGER;
|
ADD COLUMN int_column2 INTEGER;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -353,7 +359,7 @@ ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER,
|
||||||
ERROR: alter table command is currently unsupported
|
ERROR: alter table command is currently unsupported
|
||||||
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported.
|
DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT, ADD|DROP|VALIDATE CONSTRAINT, SET (), RESET (), ENABLE|DISABLE|NO FORCE|FORCE ROW LEVEL SECURITY, ATTACH|DETACH PARTITION and TYPE subcommands are supported.
|
||||||
ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2;
|
ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -410,7 +416,7 @@ ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2;
|
||||||
NOTICE: relation "non_existent_table" does not exist, skipping
|
NOTICE: relation "non_existent_table" does not exist, skipping
|
||||||
-- Verify that none of the failed alter table commands took effect on the master
|
-- Verify that none of the failed alter table commands took effect on the master
|
||||||
-- node
|
-- node
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -461,7 +467,7 @@ BEGIN;
|
||||||
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
Column | Type | Modifiers
|
Column | Type | Modifiers
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
l_orderkey | bigint | not null
|
l_orderkey | bigint | not null
|
||||||
|
@ -536,8 +542,10 @@ SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
||||||
DROP INDEX temp_index_2;
|
DROP INDEX temp_index_2;
|
||||||
-- Add column on only one worker...
|
-- Add column on only one worker...
|
||||||
\c - - - :worker_2_port
|
\c - - - :worker_2_port
|
||||||
ALTER TABLE lineitem_alter_220000 ADD COLUMN first integer;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter_220000 ADD COLUMN first integer;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 223000;
|
||||||
-- and try to add it in a multi-statement block, which fails
|
-- and try to add it in a multi-statement block, which fails
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
||||||
|
@ -637,7 +645,7 @@ DROP INDEX replica_idx;
|
||||||
ALTER TABLE single_shard_items REPLICA IDENTITY default;
|
ALTER TABLE single_shard_items REPLICA IDENTITY default;
|
||||||
-- Drop the column from the worker...
|
-- Drop the column from the worker...
|
||||||
\c - - - :worker_2_port
|
\c - - - :worker_2_port
|
||||||
ALTER TABLE lineitem_alter_220000 DROP COLUMN first;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter_220000 DROP COLUMN first;
|
||||||
-- Create table to trigger at-xact-end (deferred) failure
|
-- Create table to trigger at-xact-end (deferred) failure
|
||||||
CREATE TABLE ddl_commands (command text UNIQUE DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE ddl_commands (command text UNIQUE DEFERRABLE INITIALLY DEFERRED);
|
||||||
-- Use an event trigger to log all DDL event tags in it
|
-- Use an event trigger to log all DDL event tags in it
|
||||||
|
@ -650,6 +658,8 @@ $ldt$ LANGUAGE plpgsql;
|
||||||
RESET citus.enable_metadata_sync;
|
RESET citus.enable_metadata_sync;
|
||||||
CREATE EVENT TRIGGER log_ddl_tag ON ddl_command_end EXECUTE PROCEDURE log_ddl_tag();
|
CREATE EVENT TRIGGER log_ddl_tag ON ddl_command_end EXECUTE PROCEDURE log_ddl_tag();
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 224000;
|
||||||
-- The above trigger will cause failure at transaction end on one placement.
|
-- The above trigger will cause failure at transaction end on one placement.
|
||||||
-- Citus always uses 2PC. 2PC should handle this "best" (no divergence)
|
-- Citus always uses 2PC. 2PC should handle this "best" (no divergence)
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -670,6 +680,8 @@ DROP EVENT TRIGGER log_ddl_tag;
|
||||||
DROP FUNCTION log_ddl_tag();
|
DROP FUNCTION log_ddl_tag();
|
||||||
DROP TABLE ddl_commands;
|
DROP TABLE ddl_commands;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 225000;
|
||||||
-- Distributed SELECTs may appear after ALTER
|
-- Distributed SELECTs may appear after ALTER
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
||||||
|
@ -724,7 +736,7 @@ SELECT create_distributed_table('test_ab', 'a', 'hash');
|
||||||
INSERT INTO test_ab VALUES (2, 10);
|
INSERT INTO test_ab VALUES (2, 10);
|
||||||
INSERT INTO test_ab VALUES (2, 11);
|
INSERT INTO test_ab VALUES (2, 11);
|
||||||
CREATE UNIQUE INDEX temp_unique_index_1 ON test_ab(a);
|
CREATE UNIQUE INDEX temp_unique_index_1 ON test_ab(a);
|
||||||
ERROR: could not create unique index "temp_unique_index_1_220011"
|
ERROR: could not create unique index "temp_unique_index_1_225006"
|
||||||
DETAIL: Key (a)=(2) is duplicated.
|
DETAIL: Key (a)=(2) is duplicated.
|
||||||
CONTEXT: while executing command on localhost:xxxxx
|
CONTEXT: while executing command on localhost:xxxxx
|
||||||
SELECT shardid FROM pg_dist_shard_placement NATURAL JOIN pg_dist_shard
|
SELECT shardid FROM pg_dist_shard_placement NATURAL JOIN pg_dist_shard
|
||||||
|
@ -775,6 +787,8 @@ ORDER BY attnum;
|
||||||
(30 rows)
|
(30 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 226000;
|
||||||
-- verify that we can rename distributed tables
|
-- verify that we can rename distributed tables
|
||||||
SHOW citus.enable_ddl_propagation;
|
SHOW citus.enable_ddl_propagation;
|
||||||
citus.enable_ddl_propagation
|
citus.enable_ddl_propagation
|
||||||
|
@ -796,24 +810,28 @@ SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_renamed%' ORDER BY re
|
||||||
relname
|
relname
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
lineitem_renamed_220000
|
lineitem_renamed_220000
|
||||||
lineitem_renamed_220001
|
lineitem_renamed_222000
|
||||||
lineitem_renamed_220003
|
lineitem_renamed_222002
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 227000;
|
||||||
-- revert it to original name
|
-- revert it to original name
|
||||||
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
||||||
-- show rename worked on one worker, too
|
-- show rename worked on one worker, too
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
relname
|
relname
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
lineitem_alter_220000
|
lineitem_alter_220000
|
||||||
lineitem_alter_220001
|
lineitem_alter_222000
|
||||||
lineitem_alter_220003
|
lineitem_alter_222002
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 228000;
|
||||||
-- verify that we can set and reset storage parameters
|
-- verify that we can set and reset storage parameters
|
||||||
ALTER TABLE lineitem_alter SET(fillfactor=40);
|
ALTER TABLE lineitem_alter SET(fillfactor=40);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
|
@ -823,15 +841,17 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
lineitem_alter_220000 | {fillfactor=40}
|
lineitem_alter_220000 | {fillfactor=40}
|
||||||
lineitem_alter_220001 | {fillfactor=40}
|
lineitem_alter_222000 | {fillfactor=40}
|
||||||
lineitem_alter_220003 | {fillfactor=40}
|
lineitem_alter_222002 | {fillfactor=40}
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 229000;
|
||||||
ALTER TABLE lineitem_alter RESET(fillfactor);
|
ALTER TABLE lineitem_alter RESET(fillfactor);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
|
@ -840,15 +860,17 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
lineitem_alter_220000 |
|
lineitem_alter_220000 |
|
||||||
lineitem_alter_220001 |
|
lineitem_alter_222000 |
|
||||||
lineitem_alter_220003 |
|
lineitem_alter_222002 |
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 230000;
|
||||||
-- verify that we can rename indexes on distributed tables
|
-- verify that we can rename indexes on distributed tables
|
||||||
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
||||||
ALTER INDEX temp_index_1 RENAME TO idx_lineitem_linenumber;
|
ALTER INDEX temp_index_1 RENAME TO idx_lineitem_linenumber;
|
||||||
|
@ -865,11 +887,13 @@ SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%' ORDER
|
||||||
relname
|
relname
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
idx_lineitem_linenumber_220000
|
idx_lineitem_linenumber_220000
|
||||||
idx_lineitem_linenumber_220001
|
idx_lineitem_linenumber_222000
|
||||||
idx_lineitem_linenumber_220003
|
idx_lineitem_linenumber_222002
|
||||||
(3 rows)
|
(3 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 231000;
|
||||||
-- now get rid of the index
|
-- now get rid of the index
|
||||||
DROP INDEX idx_lineitem_linenumber;
|
DROP INDEX idx_lineitem_linenumber;
|
||||||
-- verify that we don't intercept DDL commands if propagation is turned off
|
-- verify that we don't intercept DDL commands if propagation is turned off
|
||||||
|
@ -889,9 +913,11 @@ ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN column_only_added_to_master int;
|
ALTER TABLE lineitem_alter ADD COLUMN column_only_added_to_master int;
|
||||||
-- verify newly added column is not present in a worker shard
|
-- verify newly added column is not present in a worker shard
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT column_only_added_to_master FROM lineitem_alter_220000 LIMIT 0;
|
SELECT column_only_added_to_master FROM multi_alter_table_statements.lineitem_alter_220000 LIMIT 0;
|
||||||
ERROR: column "column_only_added_to_master" does not exist
|
ERROR: column "column_only_added_to_master" does not exist
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 232000;
|
||||||
-- ddl propagation flag is reset to default, disable it again
|
-- ddl propagation flag is reset to default, disable it again
|
||||||
SET citus.enable_ddl_propagation to false;
|
SET citus.enable_ddl_propagation to false;
|
||||||
-- following query succeeds since it accesses an previously existing column
|
-- following query succeeds since it accesses an previously existing column
|
||||||
|
@ -933,6 +959,8 @@ SELECT indexname, tablename FROM pg_indexes WHERE tablename like 'lineitem_alte
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 233000;
|
||||||
-- verify alter table and drop sequence in the same transaction does not cause deadlock
|
-- verify alter table and drop sequence in the same transaction does not cause deadlock
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
SET citus.shard_replication_factor TO 2;
|
SET citus.shard_replication_factor TO 2;
|
||||||
|
@ -967,7 +995,7 @@ SELECT create_distributed_table('trigger_table', 'id');
|
||||||
-- first set a trigger on a shard
|
-- first set a trigger on a shard
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SET citus.enable_metadata_sync TO OFF;
|
SET citus.enable_metadata_sync TO OFF;
|
||||||
CREATE FUNCTION update_value() RETURNS trigger AS $up$
|
CREATE OR REPLACE FUNCTION update_value() RETURNS trigger AS $up$
|
||||||
BEGIN
|
BEGIN
|
||||||
NEW.value := 'trigger enabled';
|
NEW.value := 'trigger enabled';
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
|
@ -975,9 +1003,11 @@ CREATE FUNCTION update_value() RETURNS trigger AS $up$
|
||||||
$up$ LANGUAGE plpgsql;
|
$up$ LANGUAGE plpgsql;
|
||||||
RESET citus.enable_metadata_sync;
|
RESET citus.enable_metadata_sync;
|
||||||
CREATE TRIGGER update_value
|
CREATE TRIGGER update_value
|
||||||
BEFORE INSERT ON trigger_table_220017
|
BEFORE INSERT ON multi_alter_table_statements.trigger_table_233004
|
||||||
FOR EACH ROW EXECUTE PROCEDURE update_value();
|
FOR EACH ROW EXECUTE PROCEDURE update_value();
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 234000;
|
||||||
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
||||||
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
||||||
value | count
|
value | count
|
||||||
|
@ -1019,37 +1049,41 @@ DROP TABLESPACE super_fast_ssd;
|
||||||
SET citus.enable_ddl_propagation to true;
|
SET citus.enable_ddl_propagation to true;
|
||||||
CREATE USER alter_table_owner WITH LOGIN;
|
CREATE USER alter_table_owner WITH LOGIN;
|
||||||
GRANT USAGE ON SCHEMA public TO alter_table_owner;
|
GRANT USAGE ON SCHEMA public TO alter_table_owner;
|
||||||
|
GRANT USAGE ON SCHEMA multi_alter_table_statements TO alter_table_owner;
|
||||||
\c - alter_table_owner - :master_port
|
\c - alter_table_owner - :master_port
|
||||||
-- should not be able to access table without permission
|
-- should not be able to access table without permission
|
||||||
SELECT count(*) FROM lineitem_alter;
|
SELECT count(*) FROM multi_alter_table_statements.lineitem_alter;
|
||||||
ERROR: permission denied for table lineitem_alter
|
ERROR: permission denied for table lineitem_alter
|
||||||
-- should not be able to drop the table as non table owner
|
-- should not be able to drop the table as non table owner
|
||||||
DROP TABLE lineitem_alter;
|
DROP TABLE multi_alter_table_statements.lineitem_alter;
|
||||||
ERROR: must be owner of table lineitem_alter
|
ERROR: must be owner of table lineitem_alter
|
||||||
\c - postgres - :master_port
|
\c - postgres - :master_port
|
||||||
ALTER TABLE lineitem_alter OWNER TO alter_table_owner;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter OWNER TO alter_table_owner;
|
||||||
\c - alter_table_owner - :master_port
|
\c - alter_table_owner - :master_port
|
||||||
-- should be able to query the table as table owner
|
-- should be able to query the table as table owner
|
||||||
SELECT count(*) FROM lineitem_alter;
|
SELECT count(*) FROM multi_alter_table_statements.lineitem_alter;
|
||||||
count
|
count
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
18000
|
18000
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- should be able to drop the table as table owner
|
-- should be able to drop the table as table owner
|
||||||
DROP TABLE lineitem_alter;
|
DROP TABLE multi_alter_table_statements.lineitem_alter;
|
||||||
-- check that nothing's left over on workers, other than the leftover shard created
|
-- check that nothing's left over on workers, other than the leftover shard created
|
||||||
-- during the unsuccessful COPY
|
-- during the unsuccessful COPY
|
||||||
\c - postgres - :worker_1_port
|
\c - postgres - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%';
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%';
|
||||||
relname
|
relname
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
lineitem_alter_220002
|
lineitem_alter_222001
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 235000;
|
||||||
-- drop the roles created
|
-- drop the roles created
|
||||||
REVOKE ALL ON SCHEMA PUBLIC FROM alter_table_owner;
|
REVOKE ALL ON SCHEMA PUBLIC FROM alter_table_owner;
|
||||||
|
REVOKE ALL ON SCHEMA multi_alter_table_statements FROM alter_table_owner;
|
||||||
DROP ROLE alter_table_owner;
|
DROP ROLE alter_table_owner;
|
||||||
-- Test alter table with drop table in the same transaction
|
-- Test alter table with drop table in the same transaction
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -1071,6 +1105,8 @@ SELECT relname FROM pg_class WHERE relname LIKE 'test_table_1%';
|
||||||
(0 rows)
|
(0 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 236000;
|
||||||
-- verify logged info is propagated to workers when distributing the table
|
-- verify logged info is propagated to workers when distributing the table
|
||||||
CREATE TABLE logged_test(id int);
|
CREATE TABLE logged_test(id int);
|
||||||
ALTER TABLE logged_test SET UNLOGGED;
|
ALTER TABLE logged_test SET UNLOGGED;
|
||||||
|
@ -1084,13 +1120,15 @@ SELECT create_distributed_table('logged_test', 'id');
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
relname | logged_info
|
relname | logged_info
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
logged_test_220022 | unlogged
|
logged_test_236000 | unlogged
|
||||||
logged_test_220023 | unlogged
|
logged_test_236001 | unlogged
|
||||||
logged_test_220024 | unlogged
|
logged_test_236002 | unlogged
|
||||||
logged_test_220025 | unlogged
|
logged_test_236003 | unlogged
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 237000;
|
||||||
-- verify SET LOGGED/UNLOGGED works after distributing the table
|
-- verify SET LOGGED/UNLOGGED works after distributing the table
|
||||||
ALTER TABLE logged_test SET LOGGED;
|
ALTER TABLE logged_test SET LOGGED;
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
||||||
|
@ -1103,13 +1141,15 @@ SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logg
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
relname | logged_info
|
relname | logged_info
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
logged_test_220022 | logged
|
logged_test_236000 | logged
|
||||||
logged_test_220023 | logged
|
logged_test_236001 | logged
|
||||||
logged_test_220024 | logged
|
logged_test_236002 | logged
|
||||||
logged_test_220025 | logged
|
logged_test_236003 | logged
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 238000;
|
||||||
ALTER TABLE logged_test SET UNLOGGED;
|
ALTER TABLE logged_test SET UNLOGGED;
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
||||||
relname | logged_info
|
relname | logged_info
|
||||||
|
@ -1121,13 +1161,15 @@ SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logg
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
relname | logged_info
|
relname | logged_info
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
logged_test_220022 | unlogged
|
logged_test_236000 | unlogged
|
||||||
logged_test_220023 | unlogged
|
logged_test_236001 | unlogged
|
||||||
logged_test_220024 | unlogged
|
logged_test_236002 | unlogged
|
||||||
logged_test_220025 | unlogged
|
logged_test_236003 | unlogged
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 239000;
|
||||||
DROP TABLE logged_test;
|
DROP TABLE logged_test;
|
||||||
-- Test WITH options on a normal simple hash-distributed table
|
-- Test WITH options on a normal simple hash-distributed table
|
||||||
CREATE TABLE hash_dist(id bigint primary key, f1 text) WITH (fillfactor=40);
|
CREATE TABLE hash_dist(id bigint primary key, f1 text) WITH (fillfactor=40);
|
||||||
|
@ -1148,13 +1190,15 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist';
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relkind = 'r' AND relname LIKE 'hash_dist_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relkind = 'r' AND relname LIKE 'hash_dist_%' ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
hash_dist_220026 | {fillfactor=40}
|
hash_dist_239000 | {fillfactor=40}
|
||||||
hash_dist_220027 | {fillfactor=40}
|
hash_dist_239001 | {fillfactor=40}
|
||||||
hash_dist_220028 | {fillfactor=40}
|
hash_dist_239002 | {fillfactor=40}
|
||||||
hash_dist_220029 | {fillfactor=40}
|
hash_dist_239003 | {fillfactor=40}
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 240000;
|
||||||
-- verify that we can set and reset index storage parameters
|
-- verify that we can set and reset index storage parameters
|
||||||
ALTER INDEX hash_dist_pkey SET(fillfactor=40);
|
ALTER INDEX hash_dist_pkey SET(fillfactor=40);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
|
@ -1167,13 +1211,15 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
hash_dist_pkey_220026 | {fillfactor=40}
|
hash_dist_pkey_239000 | {fillfactor=40}
|
||||||
hash_dist_pkey_220027 | {fillfactor=40}
|
hash_dist_pkey_239001 | {fillfactor=40}
|
||||||
hash_dist_pkey_220028 | {fillfactor=40}
|
hash_dist_pkey_239002 | {fillfactor=40}
|
||||||
hash_dist_pkey_220029 | {fillfactor=40}
|
hash_dist_pkey_239003 | {fillfactor=40}
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 241000;
|
||||||
ALTER INDEX hash_dist_pkey RESET(fillfactor);
|
ALTER INDEX hash_dist_pkey RESET(fillfactor);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
|
@ -1185,13 +1231,15 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
hash_dist_pkey_220026 |
|
hash_dist_pkey_239000 |
|
||||||
hash_dist_pkey_220027 |
|
hash_dist_pkey_239001 |
|
||||||
hash_dist_pkey_220028 |
|
hash_dist_pkey_239002 |
|
||||||
hash_dist_pkey_220029 |
|
hash_dist_pkey_239003 |
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 242000;
|
||||||
-- verify error message on ALTER INDEX, SET TABLESPACE is unsupported
|
-- verify error message on ALTER INDEX, SET TABLESPACE is unsupported
|
||||||
ALTER INDEX hash_dist_pkey SET TABLESPACE foo;
|
ALTER INDEX hash_dist_pkey SET TABLESPACE foo;
|
||||||
ERROR: alter index ... set tablespace ... is currently unsupported
|
ERROR: alter index ... set tablespace ... is currently unsupported
|
||||||
|
@ -1209,13 +1257,15 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'another_index';
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index_%' ORDER BY relname;
|
||||||
relname | reloptions
|
relname | reloptions
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
another_index_220026 | {fillfactor=50}
|
another_index_239000 | {fillfactor=50}
|
||||||
another_index_220027 | {fillfactor=50}
|
another_index_239001 | {fillfactor=50}
|
||||||
another_index_220028 | {fillfactor=50}
|
another_index_239002 | {fillfactor=50}
|
||||||
another_index_220029 | {fillfactor=50}
|
another_index_239003 | {fillfactor=50}
|
||||||
(4 rows)
|
(4 rows)
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 243000;
|
||||||
-- get rid of the index
|
-- get rid of the index
|
||||||
DROP INDEX another_index;
|
DROP INDEX another_index;
|
||||||
-- check if we fail properly when a column with un-supported constraint is added
|
-- check if we fail properly when a column with un-supported constraint is added
|
||||||
|
@ -1246,15 +1296,24 @@ SELECT create_reference_table('reference_table');
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE;
|
ALTER TABLE test_table_1 ADD COLUMN test_col_1 int REFERENCES reference_table(i) ON DELETE CASCADE;
|
||||||
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
ALTER TABLE test_table_1 ADD COLUMN test_col_2 int REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
||||||
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
HINT: You can issue each command separately such as ALTER TABLE test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name FOREIGN KEY (test_col) REFERENCES reference_table(i) ON DELETE CASCADE;
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('multi_alter_table_statements.test_table_1')$$
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
)
|
||||||
ERROR: cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints
|
JOIN pg_dist_node USING (nodeid)
|
||||||
DETAIL: Adding a column with a constraint in one command is not supported because all constraints in Citus must have explicit names
|
ORDER BY is_coordinator DESC, result;
|
||||||
HINT: You can issue each command separately such as ALTER TABLE test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name FOREIGN KEY (test_col) REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
is_coordinator | result
|
||||||
DROP TABLE reference_table;
|
---------------------------------------------------------------------
|
||||||
|
t | [{"deferred": false, "deferable": false, "on_delete": "c", "on_update": "a", "match_type": "s", "constraint_names": ["test_table_1__fkey"], "referenced_tables": ["multi_alter_table_statements.reference_table"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1"], "referencing_columns": ["test_col_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "c", "on_update": "n", "match_type": "s", "constraint_names": ["test_table_1__fkey1"], "referenced_tables": ["multi_alter_table_statements.reference_table"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1"], "referencing_columns": ["test_col_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": false, "deferable": false, "on_delete": "c", "on_update": "a", "match_type": "s", "constraint_names": ["test_table_1__fkey", "test_table_1__fkey_243000", "test_table_1__fkey_243002"], "referenced_tables": ["multi_alter_table_statements.reference_table", "multi_alter_table_statements.reference_table_243004", "multi_alter_table_statements.reference_table_243004"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1", "multi_alter_table_statements.test_table_1_243000", "multi_alter_table_statements.test_table_1_243002"], "referencing_columns": ["test_col_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "c", "on_update": "n", "match_type": "s", "constraint_names": ["test_table_1__fkey1", "test_table_1__fkey1_243000", "test_table_1__fkey1_243002"], "referenced_tables": ["multi_alter_table_statements.reference_table", "multi_alter_table_statements.reference_table_243004", "multi_alter_table_statements.reference_table_243004"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1", "multi_alter_table_statements.test_table_1_243000", "multi_alter_table_statements.test_table_1_243002"], "referencing_columns": ["test_col_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": false, "deferable": false, "on_delete": "c", "on_update": "a", "match_type": "s", "constraint_names": ["test_table_1__fkey", "test_table_1__fkey_243001", "test_table_1__fkey_243003"], "referenced_tables": ["multi_alter_table_statements.reference_table", "multi_alter_table_statements.reference_table_243004", "multi_alter_table_statements.reference_table_243004"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1", "multi_alter_table_statements.test_table_1_243001", "multi_alter_table_statements.test_table_1_243003"], "referencing_columns": ["test_col_1"], "referencing_columns_set_null_or_default": null}, {"deferred": false, "deferable": false, "on_delete": "c", "on_update": "n", "match_type": "s", "constraint_names": ["test_table_1__fkey1", "test_table_1__fkey1_243001", "test_table_1__fkey1_243003"], "referenced_tables": ["multi_alter_table_statements.reference_table", "multi_alter_table_statements.reference_table_243004", "multi_alter_table_statements.reference_table_243004"], "referenced_columns": ["i"], "referencing_tables": ["multi_alter_table_statements.test_table_1", "multi_alter_table_statements.test_table_1_243001", "multi_alter_table_statements.test_table_1_243003"], "referencing_columns": ["test_col_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL client_min_messages TO WARNING;
|
||||||
|
DROP TABLE reference_table CASCADE;
|
||||||
|
COMMIT;
|
||||||
CREATE TABLE referenced_table(i int UNIQUE);
|
CREATE TABLE referenced_table(i int UNIQUE);
|
||||||
SELECT create_distributed_table('referenced_table', 'i');
|
SELECT create_distributed_table('referenced_table', 'i');
|
||||||
create_distributed_table
|
create_distributed_table
|
||||||
|
@ -1262,7 +1321,7 @@ SELECT create_distributed_table('referenced_table', 'i');
|
||||||
|
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES referenced_table(i);
|
ALTER TABLE test_table_1 ADD COLUMN test_col_3 int REFERENCES referenced_table(i);
|
||||||
ERROR: cannot create foreign key constraint
|
ERROR: cannot create foreign key constraint
|
||||||
DETAIL: Foreign keys are supported in two cases, either in between two colocated tables including partition column in the same ordinal in the both tables or from distributed to reference tables
|
DETAIL: Foreign keys are supported in two cases, either in between two colocated tables including partition column in the same ordinal in the both tables or from distributed to reference tables
|
||||||
DROP TABLE referenced_table, test_table_1;
|
DROP TABLE referenced_table, test_table_1;
|
||||||
|
@ -1290,8 +1349,7 @@ SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.p
|
||||||
(schema,{test_schema_for_sequence_propagation},{})
|
(schema,{test_schema_for_sequence_propagation},{})
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA test_schema_for_sequence_propagation CASCADE;
|
DROP SCHEMA test_schema_for_sequence_propagation CASCADE;
|
||||||
NOTICE: drop cascades to 2 other objects
|
|
||||||
DETAIL: drop cascades to sequence test_schema_for_sequence_propagation.seq_10
|
|
||||||
drop cascades to default value for column x of table table_without_sequence
|
|
||||||
DROP TABLE table_without_sequence;
|
DROP TABLE table_without_sequence;
|
||||||
|
DROP SCHEMA multi_alter_table_statements CASCADE;
|
||||||
|
|
|
@ -3,7 +3,11 @@ SET citus.next_shard_id TO 390000;
|
||||||
-- get ready for the foreign data wrapper tests
|
-- get ready for the foreign data wrapper tests
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
-- create fake fdw for use in tests
|
-- create fake fdw for use in tests
|
||||||
CREATE FUNCTION fake_fdw_handler()
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SERVER IF EXISTS fake_fdw_server CASCADE;
|
||||||
|
DROP FOREIGN DATA WRAPPER IF EXISTS fake_fdw CASCADE;
|
||||||
|
RESET client_min_messages;
|
||||||
|
CREATE OR REPLACE FUNCTION fake_fdw_handler()
|
||||||
RETURNS fdw_handler
|
RETURNS fdw_handler
|
||||||
AS 'citus'
|
AS 'citus'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
|
@ -89,9 +89,9 @@ NOTICE: executing the command locally: INSERT INTO multi_row_router_insert.citu
|
||||||
INSERT INTO citus_local_table (a) VALUES (12), (13);
|
INSERT INTO citus_local_table (a) VALUES (12), (13);
|
||||||
NOTICE: executing the command locally: INSERT INTO multi_row_router_insert.citus_local_table_1511001 AS citus_table_alias (a, b) VALUES (12,100), (13,100)
|
NOTICE: executing the command locally: INSERT INTO multi_row_router_insert.citus_local_table_1511001 AS citus_table_alias (a, b) VALUES (12,100), (13,100)
|
||||||
ALTER TABLE citus_local_table ADD COLUMN c INT DEFAULT to_number('5', '91');
|
ALTER TABLE citus_local_table ADD COLUMN c INT DEFAULT to_number('5', '91');
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1511001, 'multi_row_router_insert', 'ALTER TABLE citus_local_table ADD COLUMN c INT DEFAULT to_number(''5'', ''91'');')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1511001, 'multi_row_router_insert', 'ALTER TABLE citus_local_table ADD COLUMN c integer DEFAULT to_number(''5''::text, ''91''::text);')
|
||||||
ALTER TABLE citus_local_table ADD COLUMN d INT;
|
ALTER TABLE citus_local_table ADD COLUMN d INT;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1511001, 'multi_row_router_insert', 'ALTER TABLE citus_local_table ADD COLUMN d INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (1511001, 'multi_row_router_insert', 'ALTER TABLE citus_local_table ADD COLUMN d integer;')
|
||||||
INSERT INTO citus_local_table (d, a, b) VALUES (13, 14, 15), (16, 17, 18), (19, 20, 21);
|
INSERT INTO citus_local_table (d, a, b) VALUES (13, 14, 15), (16, 17, 18), (19, 20, 21);
|
||||||
NOTICE: executing the command locally: INSERT INTO multi_row_router_insert.citus_local_table_1511001 AS citus_table_alias (a, b, c, d) VALUES (14,15,5,13), (17,18,5,16), (20,21,5,19)
|
NOTICE: executing the command locally: INSERT INTO multi_row_router_insert.citus_local_table_1511001 AS citus_table_alias (a, b, c, d) VALUES (14,15,5,13), (17,18,5,16), (20,21,5,19)
|
||||||
SELECT * FROM citus_local_table ORDER BY 1,2,3,4;
|
SELECT * FROM citus_local_table ORDER BY 1,2,3,4;
|
||||||
|
|
|
@ -143,6 +143,8 @@ SELECT create_distributed_table('seq_test_4','x');
|
||||||
|
|
||||||
CREATE SEQUENCE seq_4;
|
CREATE SEQUENCE seq_4;
|
||||||
ALTER TABLE seq_test_4 ADD COLUMN a bigint DEFAULT nextval('seq_4');
|
ALTER TABLE seq_test_4 ADD COLUMN a bigint DEFAULT nextval('seq_4');
|
||||||
|
ALTER TABLE seq_test_4 ADD COLUMN IF NOT EXISTS a bigint DEFAULT nextval('seq_4');
|
||||||
|
NOTICE: column "a" of relation "seq_test_4" already exists, skipping
|
||||||
DROP SEQUENCE seq_4 CASCADE;
|
DROP SEQUENCE seq_4 CASCADE;
|
||||||
NOTICE: drop cascades to default value for column a of table seq_test_4
|
NOTICE: drop cascades to default value for column a of table seq_test_4
|
||||||
TRUNCATE seq_test_4;
|
TRUNCATE seq_test_4;
|
||||||
|
@ -879,7 +881,7 @@ ROLLBACK;
|
||||||
-- Show that existing sequence has been renamed and a new sequence with the same name
|
-- Show that existing sequence has been renamed and a new sequence with the same name
|
||||||
-- created for another type
|
-- created for another type
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT seqrelid::regclass, seqtypid::regtype, seqmax, seqmin FROM pg_sequence WHERE seqrelid::regclass::text like '%sequence_rollback%' ORDER BY 1,2;
|
SELECT seqrelid::regclass, seqtypid::regtype, seqmax, seqmin FROM pg_sequence WHERE seqrelid::regclass::text in ('sequence_rollback', '"sequence_rollback(citus_backup_0)"') ORDER BY 1,2;
|
||||||
seqrelid | seqtypid | seqmax | seqmin
|
seqrelid | seqtypid | seqmax | seqmin
|
||||||
---------------------------------------------------------------------
|
---------------------------------------------------------------------
|
||||||
"sequence_rollback(citus_backup_0)" | integer | 2147483647 | 1
|
"sequence_rollback(citus_backup_0)" | integer | 2147483647 | 1
|
||||||
|
|
|
@ -167,3 +167,135 @@ BEGIN
|
||||||
EXECUTE 'SELECT COUNT(*) FROM pg_catalog.pg_dist_cleanup' INTO record_count;
|
EXECUTE 'SELECT COUNT(*) FROM pg_catalog.pg_dist_cleanup' INTO record_count;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END$$ LANGUAGE plpgsql;
|
END$$ LANGUAGE plpgsql;
|
||||||
|
-- Returns the foreign keys where the referencing relation's name starts with
|
||||||
|
-- given prefix.
|
||||||
|
--
|
||||||
|
-- Foreign keys are groupped by their configurations and then the constraint name,
|
||||||
|
-- referencing table, and referenced table for each distinct configuration are
|
||||||
|
-- aggregated into arrays.
|
||||||
|
CREATE OR REPLACE FUNCTION get_grouped_fkey_constraints(referencing_relname_prefix text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
confdelsetcols_column_ref text;
|
||||||
|
get_grouped_fkey_constraints_query text;
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
-- Read confdelsetcols as null if no such column exists.
|
||||||
|
-- This can only be the case for PG versions < 15.
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'pg_constraint'::regclass AND attname='confdelsetcols')
|
||||||
|
THEN
|
||||||
|
confdelsetcols_column_ref := '(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = conrelid AND attnum = ANY(confdelsetcols))';
|
||||||
|
ELSE
|
||||||
|
confdelsetcols_column_ref := '(SELECT null::smallint[])';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.constraint_names) AS fkeys_with_different_config FROM (
|
||||||
|
SELECT array_agg(constraint_name ORDER BY constraint_oid) AS constraint_names,
|
||||||
|
array_agg(referencing_table::regclass::text ORDER BY constraint_oid) AS referencing_tables,
|
||||||
|
array_agg(referenced_table::regclass::text ORDER BY constraint_oid) AS referenced_tables,
|
||||||
|
referencing_columns, referenced_columns, deferable, deferred, on_update, on_delete, match_type, referencing_columns_set_null_or_default
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
oid AS constraint_oid,
|
||||||
|
conname AS constraint_name,
|
||||||
|
conrelid AS referencing_table,
|
||||||
|
(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = conrelid AND attnum = ANY(conkey)) AS referencing_columns,
|
||||||
|
confrelid AS referenced_table,
|
||||||
|
(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = confrelid AND attnum = ANY(confkey)) AS referenced_columns,
|
||||||
|
condeferrable AS deferable,
|
||||||
|
condeferred AS deferred,
|
||||||
|
confupdtype AS on_update,
|
||||||
|
confdeltype AS on_delete,
|
||||||
|
confmatchtype AS match_type,
|
||||||
|
%2$s AS referencing_columns_set_null_or_default
|
||||||
|
FROM pg_constraint WHERE starts_with(conrelid::regclass::text, '%1$s') AND contype = 'f'
|
||||||
|
) q2
|
||||||
|
GROUP BY referencing_columns, referenced_columns, deferable, deferred, on_update, on_delete, match_type, referencing_columns_set_null_or_default
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
referencing_relname_prefix,
|
||||||
|
confdelsetcols_column_ref
|
||||||
|
) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
CREATE OR REPLACE FUNCTION get_index_defs(schemaname text, tablename text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
indnullsnotdistinct_column_ref text;
|
||||||
|
BEGIN
|
||||||
|
-- Not use indnullsnotdistinct in group by clause if no such column exists.
|
||||||
|
-- This can only be the case for PG versions < 15.
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'pg_index'::regclass AND attname='indnullsnotdistinct')
|
||||||
|
THEN
|
||||||
|
indnullsnotdistinct_column_ref := ',indnullsnotdistinct';
|
||||||
|
ELSE
|
||||||
|
indnullsnotdistinct_column_ref := '';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.indexnames) AS index_defs FROM (
|
||||||
|
SELECT array_agg(indexname ORDER BY indexrelid) AS indexnames,
|
||||||
|
array_agg(indexdef ORDER BY indexrelid) AS indexdefs
|
||||||
|
FROM pg_indexes
|
||||||
|
JOIN pg_index
|
||||||
|
ON (indexrelid = (schemaname || '.' || indexname)::regclass)
|
||||||
|
WHERE schemaname = '%1$s' AND starts_with(tablename, '%2$s')
|
||||||
|
GROUP BY indnatts, indnkeyatts, indisunique, indisprimary, indisexclusion,
|
||||||
|
indimmediate, indisclustered, indisvalid, indisready, indislive,
|
||||||
|
indisreplident, indkey, indcollation, indclass, indoption, indexprs,
|
||||||
|
indpred %3$s
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
schemaname, tablename, indnullsnotdistinct_column_ref) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
CREATE OR REPLACE FUNCTION get_column_defaults(schemaname text, tablename text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.column_name) AS column_defs FROM (
|
||||||
|
SELECT column_name, column_default::text, generation_expression::text
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = '%1$s' AND table_name = '%2$s' AND
|
||||||
|
column_default IS NOT NULL OR generation_expression IS NOT NULL
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
schemaname, tablename) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
CREATE OR REPLACE FUNCTION get_column_attrs(relname_prefix text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT to_jsonb(q2.*) FROM (
|
||||||
|
SELECT relnames, jsonb_agg(to_jsonb(q1.*) - 'relnames' ORDER BY q1.column_name) AS column_attrs FROM (
|
||||||
|
SELECT array_agg(attrelid::regclass::text ORDER BY attrelid) AS relnames,
|
||||||
|
attname AS column_name, typname AS type_name, collname AS collation_name, attcompression AS compression_method, attnotnull AS not_null
|
||||||
|
FROM pg_attribute pa
|
||||||
|
LEFT JOIN pg_type pt ON (pa.atttypid = pt.oid)
|
||||||
|
LEFT JOIN pg_collation pc1 ON (pa.attcollation = pc1.oid)
|
||||||
|
JOIN pg_class pc2 ON (pa.attrelid = pc2.oid)
|
||||||
|
WHERE starts_with(attrelid::regclass::text, '%1$s') AND
|
||||||
|
attnum > 0 AND NOT attisdropped AND relkind = 'r'
|
||||||
|
GROUP BY column_name, type_name, collation_name, compression_method, not_null
|
||||||
|
) q1
|
||||||
|
GROUP BY relnames
|
||||||
|
) q2
|
||||||
|
$$,
|
||||||
|
relname_prefix) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
|
|
@ -1473,6 +1473,56 @@ SELECT run_command_on_workers($$DROP ACCESS METHOD heap2$$);
|
||||||
(localhost,57638,t,"DROP ACCESS METHOD")
|
(localhost,57638,t,"DROP ACCESS METHOD")
|
||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
|
CREATE TABLE referenced (int_col integer PRIMARY KEY);
|
||||||
|
CREATE TABLE referencing (text_col text);
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SELECT create_distributed_table('referenced', null);
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
SELECT create_distributed_table('referencing', null);
|
||||||
|
create_distributed_table
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
RESET citus.shard_replication_factor;
|
||||||
|
CREATE OR REPLACE FUNCTION my_random(numeric)
|
||||||
|
RETURNS numeric AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN 7 * $1;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_2 integer UNIQUE NULLS DISTINCT REFERENCES referenced(int_col);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_3 integer GENERATED ALWAYS AS (text_col::int * my_random(1)) STORED UNIQUE NULLS NOT DISTINCT;
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('pg15.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "s", "constraint_names": ["referencing__fkey"], "referenced_tables": ["pg15.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["pg15.referencing"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "s", "constraint_names": ["referencing__fkey", "referencing__fkey_960207"], "referenced_tables": ["pg15.referenced", "pg15.referenced_960206"], "referenced_columns": ["int_col"], "referencing_tables": ["pg15.referencing", "pg15.referencing_960207"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
f | [{"deferred": false, "deferable": false, "on_delete": "a", "on_update": "a", "match_type": "s", "constraint_names": ["referencing__fkey"], "referenced_tables": ["pg15.referenced"], "referenced_columns": ["int_col"], "referencing_tables": ["pg15.referencing"], "referencing_columns": ["test_2"], "referencing_columns_set_null_or_default": null}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('pg15', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
is_coordinator | result
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
t | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON pg15.referencing USING btree (test_2)"], "indexnames": ["referencing__key"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON pg15.referencing USING btree (test_3) NULLS NOT DISTINCT"], "indexnames": ["referencing__key1"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON pg15.referencing USING btree (test_2)", "CREATE UNIQUE INDEX referencing__key_960207 ON pg15.referencing_960207 USING btree (test_2)"], "indexnames": ["referencing__key", "referencing__key_960207"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON pg15.referencing USING btree (test_3) NULLS NOT DISTINCT", "CREATE UNIQUE INDEX referencing__key1_960207 ON pg15.referencing_960207 USING btree (test_3) NULLS NOT DISTINCT"], "indexnames": ["referencing__key1", "referencing__key1_960207"]}]
|
||||||
|
f | [{"indexdefs": ["CREATE UNIQUE INDEX referencing__key ON pg15.referencing USING btree (test_2)"], "indexnames": ["referencing__key"]}, {"indexdefs": ["CREATE UNIQUE INDEX referencing__key1 ON pg15.referencing USING btree (test_3) NULLS NOT DISTINCT"], "indexnames": ["referencing__key1"]}]
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
-- Clean up
|
-- Clean up
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
SET client_min_messages TO ERROR;
|
SET client_min_messages TO ERROR;
|
||||||
|
|
|
@ -446,7 +446,7 @@ INSERT INTO local_table VALUES (1), (2), (3), (4);
|
||||||
INSERT INTO numbers VALUES (1), (2), (3), (4);
|
INSERT INTO numbers VALUES (1), (2), (3), (4);
|
||||||
NOTICE: executing the command locally: INSERT INTO replicate_ref_to_coordinator.numbers_8000001 AS citus_table_alias (a) VALUES (1), (2), (3), (4)
|
NOTICE: executing the command locally: INSERT INTO replicate_ref_to_coordinator.numbers_8000001 AS citus_table_alias (a) VALUES (1), (2), (3), (4)
|
||||||
ALTER TABLE numbers ADD COLUMN d int;
|
ALTER TABLE numbers ADD COLUMN d int;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (8000001, 'replicate_ref_to_coordinator', 'ALTER TABLE numbers ADD COLUMN d int;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (8000001, 'replicate_ref_to_coordinator', 'ALTER TABLE numbers ADD COLUMN d integer;')
|
||||||
SELECT * FROM local_table JOIN numbers USING(a) ORDER BY a;
|
SELECT * FROM local_table JOIN numbers USING(a) ORDER BY a;
|
||||||
NOTICE: executing the command locally: SELECT local_table.a, numbers.d FROM (replicate_ref_to_coordinator.local_table JOIN replicate_ref_to_coordinator.numbers_8000001 numbers(a, d) USING (a)) ORDER BY local_table.a
|
NOTICE: executing the command locally: SELECT local_table.a, numbers.d FROM (replicate_ref_to_coordinator.local_table JOIN replicate_ref_to_coordinator.numbers_8000001 numbers(a, d) USING (a)) ORDER BY local_table.a
|
||||||
a | d
|
a | d
|
||||||
|
|
|
@ -2134,10 +2134,10 @@ NOTICE: executing the command locally: SELECT count(*) AS count FROM (SELECT in
|
||||||
|
|
||||||
-- test with NULL columns
|
-- test with NULL columns
|
||||||
ALTER TABLE non_binary_copy_test ADD COLUMN z INT;
|
ALTER TABLE non_binary_copy_test ADD COLUMN z INT;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630519, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630519, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630520, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630520, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630521, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630521, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630522, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630522, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
WITH cte_1 AS
|
WITH cte_1 AS
|
||||||
(INSERT INTO non_binary_copy_test SELECT * FROM non_binary_copy_test LIMIT 10000 ON CONFLICT (key) DO UPDATE SET value = (0, 'citus0')::new_type RETURNING z)
|
(INSERT INTO non_binary_copy_test SELECT * FROM non_binary_copy_test LIMIT 10000 ON CONFLICT (key) DO UPDATE SET value = (0, 'citus0')::new_type RETURNING z)
|
||||||
SELECT bool_and(z is null) FROM cte_1;
|
SELECT bool_and(z is null) FROM cte_1;
|
||||||
|
|
|
@ -2134,10 +2134,10 @@ NOTICE: executing the command locally: SELECT count(*) AS count FROM (SELECT in
|
||||||
|
|
||||||
-- test with NULL columns
|
-- test with NULL columns
|
||||||
ALTER TABLE non_binary_copy_test ADD COLUMN z INT;
|
ALTER TABLE non_binary_copy_test ADD COLUMN z INT;
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630519, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630519, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630520, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630520, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630521, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630521, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630522, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z INT;')
|
NOTICE: executing the command locally: SELECT worker_apply_shard_ddl_command (90630522, 'single_node', 'ALTER TABLE non_binary_copy_test ADD COLUMN z integer;')
|
||||||
WITH cte_1 AS
|
WITH cte_1 AS
|
||||||
(INSERT INTO non_binary_copy_test SELECT * FROM non_binary_copy_test LIMIT 10000 ON CONFLICT (key) DO UPDATE SET value = (0, 'citus0')::new_type RETURNING z)
|
(INSERT INTO non_binary_copy_test SELECT * FROM non_binary_copy_test LIMIT 10000 ON CONFLICT (key) DO UPDATE SET value = (0, 'citus0')::new_type RETURNING z)
|
||||||
SELECT bool_and(z is null) FROM cte_1;
|
SELECT bool_and(z is null) FROM cte_1;
|
||||||
|
|
|
@ -157,7 +157,7 @@ test: with_executors with_join with_partitioning with_transactions with_dml
|
||||||
# Tests around DDL statements run on distributed tables
|
# Tests around DDL statements run on distributed tables
|
||||||
# ----------
|
# ----------
|
||||||
test: multi_index_statements
|
test: multi_index_statements
|
||||||
test: multi_alter_table_statements
|
test: multi_alter_table_statements alter_table_add_column
|
||||||
test: multi_alter_table_add_constraints
|
test: multi_alter_table_add_constraints
|
||||||
test: multi_alter_table_add_constraints_without_name
|
test: multi_alter_table_add_constraints_without_name
|
||||||
test: multi_alter_table_add_foreign_key_without_name
|
test: multi_alter_table_add_foreign_key_without_name
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
CREATE SCHEMA alter_table_add_column;
|
||||||
|
SET search_path TO alter_table_add_column;
|
||||||
|
|
||||||
|
SET citus.next_shard_id TO 1830000;
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
|
||||||
|
SET client_min_messages TO NOTICE;
|
||||||
|
|
||||||
|
CREATE TABLE referenced (int_col integer PRIMARY KEY);
|
||||||
|
CREATE TABLE referencing (text_col text);
|
||||||
|
SELECT create_distributed_table('referenced', null);
|
||||||
|
SELECT create_distributed_table('referencing', null);
|
||||||
|
|
||||||
|
CREATE SCHEMA alter_table_add_column_other_schema;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION alter_table_add_column_other_schema.my_random(numeric)
|
||||||
|
RETURNS numeric AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN 7 * $1;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
|
CREATE COLLATION caseinsensitive (
|
||||||
|
provider = icu,
|
||||||
|
locale = 'und-u-ks-level2'
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TYPE "simple_!\'custom_type" AS (a integer, b integer);
|
||||||
|
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_1 integer DEFAULT (alter_table_add_column_other_schema.my_random(7) + random() + 5) NOT NULL CONSTRAINT fkey REFERENCES referenced(int_col) ON UPDATE SET DEFAULT ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_2 integer UNIQUE REFERENCES referenced(int_col) ON UPDATE CASCADE ON DELETE SET DEFAULT NOT DEFERRABLE INITIALLY IMMEDIATE;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_3 integer GENERATED ALWAYS AS (test_1 * alter_table_add_column_other_schema.my_random(1)) STORED UNIQUE REFERENCES referenced(int_col) MATCH FULL;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_4 integer PRIMARY KEY WITH (fillfactor=70) NOT NULL REFERENCES referenced(int_col) MATCH SIMPLE ON UPDATE CASCADE ON DELETE SET DEFAULT;
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_5 integer CONSTRAINT unique_c UNIQUE WITH (fillfactor=50);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_6 text COMPRESSION pglz COLLATE caseinsensitive NOT NULL;
|
||||||
|
ALTER TABLE referencing ADD COLUMN "test_\'!7" "simple_!\'custom_type";
|
||||||
|
|
||||||
|
-- we give up deparsing ALTER TABLE command if it needs to create a check constraint, and we fallback to legacy behavior
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_8 integer CHECK (test_8 > 0);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_8 integer CONSTRAINT check_test_8 CHECK (test_8 > 0);
|
||||||
|
|
||||||
|
-- try to add test_6 again, but with IF NOT EXISTS
|
||||||
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 text;
|
||||||
|
ALTER TABLE referencing ADD COLUMN IF NOT EXISTS test_6 integer;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('alter_table_add_column.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('alter_table_add_column', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_column_defaults FROM get_column_defaults('alter_table_add_column', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_column_attrs FROM get_column_attrs('alter_table_add_column.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA alter_table_add_column, alter_table_add_column_other_schema CASCADE;
|
|
@ -1,3 +1,7 @@
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SCHEMA IF EXISTS columnar_test_helpers CASCADE;
|
||||||
|
RESET client_min_messages;
|
||||||
|
|
||||||
CREATE SCHEMA columnar_test_helpers;
|
CREATE SCHEMA columnar_test_helpers;
|
||||||
SET search_path TO columnar_test_helpers;
|
SET search_path TO columnar_test_helpers;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ SELECT pg_reload_conf();
|
||||||
|
|
||||||
-- Add some helper functions for sending commands to mitmproxy
|
-- Add some helper functions for sending commands to mitmproxy
|
||||||
|
|
||||||
CREATE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
CREATE OR REPLACE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
||||||
DECLARE
|
DECLARE
|
||||||
command ALIAS FOR $1;
|
command ALIAS FOR $1;
|
||||||
BEGIN
|
BEGIN
|
||||||
|
@ -24,58 +24,14 @@ BEGIN
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
CREATE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
CREATE OR REPLACE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
PERFORM citus.mitmproxy('recorder.reset()');
|
PERFORM citus.mitmproxy('recorder.reset()');
|
||||||
RETURN; -- return void
|
RETURN; -- return void
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql;
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
CREATE FUNCTION citus.dump_network_traffic()
|
CREATE OR REPLACE FUNCTION citus.dump_network_traffic()
|
||||||
RETURNS TABLE(conn int, source text, message text) AS $$
|
|
||||||
BEGIN
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_result (
|
|
||||||
conn int, source text, message text
|
|
||||||
) ON COMMIT DROP;
|
|
||||||
|
|
||||||
INSERT INTO mitmproxy_command VALUES ('recorder.dump()');
|
|
||||||
|
|
||||||
EXECUTE format('COPY mitmproxy_command TO %L', current_setting('citus.mitmfifo'));
|
|
||||||
EXECUTE format('COPY mitmproxy_result FROM %L', current_setting('citus.mitmfifo'));
|
|
||||||
|
|
||||||
RETURN QUERY SELECT * FROM mitmproxy_result;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
\c - - - :worker_2_port
|
|
||||||
|
|
||||||
-- Add some helper functions for sending commands to mitmproxy
|
|
||||||
|
|
||||||
CREATE FUNCTION citus.mitmproxy(text) RETURNS TABLE(result text) AS $$
|
|
||||||
DECLARE
|
|
||||||
command ALIAS FOR $1;
|
|
||||||
BEGIN
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
|
||||||
CREATE TEMPORARY TABLE mitmproxy_result (res text) ON COMMIT DROP;
|
|
||||||
|
|
||||||
INSERT INTO mitmproxy_command VALUES (command);
|
|
||||||
|
|
||||||
EXECUTE format('COPY mitmproxy_command TO %L', current_setting('citus.mitmfifo'));
|
|
||||||
EXECUTE format('COPY mitmproxy_result FROM %L', current_setting('citus.mitmfifo'));
|
|
||||||
|
|
||||||
RETURN QUERY SELECT * FROM mitmproxy_result;
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
CREATE FUNCTION citus.clear_network_traffic() RETURNS void AS $$
|
|
||||||
BEGIN
|
|
||||||
PERFORM citus.mitmproxy('recorder.reset()');
|
|
||||||
RETURN; -- return void
|
|
||||||
END;
|
|
||||||
$$ LANGUAGE plpgsql;
|
|
||||||
|
|
||||||
CREATE FUNCTION citus.dump_network_traffic()
|
|
||||||
RETURNS TABLE(conn int, source text, message text) AS $$
|
RETURNS TABLE(conn int, source text, message text) AS $$
|
||||||
BEGIN
|
BEGIN
|
||||||
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
CREATE TEMPORARY TABLE mitmproxy_command (command text) ON COMMIT DROP;
|
||||||
|
|
|
@ -100,9 +100,12 @@ BEGIN;
|
||||||
SELECT COUNT(*)=0 FROM citus_local_tables_in_schema;
|
SELECT COUNT(*)=0 FROM citus_local_tables_in_schema;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
|
|
||||||
-- this actually attempts to convert local tables to citus local tables but errors out
|
BEGIN;
|
||||||
-- as citus doesn't support defining foreign keys via add column commands
|
ALTER TABLE local_table_1 ADD COLUMN col_3 INT REFERENCES reference_table_1(col_1);
|
||||||
ALTER TABLE local_table_1 ADD COLUMN col_3 INT REFERENCES reference_table_1(col_1);
|
|
||||||
|
-- show that we converted all 4 local tables in this schema to citus local tables
|
||||||
|
SELECT COUNT(*)=4 FROM citus_local_tables_in_schema;
|
||||||
|
ROLLBACK;
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
-- define a foreign key so that all 4 local tables become citus local tables
|
-- define a foreign key so that all 4 local tables become citus local tables
|
||||||
|
|
|
@ -563,6 +563,19 @@ SELECT create_distributed_table('alter_add_unique', 'x');
|
||||||
ALTER TABLE alter_add_unique ADD CONSTRAINT unique_constraint_test UNIQUE USING INDEX alter_unique_idx;
|
ALTER TABLE alter_add_unique ADD CONSTRAINT unique_constraint_test UNIQUE USING INDEX alter_unique_idx;
|
||||||
ALTER TABLE alter_add_unique DROP CONSTRAINT unique_constraint_test;
|
ALTER TABLE alter_add_unique DROP CONSTRAINT unique_constraint_test;
|
||||||
|
|
||||||
|
CREATE TABLE unique_test_table_single_shard(id int, name varchar(20));
|
||||||
|
SELECT create_distributed_table('unique_test_table_single_shard', 'id', shard_count=>1);
|
||||||
|
|
||||||
|
ALTER TABLE unique_test_table_single_shard ADD UNIQUE(id, name) WITH (fillfactor=20);
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('sc3', 'unique_test_table_single_shard')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
DROP TABLE unique_test_table_single_shard;
|
||||||
|
|
||||||
SET search_path TO 'public';
|
SET search_path TO 'public';
|
||||||
|
|
||||||
DROP SCHEMA sc1 CASCADE;
|
DROP SCHEMA sc1 CASCADE;
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
-- MULTI_ALTER_TABLE_STATEMENTS
|
-- MULTI_ALTER_TABLE_STATEMENTS
|
||||||
--
|
--
|
||||||
|
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 220000;
|
CREATE SCHEMA multi_alter_table_statements;
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 220000;
|
||||||
|
|
||||||
-- Check that we can run ALTER TABLE statements on distributed tables.
|
-- Check that we can run ALTER TABLE statements on distributed tables.
|
||||||
-- We set the shardid sequence here so that the shardids in this test
|
-- We set the shardid sequence here so that the shardids in this test
|
||||||
|
@ -38,6 +39,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 221000;
|
||||||
|
|
||||||
-- Verify that we can add columns
|
-- Verify that we can add columns
|
||||||
|
|
||||||
|
@ -55,8 +58,10 @@ FROM
|
||||||
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
||||||
ORDER BY attnum;
|
ORDER BY attnum;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 222000;
|
||||||
|
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column;
|
SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column;
|
||||||
SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
||||||
|
|
||||||
|
@ -75,7 +80,7 @@ SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1;
|
||||||
-- Verify that SET NOT NULL works
|
-- Verify that SET NOT NULL works
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
-- Drop default so that NULLs will be inserted for this column
|
-- Drop default so that NULLs will be inserted for this column
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT;
|
||||||
|
@ -90,7 +95,7 @@ END;
|
||||||
-- Verify that DROP NOT NULL works
|
-- Verify that DROP NOT NULL works
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
-- COPY should succeed now
|
-- COPY should succeed now
|
||||||
SELECT master_create_empty_shard('lineitem_alter') as shardid \gset
|
SELECT master_create_empty_shard('lineitem_alter') as shardid \gset
|
||||||
|
@ -102,7 +107,7 @@ SELECT count(*) from lineitem_alter;
|
||||||
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT;
|
ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2;
|
||||||
|
|
||||||
|
@ -130,19 +135,19 @@ ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS int_column2;
|
||||||
ALTER TABLE IF EXISTS lineitem_alter RENAME COLUMN l_orderkey_renamed TO l_orderkey;
|
ALTER TABLE IF EXISTS lineitem_alter RENAME COLUMN l_orderkey_renamed TO l_orderkey;
|
||||||
SELECT SUM(l_orderkey) FROM lineitem_alter;
|
SELECT SUM(l_orderkey) FROM lineitem_alter;
|
||||||
|
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
-- Verify that we can execute commands with multiple subcommands
|
-- Verify that we can execute commands with multiple subcommands
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER,
|
ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER,
|
||||||
ADD COLUMN int_column2 INTEGER;
|
ADD COLUMN int_column2 INTEGER;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER,
|
ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER,
|
||||||
ALTER COLUMN int_column1 SET STATISTICS 10;
|
ALTER COLUMN int_column1 SET STATISTICS 10;
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2;
|
ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2;
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
-- Verify that we cannot execute alter commands on the distribution column
|
-- Verify that we cannot execute alter commands on the distribution column
|
||||||
|
|
||||||
|
@ -174,7 +179,7 @@ ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2;
|
||||||
|
|
||||||
-- Verify that none of the failed alter table commands took effect on the master
|
-- Verify that none of the failed alter table commands took effect on the master
|
||||||
-- node
|
-- node
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
|
|
||||||
-- verify that non-propagated ddl commands are allowed inside a transaction block
|
-- verify that non-propagated ddl commands are allowed inside a transaction block
|
||||||
SET citus.enable_ddl_propagation to false;
|
SET citus.enable_ddl_propagation to false;
|
||||||
|
@ -198,7 +203,7 @@ CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
||||||
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
ALTER TABLE lineitem_alter ADD COLUMN first integer;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
||||||
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='public.lineitem_alter'::regclass;
|
SELECT "Column", "Type", "Modifiers" FROM table_desc WHERE relid='lineitem_alter'::regclass;
|
||||||
SELECT "Column", "Type", "Definition" FROM index_attrs WHERE
|
SELECT "Column", "Type", "Definition" FROM index_attrs WHERE
|
||||||
relid = 'temp_index_2'::regclass;
|
relid = 'temp_index_2'::regclass;
|
||||||
|
|
||||||
|
@ -241,8 +246,10 @@ DROP INDEX temp_index_2;
|
||||||
|
|
||||||
-- Add column on only one worker...
|
-- Add column on only one worker...
|
||||||
\c - - - :worker_2_port
|
\c - - - :worker_2_port
|
||||||
ALTER TABLE lineitem_alter_220000 ADD COLUMN first integer;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter_220000 ADD COLUMN first integer;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 223000;
|
||||||
|
|
||||||
-- and try to add it in a multi-statement block, which fails
|
-- and try to add it in a multi-statement block, which fails
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -288,7 +295,7 @@ ALTER TABLE single_shard_items REPLICA IDENTITY default;
|
||||||
|
|
||||||
-- Drop the column from the worker...
|
-- Drop the column from the worker...
|
||||||
\c - - - :worker_2_port
|
\c - - - :worker_2_port
|
||||||
ALTER TABLE lineitem_alter_220000 DROP COLUMN first;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter_220000 DROP COLUMN first;
|
||||||
|
|
||||||
-- Create table to trigger at-xact-end (deferred) failure
|
-- Create table to trigger at-xact-end (deferred) failure
|
||||||
CREATE TABLE ddl_commands (command text UNIQUE DEFERRABLE INITIALLY DEFERRED);
|
CREATE TABLE ddl_commands (command text UNIQUE DEFERRABLE INITIALLY DEFERRED);
|
||||||
|
@ -305,6 +312,8 @@ RESET citus.enable_metadata_sync;
|
||||||
CREATE EVENT TRIGGER log_ddl_tag ON ddl_command_end EXECUTE PROCEDURE log_ddl_tag();
|
CREATE EVENT TRIGGER log_ddl_tag ON ddl_command_end EXECUTE PROCEDURE log_ddl_tag();
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 224000;
|
||||||
-- The above trigger will cause failure at transaction end on one placement.
|
-- The above trigger will cause failure at transaction end on one placement.
|
||||||
-- Citus always uses 2PC. 2PC should handle this "best" (no divergence)
|
-- Citus always uses 2PC. 2PC should handle this "best" (no divergence)
|
||||||
BEGIN;
|
BEGIN;
|
||||||
|
@ -321,6 +330,8 @@ DROP FUNCTION log_ddl_tag();
|
||||||
DROP TABLE ddl_commands;
|
DROP TABLE ddl_commands;
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 225000;
|
||||||
-- Distributed SELECTs may appear after ALTER
|
-- Distributed SELECTs may appear after ALTER
|
||||||
BEGIN;
|
BEGIN;
|
||||||
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
CREATE INDEX temp_index_2 ON lineitem_alter(l_orderkey);
|
||||||
|
@ -360,6 +371,8 @@ FROM
|
||||||
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
JOIN pg_attribute ON (pc.oid = pg_attribute.attrelid)
|
||||||
ORDER BY attnum;
|
ORDER BY attnum;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 226000;
|
||||||
|
|
||||||
-- verify that we can rename distributed tables
|
-- verify that we can rename distributed tables
|
||||||
SHOW citus.enable_ddl_propagation;
|
SHOW citus.enable_ddl_propagation;
|
||||||
|
@ -372,29 +385,37 @@ SELECT relname FROM pg_class WHERE relname = 'lineitem_renamed';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_renamed%' ORDER BY relname;
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_renamed%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 227000;
|
||||||
|
|
||||||
-- revert it to original name
|
-- revert it to original name
|
||||||
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
ALTER TABLE lineitem_renamed RENAME TO lineitem_alter;
|
||||||
|
|
||||||
-- show rename worked on one worker, too
|
-- show rename worked on one worker, too
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 228000;
|
||||||
|
|
||||||
-- verify that we can set and reset storage parameters
|
-- verify that we can set and reset storage parameters
|
||||||
ALTER TABLE lineitem_alter SET(fillfactor=40);
|
ALTER TABLE lineitem_alter SET(fillfactor=40);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 229000;
|
||||||
|
|
||||||
ALTER TABLE lineitem_alter RESET(fillfactor);
|
ALTER TABLE lineitem_alter RESET(fillfactor);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'lineitem_alter';
|
||||||
|
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_220002' /* failed copy trails */ ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'lineitem_alter%' AND relname <> 'lineitem_alter_222001' /* failed copy trails */ ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 230000;
|
||||||
|
|
||||||
-- verify that we can rename indexes on distributed tables
|
-- verify that we can rename indexes on distributed tables
|
||||||
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
CREATE INDEX temp_index_1 ON lineitem_alter(l_linenumber);
|
||||||
|
@ -407,6 +428,8 @@ SELECT relname FROM pg_class WHERE relname = 'idx_lineitem_linenumber';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%' ORDER BY relname;
|
SELECT relname FROM pg_class WHERE relname LIKE 'idx_lineitem_linenumber%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 231000;
|
||||||
|
|
||||||
-- now get rid of the index
|
-- now get rid of the index
|
||||||
DROP INDEX idx_lineitem_linenumber;
|
DROP INDEX idx_lineitem_linenumber;
|
||||||
|
@ -427,8 +450,10 @@ ALTER TABLE lineitem_alter ADD COLUMN column_only_added_to_master int;
|
||||||
|
|
||||||
-- verify newly added column is not present in a worker shard
|
-- verify newly added column is not present in a worker shard
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT column_only_added_to_master FROM lineitem_alter_220000 LIMIT 0;
|
SELECT column_only_added_to_master FROM multi_alter_table_statements.lineitem_alter_220000 LIMIT 0;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 232000;
|
||||||
|
|
||||||
-- ddl propagation flag is reset to default, disable it again
|
-- ddl propagation flag is reset to default, disable it again
|
||||||
SET citus.enable_ddl_propagation to false;
|
SET citus.enable_ddl_propagation to false;
|
||||||
|
@ -458,6 +483,8 @@ SELECT indexname, tablename FROM pg_indexes WHERE tablename = 'lineitem_alter';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT indexname, tablename FROM pg_indexes WHERE tablename like 'lineitem_alter_%';
|
SELECT indexname, tablename FROM pg_indexes WHERE tablename like 'lineitem_alter_%';
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 233000;
|
||||||
|
|
||||||
-- verify alter table and drop sequence in the same transaction does not cause deadlock
|
-- verify alter table and drop sequence in the same transaction does not cause deadlock
|
||||||
SET citus.shard_count TO 4;
|
SET citus.shard_count TO 4;
|
||||||
|
@ -489,7 +516,7 @@ SELECT create_distributed_table('trigger_table', 'id');
|
||||||
-- first set a trigger on a shard
|
-- first set a trigger on a shard
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SET citus.enable_metadata_sync TO OFF;
|
SET citus.enable_metadata_sync TO OFF;
|
||||||
CREATE FUNCTION update_value() RETURNS trigger AS $up$
|
CREATE OR REPLACE FUNCTION update_value() RETURNS trigger AS $up$
|
||||||
BEGIN
|
BEGIN
|
||||||
NEW.value := 'trigger enabled';
|
NEW.value := 'trigger enabled';
|
||||||
RETURN NEW;
|
RETURN NEW;
|
||||||
|
@ -498,10 +525,12 @@ $up$ LANGUAGE plpgsql;
|
||||||
RESET citus.enable_metadata_sync;
|
RESET citus.enable_metadata_sync;
|
||||||
|
|
||||||
CREATE TRIGGER update_value
|
CREATE TRIGGER update_value
|
||||||
BEFORE INSERT ON trigger_table_220017
|
BEFORE INSERT ON multi_alter_table_statements.trigger_table_233004
|
||||||
FOR EACH ROW EXECUTE PROCEDURE update_value();
|
FOR EACH ROW EXECUTE PROCEDURE update_value();
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 234000;
|
||||||
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
INSERT INTO trigger_table VALUES (1, 'trigger disabled');
|
||||||
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
SELECT value, count(*) FROM trigger_table GROUP BY value ORDER BY value;
|
||||||
|
|
||||||
|
@ -529,32 +558,36 @@ SET citus.enable_ddl_propagation to true;
|
||||||
CREATE USER alter_table_owner WITH LOGIN;
|
CREATE USER alter_table_owner WITH LOGIN;
|
||||||
|
|
||||||
GRANT USAGE ON SCHEMA public TO alter_table_owner;
|
GRANT USAGE ON SCHEMA public TO alter_table_owner;
|
||||||
|
GRANT USAGE ON SCHEMA multi_alter_table_statements TO alter_table_owner;
|
||||||
|
|
||||||
\c - alter_table_owner - :master_port
|
\c - alter_table_owner - :master_port
|
||||||
-- should not be able to access table without permission
|
-- should not be able to access table without permission
|
||||||
SELECT count(*) FROM lineitem_alter;
|
SELECT count(*) FROM multi_alter_table_statements.lineitem_alter;
|
||||||
|
|
||||||
-- should not be able to drop the table as non table owner
|
-- should not be able to drop the table as non table owner
|
||||||
DROP TABLE lineitem_alter;
|
DROP TABLE multi_alter_table_statements.lineitem_alter;
|
||||||
|
|
||||||
\c - postgres - :master_port
|
\c - postgres - :master_port
|
||||||
ALTER TABLE lineitem_alter OWNER TO alter_table_owner;
|
ALTER TABLE multi_alter_table_statements.lineitem_alter OWNER TO alter_table_owner;
|
||||||
|
|
||||||
\c - alter_table_owner - :master_port
|
\c - alter_table_owner - :master_port
|
||||||
-- should be able to query the table as table owner
|
-- should be able to query the table as table owner
|
||||||
SELECT count(*) FROM lineitem_alter;
|
SELECT count(*) FROM multi_alter_table_statements.lineitem_alter;
|
||||||
|
|
||||||
-- should be able to drop the table as table owner
|
-- should be able to drop the table as table owner
|
||||||
DROP TABLE lineitem_alter;
|
DROP TABLE multi_alter_table_statements.lineitem_alter;
|
||||||
|
|
||||||
-- check that nothing's left over on workers, other than the leftover shard created
|
-- check that nothing's left over on workers, other than the leftover shard created
|
||||||
-- during the unsuccessful COPY
|
-- during the unsuccessful COPY
|
||||||
\c - postgres - :worker_1_port
|
\c - postgres - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%';
|
SELECT relname FROM pg_class WHERE relname LIKE 'lineitem_alter%';
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 235000;
|
||||||
|
|
||||||
-- drop the roles created
|
-- drop the roles created
|
||||||
REVOKE ALL ON SCHEMA PUBLIC FROM alter_table_owner;
|
REVOKE ALL ON SCHEMA PUBLIC FROM alter_table_owner;
|
||||||
|
REVOKE ALL ON SCHEMA multi_alter_table_statements FROM alter_table_owner;
|
||||||
DROP ROLE alter_table_owner;
|
DROP ROLE alter_table_owner;
|
||||||
|
|
||||||
-- Test alter table with drop table in the same transaction
|
-- Test alter table with drop table in the same transaction
|
||||||
|
@ -569,6 +602,8 @@ END;
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname FROM pg_class WHERE relname LIKE 'test_table_1%';
|
SELECT relname FROM pg_class WHERE relname LIKE 'test_table_1%';
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 236000;
|
||||||
|
|
||||||
-- verify logged info is propagated to workers when distributing the table
|
-- verify logged info is propagated to workers when distributing the table
|
||||||
CREATE TABLE logged_test(id int);
|
CREATE TABLE logged_test(id int);
|
||||||
|
@ -577,6 +612,8 @@ SELECT create_distributed_table('logged_test', 'id');
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 237000;
|
||||||
|
|
||||||
-- verify SET LOGGED/UNLOGGED works after distributing the table
|
-- verify SET LOGGED/UNLOGGED works after distributing the table
|
||||||
ALTER TABLE logged_test SET LOGGED;
|
ALTER TABLE logged_test SET LOGGED;
|
||||||
|
@ -584,11 +621,15 @@ SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logg
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 238000;
|
||||||
ALTER TABLE logged_test SET UNLOGGED;
|
ALTER TABLE logged_test SET UNLOGGED;
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test*' ORDER BY relname;
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
SELECT relname, CASE relpersistence WHEN 'u' THEN 'unlogged' WHEN 'p' then 'logged' ELSE 'unknown' END AS logged_info FROM pg_class WHERE relname ~ 'logged_test_' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 239000;
|
||||||
DROP TABLE logged_test;
|
DROP TABLE logged_test;
|
||||||
|
|
||||||
-- Test WITH options on a normal simple hash-distributed table
|
-- Test WITH options on a normal simple hash-distributed table
|
||||||
|
@ -601,6 +642,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relkind = 'r' AND relname LIKE 'hash_dist_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relkind = 'r' AND relname LIKE 'hash_dist_%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 240000;
|
||||||
|
|
||||||
-- verify that we can set and reset index storage parameters
|
-- verify that we can set and reset index storage parameters
|
||||||
ALTER INDEX hash_dist_pkey SET(fillfactor=40);
|
ALTER INDEX hash_dist_pkey SET(fillfactor=40);
|
||||||
|
@ -609,6 +652,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 241000;
|
||||||
|
|
||||||
ALTER INDEX hash_dist_pkey RESET(fillfactor);
|
ALTER INDEX hash_dist_pkey RESET(fillfactor);
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
|
@ -616,6 +661,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'hash_dist_pkey';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'hash_dist_pkey_%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 242000;
|
||||||
|
|
||||||
-- verify error message on ALTER INDEX, SET TABLESPACE is unsupported
|
-- verify error message on ALTER INDEX, SET TABLESPACE is unsupported
|
||||||
ALTER INDEX hash_dist_pkey SET TABLESPACE foo;
|
ALTER INDEX hash_dist_pkey SET TABLESPACE foo;
|
||||||
|
@ -629,6 +676,8 @@ SELECT relname, reloptions FROM pg_class WHERE relname = 'another_index';
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index_%' ORDER BY relname;
|
SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index_%' ORDER BY relname;
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
SET search_path TO multi_alter_table_statements, public;
|
||||||
|
SET citus.next_shard_id TO 243000;
|
||||||
|
|
||||||
-- get rid of the index
|
-- get rid of the index
|
||||||
DROP INDEX another_index;
|
DROP INDEX another_index;
|
||||||
|
@ -645,13 +694,24 @@ ALTER TABLE test_table_1 ADD COLUMN test_col int CHECK (test_col > 3);
|
||||||
|
|
||||||
CREATE TABLE reference_table(i int UNIQUE);
|
CREATE TABLE reference_table(i int UNIQUE);
|
||||||
SELECT create_reference_table('reference_table');
|
SELECT create_reference_table('reference_table');
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE;
|
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
ALTER TABLE test_table_1 ADD COLUMN test_col_1 int REFERENCES reference_table(i) ON DELETE CASCADE;
|
||||||
DROP TABLE reference_table;
|
ALTER TABLE test_table_1 ADD COLUMN test_col_2 int REFERENCES reference_table(i) ON DELETE CASCADE ON UPDATE SET NULL;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('multi_alter_table_statements.test_table_1')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SET LOCAL client_min_messages TO WARNING;
|
||||||
|
DROP TABLE reference_table CASCADE;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
CREATE TABLE referenced_table(i int UNIQUE);
|
CREATE TABLE referenced_table(i int UNIQUE);
|
||||||
SELECT create_distributed_table('referenced_table', 'i');
|
SELECT create_distributed_table('referenced_table', 'i');
|
||||||
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES referenced_table(i);
|
ALTER TABLE test_table_1 ADD COLUMN test_col_3 int REFERENCES referenced_table(i);
|
||||||
DROP TABLE referenced_table, test_table_1;
|
DROP TABLE referenced_table, test_table_1;
|
||||||
|
|
||||||
-- Check sequence propagate its own dependencies while adding a column
|
-- Check sequence propagate its own dependencies while adding a column
|
||||||
|
@ -667,5 +727,7 @@ ALTER TABLE table_without_sequence ADD COLUMN x BIGINT DEFAULT nextval('test_sch
|
||||||
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation.seq_10'::regclass);
|
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation.seq_10'::regclass);
|
||||||
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation'::regnamespace);
|
SELECT pg_identify_object_as_address(classid, objid, objsubid) from pg_catalog.pg_dist_object WHERE objid IN ('test_schema_for_sequence_propagation'::regnamespace);
|
||||||
|
|
||||||
|
SET client_min_messages TO WARNING;
|
||||||
DROP SCHEMA test_schema_for_sequence_propagation CASCADE;
|
DROP SCHEMA test_schema_for_sequence_propagation CASCADE;
|
||||||
DROP TABLE table_without_sequence;
|
DROP TABLE table_without_sequence;
|
||||||
|
DROP SCHEMA multi_alter_table_statements CASCADE;
|
||||||
|
|
|
@ -7,7 +7,12 @@ SET citus.next_shard_id TO 390000;
|
||||||
-- ===================================================================
|
-- ===================================================================
|
||||||
|
|
||||||
-- create fake fdw for use in tests
|
-- create fake fdw for use in tests
|
||||||
CREATE FUNCTION fake_fdw_handler()
|
SET client_min_messages TO WARNING;
|
||||||
|
DROP SERVER IF EXISTS fake_fdw_server CASCADE;
|
||||||
|
DROP FOREIGN DATA WRAPPER IF EXISTS fake_fdw CASCADE;
|
||||||
|
RESET client_min_messages;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION fake_fdw_handler()
|
||||||
RETURNS fdw_handler
|
RETURNS fdw_handler
|
||||||
AS 'citus'
|
AS 'citus'
|
||||||
LANGUAGE C STRICT;
|
LANGUAGE C STRICT;
|
||||||
|
|
|
@ -65,6 +65,7 @@ CREATE TABLE seq_test_4 (x int, y int);
|
||||||
SELECT create_distributed_table('seq_test_4','x');
|
SELECT create_distributed_table('seq_test_4','x');
|
||||||
CREATE SEQUENCE seq_4;
|
CREATE SEQUENCE seq_4;
|
||||||
ALTER TABLE seq_test_4 ADD COLUMN a bigint DEFAULT nextval('seq_4');
|
ALTER TABLE seq_test_4 ADD COLUMN a bigint DEFAULT nextval('seq_4');
|
||||||
|
ALTER TABLE seq_test_4 ADD COLUMN IF NOT EXISTS a bigint DEFAULT nextval('seq_4');
|
||||||
DROP SEQUENCE seq_4 CASCADE;
|
DROP SEQUENCE seq_4 CASCADE;
|
||||||
TRUNCATE seq_test_4;
|
TRUNCATE seq_test_4;
|
||||||
CREATE SEQUENCE seq_4;
|
CREATE SEQUENCE seq_4;
|
||||||
|
@ -440,7 +441,7 @@ ROLLBACK;
|
||||||
-- Show that existing sequence has been renamed and a new sequence with the same name
|
-- Show that existing sequence has been renamed and a new sequence with the same name
|
||||||
-- created for another type
|
-- created for another type
|
||||||
\c - - - :worker_1_port
|
\c - - - :worker_1_port
|
||||||
SELECT seqrelid::regclass, seqtypid::regtype, seqmax, seqmin FROM pg_sequence WHERE seqrelid::regclass::text like '%sequence_rollback%' ORDER BY 1,2;
|
SELECT seqrelid::regclass, seqtypid::regtype, seqmax, seqmin FROM pg_sequence WHERE seqrelid::regclass::text in ('sequence_rollback', '"sequence_rollback(citus_backup_0)"') ORDER BY 1,2;
|
||||||
|
|
||||||
\c - - - :master_port
|
\c - - - :master_port
|
||||||
|
|
||||||
|
|
|
@ -180,3 +180,139 @@ BEGIN
|
||||||
EXECUTE 'SELECT COUNT(*) FROM pg_catalog.pg_dist_cleanup' INTO record_count;
|
EXECUTE 'SELECT COUNT(*) FROM pg_catalog.pg_dist_cleanup' INTO record_count;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END$$ LANGUAGE plpgsql;
|
END$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Returns the foreign keys where the referencing relation's name starts with
|
||||||
|
-- given prefix.
|
||||||
|
--
|
||||||
|
-- Foreign keys are groupped by their configurations and then the constraint name,
|
||||||
|
-- referencing table, and referenced table for each distinct configuration are
|
||||||
|
-- aggregated into arrays.
|
||||||
|
CREATE OR REPLACE FUNCTION get_grouped_fkey_constraints(referencing_relname_prefix text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
confdelsetcols_column_ref text;
|
||||||
|
get_grouped_fkey_constraints_query text;
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
-- Read confdelsetcols as null if no such column exists.
|
||||||
|
-- This can only be the case for PG versions < 15.
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'pg_constraint'::regclass AND attname='confdelsetcols')
|
||||||
|
THEN
|
||||||
|
confdelsetcols_column_ref := '(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = conrelid AND attnum = ANY(confdelsetcols))';
|
||||||
|
ELSE
|
||||||
|
confdelsetcols_column_ref := '(SELECT null::smallint[])';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.constraint_names) AS fkeys_with_different_config FROM (
|
||||||
|
SELECT array_agg(constraint_name ORDER BY constraint_oid) AS constraint_names,
|
||||||
|
array_agg(referencing_table::regclass::text ORDER BY constraint_oid) AS referencing_tables,
|
||||||
|
array_agg(referenced_table::regclass::text ORDER BY constraint_oid) AS referenced_tables,
|
||||||
|
referencing_columns, referenced_columns, deferable, deferred, on_update, on_delete, match_type, referencing_columns_set_null_or_default
|
||||||
|
FROM (
|
||||||
|
SELECT
|
||||||
|
oid AS constraint_oid,
|
||||||
|
conname AS constraint_name,
|
||||||
|
conrelid AS referencing_table,
|
||||||
|
(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = conrelid AND attnum = ANY(conkey)) AS referencing_columns,
|
||||||
|
confrelid AS referenced_table,
|
||||||
|
(SELECT array_agg(attname ORDER BY attnum) FROM pg_attribute WHERE attrelid = confrelid AND attnum = ANY(confkey)) AS referenced_columns,
|
||||||
|
condeferrable AS deferable,
|
||||||
|
condeferred AS deferred,
|
||||||
|
confupdtype AS on_update,
|
||||||
|
confdeltype AS on_delete,
|
||||||
|
confmatchtype AS match_type,
|
||||||
|
%2$s AS referencing_columns_set_null_or_default
|
||||||
|
FROM pg_constraint WHERE starts_with(conrelid::regclass::text, '%1$s') AND contype = 'f'
|
||||||
|
) q2
|
||||||
|
GROUP BY referencing_columns, referenced_columns, deferable, deferred, on_update, on_delete, match_type, referencing_columns_set_null_or_default
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
referencing_relname_prefix,
|
||||||
|
confdelsetcols_column_ref
|
||||||
|
) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION get_index_defs(schemaname text, tablename text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
indnullsnotdistinct_column_ref text;
|
||||||
|
BEGIN
|
||||||
|
-- Not use indnullsnotdistinct in group by clause if no such column exists.
|
||||||
|
-- This can only be the case for PG versions < 15.
|
||||||
|
IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid = 'pg_index'::regclass AND attname='indnullsnotdistinct')
|
||||||
|
THEN
|
||||||
|
indnullsnotdistinct_column_ref := ',indnullsnotdistinct';
|
||||||
|
ELSE
|
||||||
|
indnullsnotdistinct_column_ref := '';
|
||||||
|
END IF;
|
||||||
|
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.indexnames) AS index_defs FROM (
|
||||||
|
SELECT array_agg(indexname ORDER BY indexrelid) AS indexnames,
|
||||||
|
array_agg(indexdef ORDER BY indexrelid) AS indexdefs
|
||||||
|
FROM pg_indexes
|
||||||
|
JOIN pg_index
|
||||||
|
ON (indexrelid = (schemaname || '.' || indexname)::regclass)
|
||||||
|
WHERE schemaname = '%1$s' AND starts_with(tablename, '%2$s')
|
||||||
|
GROUP BY indnatts, indnkeyatts, indisunique, indisprimary, indisexclusion,
|
||||||
|
indimmediate, indisclustered, indisvalid, indisready, indislive,
|
||||||
|
indisreplident, indkey, indcollation, indclass, indoption, indexprs,
|
||||||
|
indpred %3$s
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
schemaname, tablename, indnullsnotdistinct_column_ref) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION get_column_defaults(schemaname text, tablename text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT jsonb_agg(to_jsonb(q1.*) ORDER BY q1.column_name) AS column_defs FROM (
|
||||||
|
SELECT column_name, column_default::text, generation_expression::text
|
||||||
|
FROM information_schema.columns
|
||||||
|
WHERE table_schema = '%1$s' AND table_name = '%2$s' AND
|
||||||
|
column_default IS NOT NULL OR generation_expression IS NOT NULL
|
||||||
|
) q1
|
||||||
|
$$,
|
||||||
|
schemaname, tablename) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION get_column_attrs(relname_prefix text)
|
||||||
|
RETURNS jsonb AS $func$
|
||||||
|
DECLARE
|
||||||
|
result jsonb;
|
||||||
|
BEGIN
|
||||||
|
EXECUTE format(
|
||||||
|
$$
|
||||||
|
SELECT to_jsonb(q2.*) FROM (
|
||||||
|
SELECT relnames, jsonb_agg(to_jsonb(q1.*) - 'relnames' ORDER BY q1.column_name) AS column_attrs FROM (
|
||||||
|
SELECT array_agg(attrelid::regclass::text ORDER BY attrelid) AS relnames,
|
||||||
|
attname AS column_name, typname AS type_name, collname AS collation_name, attcompression AS compression_method, attnotnull AS not_null
|
||||||
|
FROM pg_attribute pa
|
||||||
|
LEFT JOIN pg_type pt ON (pa.atttypid = pt.oid)
|
||||||
|
LEFT JOIN pg_collation pc1 ON (pa.attcollation = pc1.oid)
|
||||||
|
JOIN pg_class pc2 ON (pa.attrelid = pc2.oid)
|
||||||
|
WHERE starts_with(attrelid::regclass::text, '%1$s') AND
|
||||||
|
attnum > 0 AND NOT attisdropped AND relkind = 'r'
|
||||||
|
GROUP BY column_name, type_name, collation_name, compression_method, not_null
|
||||||
|
) q1
|
||||||
|
GROUP BY relnames
|
||||||
|
) q2
|
||||||
|
$$,
|
||||||
|
relname_prefix) INTO result;
|
||||||
|
RETURN result;
|
||||||
|
END;
|
||||||
|
$func$ LANGUAGE plpgsql;
|
||||||
|
|
|
@ -933,6 +933,38 @@ DROP TABLE mx_ddl_table2;
|
||||||
DROP ACCESS METHOD heap2;
|
DROP ACCESS METHOD heap2;
|
||||||
SELECT run_command_on_workers($$DROP ACCESS METHOD heap2$$);
|
SELECT run_command_on_workers($$DROP ACCESS METHOD heap2$$);
|
||||||
|
|
||||||
|
CREATE TABLE referenced (int_col integer PRIMARY KEY);
|
||||||
|
CREATE TABLE referencing (text_col text);
|
||||||
|
|
||||||
|
SET citus.shard_replication_factor TO 1;
|
||||||
|
SELECT create_distributed_table('referenced', null);
|
||||||
|
SELECT create_distributed_table('referencing', null);
|
||||||
|
RESET citus.shard_replication_factor;
|
||||||
|
|
||||||
|
CREATE OR REPLACE FUNCTION my_random(numeric)
|
||||||
|
RETURNS numeric AS
|
||||||
|
$$
|
||||||
|
BEGIN
|
||||||
|
RETURN 7 * $1;
|
||||||
|
END;
|
||||||
|
$$
|
||||||
|
LANGUAGE plpgsql IMMUTABLE;
|
||||||
|
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_2 integer UNIQUE NULLS DISTINCT REFERENCES referenced(int_col);
|
||||||
|
ALTER TABLE referencing ADD COLUMN test_3 integer GENERATED ALWAYS AS (text_col::int * my_random(1)) STORED UNIQUE NULLS NOT DISTINCT;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_grouped_fkey_constraints FROM get_grouped_fkey_constraints('pg15.referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
|
SELECT (groupid = 0) AS is_coordinator, result FROM run_command_on_all_nodes(
|
||||||
|
$$SELECT get_index_defs FROM get_index_defs('pg15', 'referencing')$$
|
||||||
|
)
|
||||||
|
JOIN pg_dist_node USING (nodeid)
|
||||||
|
ORDER BY is_coordinator DESC, result;
|
||||||
|
|
||||||
-- Clean up
|
-- Clean up
|
||||||
\set VERBOSITY terse
|
\set VERBOSITY terse
|
||||||
SET client_min_messages TO ERROR;
|
SET client_min_messages TO ERROR;
|
||||||
|
|
Loading…
Reference in New Issue