Compare commits

...

17 Commits
main ... v7.5.1

Author SHA1 Message Date
velioglu 8027fdbfb8 Bump version to 7.5.1 2018-08-28 15:33:19 +03:00
velioglu 33611c168a Add changelog entry for 7.5.1 2018-08-28 14:17:24 +03:00
Onder Kalaci 4c94bf3eae Make sure that modifying CTEs always use the correct execution mode 2018-08-28 13:21:37 +03:00
Onder Kalaci a207c84548 Prevent multiple placements of a single shard to lead huge memory allocations 2018-08-28 13:04:33 +03:00
Onder Kalaci 509b993758 Prevent excessive number of unnecessary range table traversal 2018-08-28 13:04:25 +03:00
mehmet furkan Ĺźahin 8a86c87750
ApplyLogRedaction noop func is added 2018-08-20 10:37:08 -06:00
Jason Petersen 95141fef42 Add test showing poolinfo validation works
In other words, that it errors out.
2018-08-08 10:52:27 -06:00
mehmet furkan Ĺźahin 2bbdfad1fd windows version fix 2018-07-27 09:59:42 +03:00
mehmet furkan Ĺźahin 00bd8bfa8a Bump Citus version to 7.5.0 2018-07-26 11:25:15 +03:00
mehmet furkan Ĺźahin fa5b3f4ffc Add changelog entry for 7.5.0 2018-07-25 11:26:34 +03:00
velioglu af31f74cd1 Use contype to check for FK constraint instead of reading catalog table 2018-07-24 16:23:33 +03:00
mehmet furkan Ĺźahin 5ab0bc8c0a ALTER TABLE %s ADD COLUMN constraint check is added 2018-07-24 16:23:25 +03:00
Marco Slot 7c3c29e505
Don't try to check unopened connection in EXEC_TASK_FAILED state 2018-07-23 12:36:33 -06:00
Nils Dijk 416738374a
error on unsupported changing of distirbution column in ON CONFLICT for INSERT ... SELECT 2018-07-23 12:36:33 -06:00
Nils Dijk 9d8236961b
extract ErrorIfOnConflictNotSupported function for reuse 2018-07-23 12:36:33 -06:00
Nils Dijk 3eff9e8b9d
fix missing space for tablein in error 2018-07-23 12:36:33 -06:00
Marco Slot db07901889
Ensure StartPlacementListConnection connects with username supplied by the caller 2018-07-23 12:36:32 -06:00
54 changed files with 2763 additions and 458 deletions

View File

@ -1,3 +1,43 @@
### citus v7.5.1 (August 28, 2018) ###
* Improves query pushdown planning performance
* Fixes a bug that could cause modifying CTEs to select wrong execution mode
### citus v7.4.2 (July 27, 2018) ###
* Fixes a segfault in real-time executor during online shard move
### citus v7.5.0 (July 25, 2018) ###
* Adds foreign key support from hash distributed to reference tables
* Adds SELECT ... FOR UPDATE support for router plannable queries
* Adds support for non-partition columns in count distinct
* Fixes a segfault in real-time executor during online shard move
* Fixes ALTER TABLE ADD COLUMN constraint check
* Fixes a bug where INSERT ... SELECT was allowed to update distribution column
* Allows DDL commands to be sequentialized via `citus.multi_shard_modify_mode`
* Adds support for topn_union_agg and topn_add_agg across shards
* Adds support for hll_union_agg and hll_add_agg across shards
* Fixes a bug that might cause shards to have a wrong owner
* GUC select_opens_transaction_block defers opening transaction block on workers
* Utils to implement DDLs for policies in future, warn about being unsupported
* Intermediate results use separate connections to avoid interfering with tasks
* Adds a node_conninfo GUC to set outgoing connection settings
### citus v6.2.6 (July 06, 2018) ###
* Adds support for respecting enable_hashagg in the master planner

18
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for Citus 7.5devel.
# Generated by GNU Autoconf 2.69 for Citus 7.5.1.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@ -579,8 +579,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='Citus'
PACKAGE_TARNAME='citus'
PACKAGE_VERSION='7.5devel'
PACKAGE_STRING='Citus 7.5devel'
PACKAGE_VERSION='7.5.1'
PACKAGE_STRING='Citus 7.5.1'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@ -1239,7 +1239,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures Citus 7.5devel to adapt to many kinds of systems.
\`configure' configures Citus 7.5.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1300,7 +1300,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of Citus 7.5devel:";;
short | recursive ) echo "Configuration of Citus 7.5.1:";;
esac
cat <<\_ACEOF
@ -1400,7 +1400,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
Citus configure 7.5devel
Citus configure 7.5.1
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@ -1883,7 +1883,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by Citus $as_me 7.5devel, which was
It was created by Citus $as_me 7.5.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@ -4701,7 +4701,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by Citus $as_me 7.5devel, which was
This file was extended by Citus $as_me 7.5.1, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -4763,7 +4763,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
Citus config.status 7.5devel
Citus config.status 7.5.1
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"

View File

@ -5,7 +5,7 @@
# everyone needing autoconf installed, the resulting files are checked
# into the SCM.
AC_INIT([Citus], [7.5devel])
AC_INIT([Citus], [7.5.1])
AC_COPYRIGHT([Copyright (c) 2012-2017, Citus Data, Inc.])
# we'll need sed and awk for some of the version commands

View File

@ -1240,7 +1240,8 @@ ReportCopyError(MultiConnection *connection, PGresult *result)
bool haveDetail = remoteDetail != NULL;
ereport(ERROR, (errmsg("%s", remoteMessage),
haveDetail ? errdetail("%s", remoteDetail) : 0));
haveDetail ? errdetail("%s", ApplyLogRedaction(remoteDetail)) :
0));
}
else
{
@ -1250,7 +1251,7 @@ ReportCopyError(MultiConnection *connection, PGresult *result)
ereport(ERROR, (errcode(ERRCODE_IO_ERROR),
errmsg("failed to complete COPY on %s:%d", connection->hostname,
connection->port),
errdetail("%s", remoteMessage)));
errdetail("%s", ApplyLogRedaction(remoteMessage))));
}
}

View File

@ -22,6 +22,7 @@
#include "access/hash.h"
#include "commands/dbcommands.h"
#include "distributed/connection_management.h"
#include "distributed/errormessage.h"
#include "distributed/metadata_cache.h"
#include "distributed/hash_helpers.h"
#include "distributed/placement_connection.h"
@ -824,9 +825,9 @@ DefaultCitusNoticeProcessor(void *arg, const char *message)
char *trimmedMessage = TrimLogLevel(message);
char *level = strtok((char *) message, ":");
ereport(CitusNoticeLogLevel, (errmsg("%s", trimmedMessage),
errdetail("%s from %s:%d",
level, nodeName, nodePort)));
ereport(CitusNoticeLogLevel,
(errmsg("%s", ApplyLogRedaction(trimmedMessage)),
errdetail("%s from %s:%d", level, nodeName, nodePort)));
}

View File

@ -311,7 +311,8 @@ StartPlacementListConnection(uint32 flags, List *placementAccessList,
* No suitable connection in the placement->connection mapping, get one from
* the node->connection pool.
*/
chosenConnection = StartNodeConnection(flags, nodeName, nodePort);
chosenConnection = StartNodeUserDatabaseConnection(flags, nodeName, nodePort,
userName, NULL);
if (flags & CONNECTION_PER_PLACEMENT &&
ConnectionAccessedDifferentPlacement(chosenConnection, placement))
@ -328,8 +329,10 @@ StartPlacementListConnection(uint32 flags, List *placementAccessList,
* ID as the current placement, then we'd no longer able to write to
* placement B later in the COPY.
*/
chosenConnection = StartNodeConnection(flags | FORCE_NEW_CONNECTION, nodeName,
nodePort);
chosenConnection = StartNodeUserDatabaseConnection(flags |
FORCE_NEW_CONNECTION,
nodeName, nodePort,
userName, NULL);
Assert(!ConnectionAccessedDifferentPlacement(chosenConnection, placement));
}

View File

@ -14,6 +14,7 @@
#include "libpq-fe.h"
#include "distributed/connection_management.h"
#include "distributed/errormessage.h"
#include "distributed/remote_commands.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"
@ -253,7 +254,8 @@ ReportConnectionError(MultiConnection *connection, int elevel)
ereport(elevel, (errcode(ERRCODE_CONNECTION_FAILURE),
errmsg("connection error: %s:%d", nodeName, nodePort),
messageDetail != NULL ? errdetail("%s", messageDetail) : 0));
messageDetail != NULL ?
errdetail("%s", ApplyLogRedaction(messageDetail)) : 0));
}
@ -295,7 +297,8 @@ ReportResultError(MultiConnection *connection, PGresult *result, int elevel)
}
ereport(elevel, (errcode(sqlState), errmsg("%s", messagePrimary),
messageDetail ? errdetail("%s", messageDetail) : 0,
messageDetail ?
errdetail("%s", ApplyLogRedaction(messageDetail)) : 0,
messageHint ? errhint("%s", messageHint) : 0,
messageContext ? errcontext("%s", messageContext) : 0,
errcontext("while executing command on %s:%d",
@ -344,7 +347,7 @@ LogRemoteCommand(MultiConnection *connection, const char *command)
return;
}
ereport(LOG, (errmsg("issuing %s", command),
ereport(LOG, (errmsg("issuing %s", ApplyLogRedaction(command)),
errdetail("on server %s:%d", connection->hostname, connection->port)));
}

View File

@ -88,19 +88,10 @@ static CustomExecMethods TaskTrackerCustomExecMethods = {
.ExplainCustomScan = CitusExplainScan
};
static CustomExecMethods RouterSequentialModifyCustomExecMethods = {
.CustomName = "RouterSequentialModifyScan",
static CustomExecMethods RouterModifyCustomExecMethods = {
.CustomName = "RouterModifyScan",
.BeginCustomScan = CitusModifyBeginScan,
.ExecCustomScan = RouterSequentialModifyExecScan,
.EndCustomScan = CitusEndScan,
.ReScanCustomScan = CitusReScan,
.ExplainCustomScan = CitusExplainScan
};
static CustomExecMethods RouterMultiModifyCustomExecMethods = {
.CustomName = "RouterMultiModifyScan",
.BeginCustomScan = CitusModifyBeginScan,
.ExecCustomScan = RouterMultiModifyExecScan,
.ExecCustomScan = RouterModifyExecScan,
.EndCustomScan = CitusEndScan,
.ReScanCustomScan = CitusReScan,
.ExplainCustomScan = CitusExplainScan
@ -187,6 +178,8 @@ RouterCreateScan(CustomScan *scan)
List *taskList = NIL;
bool isModificationQuery = false;
List *relationRowLockList = NIL;
scanState->executorType = MULTI_EXECUTOR_ROUTER;
scanState->customScanState.ss.ps.type = T_CustomScanState;
scanState->distributedPlan = GetDistributedPlan(scan);
@ -194,13 +187,8 @@ RouterCreateScan(CustomScan *scan)
distributedPlan = scanState->distributedPlan;
workerJob = distributedPlan->workerJob;
taskList = workerJob->taskList;
isModificationQuery = IsModifyDistributedPlan(distributedPlan);
/* check whether query has at most one shard */
if (list_length(taskList) <= 1)
{
List *relationRowLockList = NIL;
if (list_length(taskList) == 1)
{
Task *task = (Task *) linitial(taskList);
@ -210,32 +198,12 @@ RouterCreateScan(CustomScan *scan)
/* if query is SELECT ... FOR UPDATE query, use modify logic */
if (isModificationQuery || relationRowLockList != NIL)
{
scanState->customScanState.methods = &RouterSequentialModifyCustomExecMethods;
scanState->customScanState.methods = &RouterModifyCustomExecMethods;
}
else
{
scanState->customScanState.methods = &RouterSelectCustomExecMethods;
}
}
else
{
Assert(isModificationQuery);
if (IsMultiRowInsert(workerJob->jobQuery) ||
MultiShardConnectionType == SEQUENTIAL_CONNECTION)
{
/*
* Multi shard modifications while multi_shard_modify_mode equals
* to 'sequential' or Multi-row INSERT are executed sequentially
* instead of using parallel connections.
*/
scanState->customScanState.methods = &RouterSequentialModifyCustomExecMethods;
}
else
{
scanState->customScanState.methods = &RouterMultiModifyCustomExecMethods;
}
}
return (Node *) scanState;
}

View File

@ -294,6 +294,14 @@ MultiClientConnectPoll(int32 connectionId)
MultiConnection *
MultiClientGetConnection(int32 connectionId)
{
if (connectionId == INVALID_CONNECTION_ID)
{
return NULL;
}
Assert(connectionId >= 0);
Assert(connectionId < MAX_CONNECTION_COUNT);
return ClientConnectionArray[connectionId];
}
@ -411,8 +419,17 @@ MultiClientSendQuery(int32 connectionId, const char *query)
if (querySent == 0)
{
char *errorMessage = pchomp(PQerrorMessage(connection->pgConn));
ereport(WARNING, (errmsg("could not send remote query \"%s\"", query),
errdetail("Client error: %s", errorMessage)));
/*
* query might include the user query coming from the taskTracker
* code path, that's why we hash it, too. Otherwise, this code
* path is generally exercised for the kind of errors that
* we cannot send the queries that Citus itself produced.
*/
ereport(WARNING, (errmsg("could not send remote query \"%s\"",
ApplyLogRedaction(query)),
errdetail("Client error: %s",
ApplyLogRedaction(errorMessage))));
success = false;
}

View File

@ -425,6 +425,7 @@ ManageTaskExecution(Task *task, TaskExecution *taskExecution,
case EXEC_TASK_FAILED:
{
bool raiseError = false;
bool isCritical = false;
/*
* On task failure, we close the connection. We also reset our execution
@ -434,7 +435,35 @@ ManageTaskExecution(Task *task, TaskExecution *taskExecution,
*/
int32 connectionId = connectionIdArray[currentIndex];
MultiConnection *connection = MultiClientGetConnection(connectionId);
bool isCritical = connection->remoteTransaction.transactionCritical;
/* next time we try this worker node, start from the beginning */
taskStatusArray[currentIndex] = EXEC_TASK_CONNECT_START;
/* try next worker node */
AdjustStateForFailure(taskExecution);
/*
* Add a delay in MultiClientWait, to avoid potentially excerbating problems
* by looping quickly
*/
*executionStatus = TASK_STATUS_ERROR;
if (connection == NULL)
{
/*
* The task failed before we even managed to connect. This happens when
* the metadata is out of sync due to a rebalance. It may be that only
* one placement was moved, in that case the other one might still work.
*/
break;
}
isCritical = connection->remoteTransaction.transactionCritical;
if (isCritical)
{
/* cannot recover when error occurs in a critical transaction */
taskExecution->criticalErrorOccurred = true;
}
/*
* Mark the connection as failed in case it was already used to perform
@ -447,27 +476,9 @@ ManageTaskExecution(Task *task, TaskExecution *taskExecution,
MultiClientDisconnect(connectionId);
connectionIdArray[currentIndex] = INVALID_CONNECTION_ID;
connectAction = CONNECT_ACTION_CLOSED;
taskStatusArray[currentIndex] = EXEC_TASK_CONNECT_START;
if (isCritical)
{
/* cannot recover when error occurs in a critical transaction */
taskExecution->criticalErrorOccurred = true;
}
else
{
/* try next worker node */
AdjustStateForFailure(taskExecution);
}
/*
* Add a delay, to avoid potentially excerbating problems by
* looping quickly
*/
*executionStatus = TASK_STATUS_ERROR;
break;
}

View File

@ -96,6 +96,8 @@ static int64 ExecuteModifyTasks(List *taskList, bool expectResults,
static void AcquireExecutorShardLock(Task *task, CmdType commandType);
static void AcquireExecutorMultiShardLocks(List *taskList);
static bool RequiresConsistentSnapshot(Task *task);
static void RouterMultiModifyExecScan(CustomScanState *node);
static void RouterSequentialModifyExecScan(CustomScanState *node);
static void ExtractParametersFromParamListInfo(ParamListInfo paramListInfo,
Oid **parameterTypes,
const char ***parameterValues);
@ -534,18 +536,62 @@ CitusModifyBeginScan(CustomScanState *node, EState *estate, int eflags)
/*
* RouterSequentialModifyExecScan executes 0 or more modifications on a
* distributed table sequentially and returns results if there are any.
* Note that we also use this path for SELECT ... FOR UPDATE queries.
* RouterModifyExecScan executes a list of tasks on remote nodes, retrieves
* the results and, if RETURNING is used or SELECT FOR UPDATE executed,
* returns the results with a TupleTableSlot.
*
* The function can handle both single task query executions,
* sequential or parallel multi-task query executions.
*/
TupleTableSlot *
RouterSequentialModifyExecScan(CustomScanState *node)
RouterModifyExecScan(CustomScanState *node)
{
CitusScanState *scanState = (CitusScanState *) node;
TupleTableSlot *resultSlot = NULL;
if (!scanState->finishedRemoteScan)
{
DistributedPlan *distributedPlan = scanState->distributedPlan;
Job *workerJob = distributedPlan->workerJob;
List *taskList = workerJob->taskList;
bool parallelExecution = true;
ExecuteSubPlans(distributedPlan);
if (list_length(taskList) <= 1 ||
IsMultiRowInsert(workerJob->jobQuery) ||
MultiShardConnectionType == SEQUENTIAL_CONNECTION)
{
parallelExecution = false;
}
if (parallelExecution)
{
RouterMultiModifyExecScan(node);
}
else
{
RouterSequentialModifyExecScan(node);
}
scanState->finishedRemoteScan = true;
}
resultSlot = ReturnTupleFromTuplestore(scanState);
return resultSlot;
}
/*
* RouterSequentialModifyExecScan executes 0 or more modifications on a
* distributed table sequentially and stores them in custom scan's tuple
* store. Note that we also use this path for SELECT ... FOR UPDATE queries.
*/
static void
RouterSequentialModifyExecScan(CustomScanState *node)
{
CitusScanState *scanState = (CitusScanState *) node;
DistributedPlan *distributedPlan = scanState->distributedPlan;
bool hasReturning = distributedPlan->hasReturning;
Job *workerJob = distributedPlan->workerJob;
@ -557,6 +603,8 @@ RouterSequentialModifyExecScan(CustomScanState *node)
bool alwaysThrowErrorOnFailure = false;
CmdType operation = scanState->distributedPlan->operation;
Assert(!scanState->finishedRemoteScan);
/*
* We could naturally handle function-based transactions (i.e. those using
* PL/pgSQL or similar) by checking the type of queryDesc->dest, but some
@ -591,27 +639,16 @@ RouterSequentialModifyExecScan(CustomScanState *node)
}
}
ExecuteSubPlans(distributedPlan);
foreach(taskCell, taskList)
{
Task *task = (Task *) lfirst(taskCell);
bool expectResults = (hasReturning || task->relationRowLockList != NIL);
/*
* Result is expected for SELECT ... FOR UPDATE queries as well.
*/
executorState->es_processed +=
ExecuteSingleModifyTask(scanState, task, operation,
alwaysThrowErrorOnFailure,
hasReturning || task->relationRowLockList != NIL);
alwaysThrowErrorOnFailure, expectResults);
}
scanState->finishedRemoteScan = true;
}
resultSlot = ReturnTupleFromTuplestore(scanState);
return resultSlot;
}
@ -667,31 +704,20 @@ TaskListRequires2PC(List *taskList)
/*
* RouterMultiModifyExecScan executes a list of tasks on remote nodes, retrieves
* the results and, if RETURNING is used, stores them in custom scan's tuple store.
* Then, it returns tuples one by one from this tuple store.
*/
TupleTableSlot *
static void
RouterMultiModifyExecScan(CustomScanState *node)
{
CitusScanState *scanState = (CitusScanState *) node;
TupleTableSlot *resultSlot = NULL;
if (!scanState->finishedRemoteScan)
{
DistributedPlan *distributedPlan = scanState->distributedPlan;
Job *workerJob = distributedPlan->workerJob;
List *taskList = workerJob->taskList;
bool hasReturning = distributedPlan->hasReturning;
bool isModificationQuery = true;
ExecuteSubPlans(distributedPlan);
Assert(!scanState->finishedRemoteScan);
ExecuteMultipleTasks(scanState, taskList, isModificationQuery, hasReturning);
scanState->finishedRemoteScan = true;
}
resultSlot = ReturnTupleFromTuplestore(scanState);
return resultSlot;
}

View File

@ -67,7 +67,7 @@ JobExecutorType(DistributedPlan *distributedPlan)
ereport(DEBUG2, (errmsg("Plan is router executable"),
errdetail("distribution column value: %s",
partitionColumnString)));
ApplyLogRedaction(partitionColumnString))));
}
else
{

View File

@ -173,6 +173,8 @@ static void ProcessDropTableStmt(DropStmt *dropTableStatement);
static void ProcessDropSchemaStmt(DropStmt *dropSchemaStatement);
static void InvalidateForeignKeyGraphForDDL(void);
static void ErrorUnsupportedAlterTableAddColumn(Oid relationId, AlterTableCmd *command,
Constraint *constraint);
/*
* We need to run some of the commands sequentially if there is a foreign constraint
@ -613,11 +615,47 @@ multi_ProcessUtility(PlannedStmt *pstmt,
}
constraint = (Constraint *) command->def;
if (ConstraintIsAForeignKey(constraint->conname, relationId))
if (constraint->contype == CONSTR_FOREIGN)
{
InvalidateForeignKeyGraph();
}
}
else if (alterTableType == AT_AddColumn)
{
List *columnConstraints = NIL;
ListCell *columnConstraint = NULL;
Oid relationId = InvalidOid;
LOCKMODE lockmode = NoLock;
ColumnDef *columnDefinition = (ColumnDef *) command->def;
columnConstraints = columnDefinition->constraints;
if (columnConstraints)
{
ErrorIfUnsupportedAlterAddConstraintStmt(alterTableStatement);
}
lockmode = AlterTableGetLockLevel(alterTableStatement->cmds);
relationId = AlterTableLookupRelation(alterTableStatement, lockmode);
if (!OidIsValid(relationId))
{
continue;
}
foreach(columnConstraint, columnConstraints)
{
Constraint *constraint = (Constraint *) lfirst(columnConstraint);
if (constraint->conname == NULL &&
(constraint->contype == CONSTR_PRIMARY ||
constraint->contype == CONSTR_UNIQUE ||
constraint->contype == CONSTR_FOREIGN ||
constraint->contype == CONSTR_CHECK))
{
ErrorUnsupportedAlterTableAddColumn(relationId, command,
constraint);
}
}
}
}
}
@ -676,6 +714,89 @@ multi_ProcessUtility(PlannedStmt *pstmt,
}
static void
ErrorUnsupportedAlterTableAddColumn(Oid relationId, AlterTableCmd *command,
Constraint *constraint)
{
ColumnDef *columnDefinition = (ColumnDef *) command->def;
char *colName = columnDefinition->colname;
char *errMsg =
"cannot execute ADD COLUMN command with PRIMARY KEY, UNIQUE, FOREIGN and CHECK constraints";
StringInfo errHint = makeStringInfo();
appendStringInfo(errHint, "You can issue each command separately such as ");
appendStringInfo(errHint,
"ALTER TABLE %s ADD COLUMN %s data_type; ALTER TABLE %s ADD CONSTRAINT constraint_name ",
get_rel_name(relationId),
colName, get_rel_name(relationId));
if (constraint->contype == CONSTR_UNIQUE)
{
appendStringInfo(errHint, "UNIQUE (%s)", colName);
}
else if (constraint->contype == CONSTR_PRIMARY)
{
appendStringInfo(errHint, "PRIMARY KEY (%s)", colName);
}
else if (constraint->contype == CONSTR_CHECK)
{
appendStringInfo(errHint, "CHECK (check_expression)");
}
else if (constraint->contype == CONSTR_FOREIGN)
{
RangeVar *referencedTable = constraint->pktable;
char *referencedColumn = strVal(lfirst(list_head(constraint->pk_attrs)));
Oid referencedRelationId = RangeVarGetRelid(referencedTable, NoLock, false);
appendStringInfo(errHint, "FOREIGN KEY (%s) REFERENCES %s(%s)", colName,
get_rel_name(referencedRelationId), referencedColumn);
if (constraint->fk_del_action == FKCONSTR_ACTION_SETNULL)
{
appendStringInfo(errHint, " %s", "ON DELETE SET NULL");
}
else if (constraint->fk_del_action == FKCONSTR_ACTION_CASCADE)
{
appendStringInfo(errHint, " %s", "ON DELETE CASCADE");
}
else if (constraint->fk_del_action == FKCONSTR_ACTION_SETDEFAULT)
{
appendStringInfo(errHint, " %s", "ON DELETE SET DEFAULT");
}
else if (constraint->fk_del_action == FKCONSTR_ACTION_RESTRICT)
{
appendStringInfo(errHint, " %s", "ON DELETE RESTRICT");
}
if (constraint->fk_upd_action == FKCONSTR_ACTION_SETNULL)
{
appendStringInfo(errHint, " %s", "ON UPDATE SET NULL");
}
else if (constraint->fk_upd_action == FKCONSTR_ACTION_CASCADE)
{
appendStringInfo(errHint, " %s", "ON UPDATE CASCADE");
}
else if (constraint->fk_upd_action == FKCONSTR_ACTION_SETDEFAULT)
{
appendStringInfo(errHint, " %s", "ON UPDATE SET DEFAULT");
}
else if (constraint->fk_upd_action == FKCONSTR_ACTION_RESTRICT)
{
appendStringInfo(errHint, " %s", "ON UPDATE RESTRICT");
}
}
appendStringInfo(errHint, "%s", ";");
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("%s", errMsg),
errhint("%s", errHint->data),
errdetail("Adding a column with a constraint in "
"one command is not supported because "
"all constraints in Citus must have "
"explicit names")));
}
/*
* InvalidateForeignKeyGraphForDDL simply keeps track of whether
* the foreign key graph should be invalidated due to a DDL.
@ -1414,6 +1535,39 @@ PlanAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCo
constraint->skip_validation = true;
}
}
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;
List *columnConstraints = columnDefinition->constraints;
ListCell *columnConstraint = NULL;
foreach(columnConstraint, columnConstraints)
{
Constraint *constraint = (Constraint *) lfirst(columnConstraint);
if (constraint->contype == CONSTR_FOREIGN)
{
rightRelationId = RangeVarGetRelid(constraint->pktable, lockmode,
alterTableStatement->missing_ok);
/*
* Foreign constraint validations will be done in workers. If we do not
* set this flag, PostgreSQL tries to do additional checking when we drop
* to standard_ProcessUtility. standard_ProcessUtility tries to open new
* connections to workers to verify foreign constraints while original
* transaction is in process, which causes deadlock.
*/
constraint->skip_validation = true;
break;
}
}
}
#if (PG_VERSION_NUM >= 100000)
else if (alterTableType == AT_AttachPartition)
{
@ -4037,6 +4191,34 @@ SetupExecutionModeForAlterTable(Oid relationId, AlterTableCmd *command)
executeSequentially = true;
}
}
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;
List *columnConstraints = columnDefinition->constraints;
ListCell *columnConstraint = NULL;
foreach(columnConstraint, columnConstraints)
{
Constraint *constraint = (Constraint *) lfirst(columnConstraint);
if (constraint->contype == CONSTR_FOREIGN)
{
Oid rightRelationId = RangeVarGetRelid(constraint->pktable, NoLock,
false);
if (IsDistributedTable(rightRelationId) &&
PartitionMethod(rightRelationId) == DISTRIBUTE_BY_NONE)
{
executeSequentially = true;
}
}
}
}
else if (alterTableType == AT_DropColumn || alterTableType == AT_AlterColumnType)
{
char *affectedColumnName = command->name;

View File

@ -122,7 +122,7 @@ master_apply_delete_command(PG_FUNCTION_ARGS)
if (!IsA(queryTreeNode, DeleteStmt))
{
ereport(ERROR, (errmsg("query \"%s\" is not a delete statement",
queryString)));
ApplyLogRedaction(queryString))));
}
deleteStatement = (DeleteStmt *) queryTreeNode;

View File

@ -145,7 +145,7 @@ master_modify_multiple_shards(PG_FUNCTION_ARGS)
else
{
ereport(ERROR, (errmsg("query \"%s\" is not a delete, update, or truncate "
"statement", queryString)));
"statement", ApplyLogRedaction(queryString))));
}
CheckDistributedTable(relationId);

View File

@ -109,11 +109,13 @@ RebuildQueryStrings(Query *originalQuery, List *taskList)
}
}
ereport(DEBUG4, (errmsg("query before rebuilding: %s", task->queryString)));
ereport(DEBUG4, (errmsg("query before rebuilding: %s",
ApplyLogRedaction(task->queryString))));
UpdateTaskQueryString(query, relationId, valuesRTE, task);
ereport(DEBUG4, (errmsg("query after rebuilding: %s", task->queryString)));
ereport(DEBUG4, (errmsg("query after rebuilding: %s",
ApplyLogRedaction(task->queryString))));
}
}

View File

@ -176,6 +176,14 @@ CreateInsertSelectPlan(Query *originalQuery,
PlannerRestrictionContext *plannerRestrictionContext)
{
DistributedPlan *distributedPlan = NULL;
DeferredErrorMessage *deferredError = NULL;
deferredError = ErrorIfOnConflictNotSupported(originalQuery);
if (deferredError != NULL)
{
/* raising the error as there is no possible solution for the unsupported on conflict statements */
RaiseDeferredError(deferredError, ERROR);
}
distributedPlan = CreateDistributedInsertSelectPlan(originalQuery,
plannerRestrictionContext);
@ -568,7 +576,8 @@ RouterModifyTaskForShardInterval(Query *originalQuery, ShardInterval *shardInter
/* and generate the full query string */
deparse_shard_query(copiedQuery, distributedTableId, shardInterval->shardId,
queryString);
ereport(DEBUG2, (errmsg("distributed statement: %s", queryString->data)));
ereport(DEBUG2, (errmsg("distributed statement: %s",
ApplyLogRedaction(queryString->data))));
modifyTask = CreateBasicTask(jobId, taskIdIndex, MODIFY_TASK, queryString->data);
modifyTask->dependedTaskList = NULL;

View File

@ -714,7 +714,8 @@ PrintJoinOrderList(List *joinOrder)
}
}
ereport(LOG, (errmsg("join order: %s", printBuffer->data)));
ereport(LOG, (errmsg("join order: %s",
ApplyLogRedaction(printBuffer->data))));
}

View File

@ -2080,12 +2080,6 @@ ExtractRangeTableRelationWalker(Node *node, List **rangeTableRelationList)
walkIsComplete = false;
}
else
{
walkIsComplete = range_table_walker(list_make1(rangeTable),
ExtractRangeTableRelationWalker,
rangeTableRelationList, 0);
}
}
else if (IsA(node, Query))
{

View File

@ -2418,7 +2418,8 @@ QueryPushdownTaskCreate(Query *originalQuery, int shardIndex,
taskType == SQL_TASK)
{
pg_get_query_def(taskQuery, queryString);
ereport(DEBUG4, (errmsg("distributed statement: %s", queryString->data)));
ereport(DEBUG4, (errmsg("distributed statement: %s",
ApplyLogRedaction(queryString->data))));
subqueryTask->queryString = queryString->data;
}
@ -2698,7 +2699,8 @@ SqlTaskList(Job *job)
/* log the query string we generated */
ereport(DEBUG4, (errmsg("generated sql query for task %d", sqlTask->taskId),
errdetail("query string: \"%s\"", sqlQueryString->data)));
errdetail("query string: \"%s\"",
ApplyLogRedaction(sqlQueryString->data))));
sqlTask->anchorShardId = INVALID_SHARD_ID;
if (anchorRangeTableBasedAssignment)

View File

@ -530,12 +530,8 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
List *rangeTableList = NIL;
ListCell *rangeTableCell = NULL;
uint32 queryTableCount = 0;
bool specifiesPartitionValue = false;
ListCell *setTargetCell = NULL;
List *onConflictSet = NIL;
Node *arbiterWhere = NULL;
Node *onConflictWhere = NULL;
CmdType commandType = queryTree->commandType;
DeferredErrorMessage *deferredError = NULL;
/*
* Here, we check if a recursively planned query tries to modify
@ -769,7 +765,10 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
TargetEntryChangesValue(targetEntry, partitionColumn,
queryTree->jointree))
{
specifiesPartitionValue = true;
return DeferredError(ERRCODE_FEATURE_NOT_SUPPORTED,
"modifying the partition value of rows is not "
"allowed",
NULL, NULL);
}
if (commandType == CMD_UPDATE &&
@ -829,12 +828,45 @@ ModifyQuerySupported(Query *queryTree, Query *originalQuery, bool multiShardQuer
}
}
if (commandType == CMD_INSERT && queryTree->onConflict != NULL)
deferredError = ErrorIfOnConflictNotSupported(queryTree);
if (deferredError != NULL)
{
return deferredError;
}
return NULL;
}
/*
* ErrorIfOnConflictNotSupprted returns an error if an INSERT query has an
* unsupported ON CONFLICT clause. In particular, changing the partition
* column value or using volatile functions is not allowed.
*/
DeferredErrorMessage *
ErrorIfOnConflictNotSupported(Query *queryTree)
{
Oid distributedTableId = InvalidOid;
uint32 rangeTableId = 1;
Var *partitionColumn = NULL;
List *onConflictSet = NIL;
Node *arbiterWhere = NULL;
Node *onConflictWhere = NULL;
ListCell *setTargetCell = NULL;
bool specifiesPartitionValue = false;
CmdType commandType = queryTree->commandType;
if (commandType != CMD_INSERT || queryTree->onConflict == NULL)
{
return NULL;
}
distributedTableId = ExtractFirstDistributedTableId(queryTree);
partitionColumn = PartitionColumn(distributedTableId, rangeTableId);
onConflictSet = queryTree->onConflict->onConflictSet;
arbiterWhere = queryTree->onConflict->arbiterWhere;
onConflictWhere = queryTree->onConflict->onConflictWhere;
}
/*
* onConflictSet is expanded via expand_targetlist() on the standard planner.
@ -2513,6 +2545,12 @@ IntersectPlacementList(List *lhsPlacementList, List *rhsPlacementList)
WORKER_LENGTH) == 0)
{
placementList = lappend(placementList, rhsPlacement);
/*
* We don't need to add the same placement over and over again. This
* could happen if both placements of a shard appear on the same node.
*/
break;
}
}
}

View File

@ -218,7 +218,7 @@ GenerateSubplansForSubqueriesAndCTEs(uint64 planId, Query *originalQuery,
ereport(DEBUG1, (errmsg(
"Plan " UINT64_FORMAT
" query after replacing subqueries and CTEs: %s", planId,
subPlanString->data)));
ApplyLogRedaction(subPlanString->data))));
}
return context.subPlanList;
@ -715,9 +715,10 @@ RecursivelyPlanCTEs(Query *query, RecursivePlanningContext *planningContext)
{
StringInfo subPlanString = makeStringInfo();
pg_get_query_def(subquery, subPlanString);
ereport(DEBUG1, (errmsg("generating subplan " UINT64_FORMAT "_%u for "
"CTE %s: %s",
planId, subPlanId, cteName, subPlanString->data)));
ereport(DEBUG1, (errmsg("generating subplan " UINT64_FORMAT
"_%u for CTE %s: %s", planId, subPlanId,
cteName,
ApplyLogRedaction(subPlanString->data))));
}
/* build a sub plan for the CTE */
@ -1120,9 +1121,9 @@ RecursivelyPlanSubquery(Query *subquery, RecursivePlanningContext *planningConte
pg_get_query_def(debugQuery, subqueryString);
ereport(DEBUG1, (errmsg("generating subplan " UINT64_FORMAT "_%u for "
"subquery %s",
planId, subPlanId, subqueryString->data)));
ereport(DEBUG1, (errmsg("generating subplan " UINT64_FORMAT
"_%u for subquery %s", planId, subPlanId,
ApplyLogRedaction(subqueryString->data))));
}
/* finally update the input subquery to point the result query */

View File

@ -1825,8 +1825,21 @@ RangeTableArrayContainsAnyRTEIdentities(RangeTblEntry **rangeTableEntries, int
* (i.e.,rangeTableEntry could be a subquery where we're interested
* in relations).
*/
if (rangeTableEntry->rtekind == RTE_SUBQUERY)
{
ExtractRangeTableRelationWalker((Node *) rangeTableEntry->subquery,
&rangeTableRelationList);
}
else if (rangeTableEntry->rtekind == RTE_RELATION)
{
ExtractRangeTableRelationWalker((Node *) rangeTableEntry,
&rangeTableRelationList);
}
else
{
/* we currently do not accept any other RTE types here */
continue;
}
foreach(rteRelationCell, rangeTableRelationList)
{

View File

@ -520,6 +520,29 @@ RelayEventExtendNamesForInterShardCommands(Node *parseTree, uint64 leftShardId,
relationSchemaName = &(constraint->pktable->schemaname);
}
}
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;
List *columnConstraints = columnDefinition->constraints;
ListCell *columnConstraint = NULL;
foreach(columnConstraint, columnConstraints)
{
Constraint *constraint = (Constraint *) lfirst(columnConstraint);
if (constraint->contype == CONSTR_FOREIGN)
{
referencedTableName = &(constraint->pktable->relname);
relationSchemaName = &(constraint->pktable->schemaname);
}
}
}
#if (PG_VERSION_NUM >= 100000)
else if (command->subtype == AT_AttachPartition ||
command->subtype == AT_DetachPartition)

View File

@ -76,7 +76,7 @@ deparse_shard_query_test(PG_FUNCTION_ARGS)
deparse_shard_query(query, InvalidOid, 0, buffer);
elog(INFO, "query: %s", buffer->data);
elog(INFO, "query: %s", ApplyLogRedaction(buffer->data));
}
}

View File

@ -32,6 +32,7 @@
#include "nodes/pg_list.h"
#include "nodes/primnodes.h"
#include "storage/lock.h"
#include "tcop/tcopprot.h"
#include "utils/array.h"
#include "utils/elog.h"
#include "utils/errcodes.h"
@ -48,6 +49,7 @@ PG_FUNCTION_INFO_V1(partition_type);
PG_FUNCTION_INFO_V1(is_distributed_table);
PG_FUNCTION_INFO_V1(create_monolithic_shard_row);
PG_FUNCTION_INFO_V1(acquire_shared_shard_lock);
PG_FUNCTION_INFO_V1(relation_count_in_query);
/*
@ -249,3 +251,43 @@ acquire_shared_shard_lock(PG_FUNCTION_ARGS)
PG_RETURN_VOID();
}
/*
* relation_count_in_query return the first query's relation count.
*/
Datum
relation_count_in_query(PG_FUNCTION_ARGS)
{
text *queryString = PG_GETARG_TEXT_P(0);
char *queryStringChar = text_to_cstring(queryString);
List *parseTreeList = pg_parse_query(queryStringChar);
ListCell *parseTreeCell = NULL;
foreach(parseTreeCell, parseTreeList)
{
Node *parsetree = (Node *) lfirst(parseTreeCell);
ListCell *queryTreeCell = NULL;
List *queryTreeList = NIL;
#if (PG_VERSION_NUM >= 100000)
queryTreeList = pg_analyze_and_rewrite((RawStmt *) parsetree, queryStringChar,
NULL, 0, NULL);
#else
queryTreeList = pg_analyze_and_rewrite(parsetree, queryStringChar, NULL, 0);
#endif
foreach(queryTreeCell, queryTreeList)
{
Query *query = lfirst(queryTreeCell);
List *rangeTableList = NIL;
ExtractRangeTableRelationWalker((Node *) query, &rangeTableList);
PG_RETURN_INT32(list_length(rangeTableList));
}
}
PG_RETURN_INT32(0);
}

View File

@ -17,6 +17,7 @@
#include "access/hash.h"
#include "distributed/backend_data.h"
#include "distributed/distributed_deadlock_detection.h"
#include "distributed/errormessage.h"
#include "distributed/hash_helpers.h"
#include "distributed/listutils.h"
#include "distributed/lock_graph.h"
@ -673,7 +674,7 @@ LogDistributedDeadlockDebugMessage(const char *errorMessage)
}
ereport(LOG, (errmsg("[%s] %s", timestamptz_to_str(GetCurrentTimestamp()),
errorMessage)));
ApplyLogRedaction(errorMessage))));
}

View File

@ -12,6 +12,16 @@
#include "distributed/errormessage.h"
/*
* ApplyLogRedaction is only supported in Citus Enterprise
*/
char *
ApplyLogRedaction(const char *text)
{
return (char *) text;
}
/*
* DeferredErrorInternal is a helper function for DeferredError().
*/

View File

@ -695,7 +695,8 @@ ParseTreeRawStmt(const char *ddlCommand)
/* log immediately if dictated by log statement */
if (check_log_statement(parseTreeList))
{
ereport(LOG, (errmsg("statement: %s", ddlCommand), errhidestmt(true)));
ereport(LOG, (errmsg("statement: %s", ApplyLogRedaction(ddlCommand)),
errhidestmt(true)));
}
parseTreeCount = list_length(parseTreeList);

View File

@ -923,7 +923,7 @@ FilterAndPartitionTable(const char *filterQuery,
if (queryPortal == NULL)
{
ereport(ERROR, (errmsg("could not open implicit cursor for query \"%s\"",
filterQuery)));
ApplyLogRedaction(filterQuery))));
}
rowOutputState = InitRowOutputState();

View File

@ -70,3 +70,5 @@ DeferredErrorMessage * DeferredErrorInternal(int code, const char *message, cons
void RaiseDeferredErrorInternal(DeferredErrorMessage *error, int elevel);
#endif
extern char * ApplyLogRedaction(const char *text);

View File

@ -37,9 +37,8 @@ extern bool AllModificationsCommutative;
extern bool EnableDeadlockPrevention;
extern void CitusModifyBeginScan(CustomScanState *node, EState *estate, int eflags);
extern TupleTableSlot * RouterSequentialModifyExecScan(CustomScanState *node);
extern TupleTableSlot * RouterSelectExecScan(CustomScanState *node);
extern TupleTableSlot * RouterMultiModifyExecScan(CustomScanState *node);
extern TupleTableSlot * RouterModifyExecScan(CustomScanState *node);
extern int64 ExecuteModifyTasksWithoutResults(List *taskList);
extern int64 ExecuteModifyTasksSequentiallyWithoutResults(List *taskList,

View File

@ -52,6 +52,7 @@ extern DeferredErrorMessage * ModifyQuerySupported(Query *queryTree, Query *orig
bool multiShardQuery,
PlannerRestrictionContext *
plannerRestrictionContext);
extern DeferredErrorMessage * ErrorIfOnConflictNotSupported(Query *queryTree);
extern List * ShardIntervalOpExpressions(ShardInterval *shardInterval, Index rteIndex);
extern RelationRestrictionContext * CopyRelationRestrictionContext(
RelationRestrictionContext *oldContext);

View File

@ -1136,10 +1136,155 @@ DEBUG: verifying table "test_table_2"
SET LOCAL client_min_messages TO ERROR;
DROP TABLE test_table_2, test_table_1;
COMMIT;
-- make sure that modifications to reference tables in a CTE can
-- set the mode to sequential for the next operations
CREATE TABLE reference_table(id int PRIMARY KEY);
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "reference_table_pkey" for table "reference_table"
DEBUG: building index "reference_table_pkey" on table "reference_table"
SELECT create_reference_table('reference_table');
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57638
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57637
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57637
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57638
create_reference_table
------------------------
(1 row)
CREATE TABLE distributed_table(id int PRIMARY KEY, value_1 int);
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "distributed_table_pkey" for table "distributed_table"
DEBUG: building index "distributed_table_pkey" on table "distributed_table"
SELECT create_distributed_table('distributed_table', 'id');
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57638
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57637
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57637
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57638
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57637
DEBUG: schema "test_fkey_to_ref_in_tx" already exists, skipping
DETAIL: NOTICE from localhost:57638
create_distributed_table
--------------------------
(1 row)
ALTER TABLE
distributed_table
ADD CONSTRAINT
fkey_delete FOREIGN KEY(value_1)
REFERENCES
reference_table(id) ON DELETE CASCADE;
DEBUG: switching to sequential query execution mode
DETAIL: Reference relation "reference_table" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed relations due to foreign keys. Any parallel modification to those hash distributed relations in the same transaction can only be executed in sequential query execution mode
INSERT INTO reference_table SELECT i FROM generate_series(0, 10) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
DEBUG: switching to sequential query execution mode
DETAIL: Reference relation "reference_table" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed relations due to foreign keys. Any parallel modification to those hash distributed relations in the same transaction can only be executed in sequential query execution mode
INSERT INTO distributed_table SELECT i, i % 10 FROM generate_series(0, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
-- this query returns 100 rows in Postgres, but not in Citus
-- see https://github.com/citusdata/citus_docs/issues/664 for the discussion
WITH t1 AS (DELETE FROM reference_table RETURNING id)
DELETE FROM distributed_table USING t1 WHERE value_1 = t1.id RETURNING *;
DEBUG: common table expressions are not supported in distributed modifications
DEBUG: generating subplan 92_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
DEBUG: Plan 92 query after replacing subqueries and CTEs: DELETE FROM test_fkey_to_ref_in_tx.distributed_table USING (SELECT intermediate_result.id FROM read_intermediate_result('92_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t1 WHERE (distributed_table.value_1 OPERATOR(pg_catalog.=) t1.id) RETURNING distributed_table.id, distributed_table.value_1, t1.id
DEBUG: switching to sequential query execution mode
DETAIL: Reference relation "reference_table" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed relations due to foreign keys. Any parallel modification to those hash distributed relations in the same transaction can only be executed in sequential query execution mode
id | value_1 | id
----+---------+----
(0 rows)
-- load some more data for one more test with real-time selects
INSERT INTO reference_table SELECT i FROM generate_series(0, 10) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
DEBUG: switching to sequential query execution mode
DETAIL: Reference relation "reference_table" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed relations due to foreign keys. Any parallel modification to those hash distributed relations in the same transaction can only be executed in sequential query execution mode
INSERT INTO distributed_table SELECT i, i % 10 FROM generate_series(0, 100) i;
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: Collecting INSERT ... SELECT results on coordinator
-- this query returns 100 rows in Postgres, but not in Citus
-- see https://github.com/citusdata/citus_docs/issues/664 for the discussion
WITH t1 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1 WHERE value_1 = t1.id;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries
DEBUG: generating subplan 96_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
DEBUG: Plan 96 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM test_fkey_to_ref_in_tx.distributed_table, (SELECT intermediate_result.id FROM read_intermediate_result('96_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t1 WHERE (distributed_table.value_1 OPERATOR(pg_catalog.=) t1.id)
DEBUG: switching to sequential query execution mode
DETAIL: Reference relation "reference_table" is modified, which might lead to data inconsistencies or distributed deadlocks via parallel accesses to hash distributed relations due to foreign keys. Any parallel modification to those hash distributed relations in the same transaction can only be executed in sequential query execution mode
count
-------
0
(1 row)
-- this query should fail since we first to a parallel access to a distributed table
-- with t1, and then access to t2
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
t2 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1, t2 WHERE value_1 = t1.id AND value_1 = t2.id;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries
DEBUG: generating subplan 98_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.distributed_table RETURNING id
DEBUG: generating subplan 98_2 for CTE t2: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
DEBUG: Plan 98 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM test_fkey_to_ref_in_tx.distributed_table, (SELECT intermediate_result.id FROM read_intermediate_result('98_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t1, (SELECT intermediate_result.id FROM read_intermediate_result('98_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t2 WHERE ((distributed_table.value_1 OPERATOR(pg_catalog.=) t1.id) AND (distributed_table.value_1 OPERATOR(pg_catalog.=) t2.id))
ERROR: cannot execute DML on reference relation "reference_table" because there was a parallel DML access to distributed relation "distributed_table" in the same transaction
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
-- similarly this should fail since we first access to a distributed
-- table via t1, and then access to the reference table in the main query
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
DELETE FROM reference_table RETURNING id;
DEBUG: common table expressions are not supported in distributed modifications
DEBUG: generating subplan 101_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.distributed_table RETURNING id
DEBUG: Plan 101 query after replacing subqueries and CTEs: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
ERROR: cannot execute DML on reference relation "reference_table" because there was a parallel DML access to distributed relation "distributed_table" in the same transaction
HINT: Try re-running the transaction with "SET LOCAL citus.multi_shard_modify_mode TO 'sequential';"
-- finally, make sure that we can execute the same queries
-- in the sequential mode
BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
t2 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1, t2 WHERE value_1 = t1.id AND value_1 = t2.id;
DEBUG: data-modifying statements are not supported in the WITH clauses of distributed queries
DEBUG: generating subplan 103_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.distributed_table RETURNING id
DEBUG: generating subplan 103_2 for CTE t2: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
DEBUG: Plan 103 query after replacing subqueries and CTEs: SELECT count(*) AS count FROM test_fkey_to_ref_in_tx.distributed_table, (SELECT intermediate_result.id FROM read_intermediate_result('103_1'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t1, (SELECT intermediate_result.id FROM read_intermediate_result('103_2'::text, 'binary'::citus_copy_format) intermediate_result(id integer)) t2 WHERE ((distributed_table.value_1 OPERATOR(pg_catalog.=) t1.id) AND (distributed_table.value_1 OPERATOR(pg_catalog.=) t2.id))
count
-------
0
(1 row)
ROLLBACK;
BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
DELETE FROM reference_table RETURNING id;
DEBUG: common table expressions are not supported in distributed modifications
DEBUG: generating subplan 106_1 for CTE t1: DELETE FROM test_fkey_to_ref_in_tx.distributed_table RETURNING id
DEBUG: Plan 106 query after replacing subqueries and CTEs: DELETE FROM test_fkey_to_ref_in_tx.reference_table RETURNING id
id
----
(0 rows)
ROLLBACK;
RESET client_min_messages;
DROP SCHEMA test_fkey_to_ref_in_tx CASCADE;
NOTICE: drop cascades to 3 other objects
NOTICE: drop cascades to 5 other objects
DETAIL: drop cascades to table referece_table
drop cascades to table on_update_fkey_table
drop cascades to table unrelated_dist_table
drop cascades to table reference_table
drop cascades to table distributed_table
SET search_path TO public;

File diff suppressed because it is too large Load Diff

View File

@ -293,6 +293,24 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A
fkey_ref_7000098 | fkey_reference_table.referencing_table_7000098 | fkey_reference_table.referenced_table_7000042
(8 rows)
DROP TABLE referencing_table;
-- check if we can add the foreign key while adding the column
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
create_distributed_table
--------------------------
(1 row)
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 * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
-- foreign keys are only supported when the replication factor = 1
SET citus.shard_replication_factor TO 2;
@ -312,6 +330,24 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
-- should fail when we add the column as well
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
create_distributed_table
--------------------------
(1 row)
ALTER TABLE referencing_table ADD COLUMN referencing_col int REFERENCES referenced_table(id) ON DELETE SET NULL;
ERROR: cannot create foreign key constraint
DETAIL: Citus Community Edition currently supports foreign key constraints only for "citus.shard_replication_factor = 1".
HINT: Please change "citus.shard_replication_factor to 1". To learn more about using foreign keys with other replication factors, please contact us at https://citusdata.com/about/contact_us.
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
SET citus.shard_replication_factor TO 1;
-- simple create_distributed_table should work in/out transactions on tables with foreign key to reference tables
@ -325,14 +361,14 @@ SELECT create_distributed_table('referencing_table', 'ref_id');
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------+------------------------------------------------+-----------------------------------------------
referencing_table_id_fkey_7000107 | fkey_reference_table.referencing_table_7000107 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000108 | fkey_reference_table.referencing_table_7000108 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000109 | fkey_reference_table.referencing_table_7000109 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000110 | fkey_reference_table.referencing_table_7000110 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000111 | fkey_reference_table.referencing_table_7000111 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000112 | fkey_reference_table.referencing_table_7000112 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000113 | fkey_reference_table.referencing_table_7000113 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000114 | fkey_reference_table.referencing_table_7000114 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000123 | fkey_reference_table.referencing_table_7000123 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000124 | fkey_reference_table.referencing_table_7000124 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000125 | fkey_reference_table.referencing_table_7000125 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000126 | fkey_reference_table.referencing_table_7000126 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000127 | fkey_reference_table.referencing_table_7000127 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000128 | fkey_reference_table.referencing_table_7000128 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000129 | fkey_reference_table.referencing_table_7000129 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000130 | fkey_reference_table.referencing_table_7000130 | fkey_reference_table.referenced_table_7000042
(8 rows)
DROP TABLE referencing_table;
@ -356,14 +392,14 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------+------------------------------------------------+-----------------------------------------------
referencing_table_id_fkey_7000116 | fkey_reference_table.referencing_table_7000116 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000117 | fkey_reference_table.referencing_table_7000117 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000118 | fkey_reference_table.referencing_table_7000118 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000119 | fkey_reference_table.referencing_table_7000119 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000120 | fkey_reference_table.referencing_table_7000120 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000121 | fkey_reference_table.referencing_table_7000121 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000122 | fkey_reference_table.referencing_table_7000122 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000123 | fkey_reference_table.referencing_table_7000123 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000132 | fkey_reference_table.referencing_table_7000132 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000133 | fkey_reference_table.referencing_table_7000133 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000134 | fkey_reference_table.referencing_table_7000134 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000135 | fkey_reference_table.referencing_table_7000135 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000136 | fkey_reference_table.referencing_table_7000136 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000137 | fkey_reference_table.referencing_table_7000137 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000138 | fkey_reference_table.referencing_table_7000138 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000139 | fkey_reference_table.referencing_table_7000139 | fkey_reference_table.referenced_table_7000131
(8 rows)
DROP TABLE referencing_table;
@ -421,8 +457,8 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFER
-- test inserts
-- test insert to referencing table while there is NO corresponding value in referenced table
INSERT INTO referencing_table VALUES(1, 1);
ERROR: insert or update on table "referencing_table_7000125" violates foreign key constraint "fkey_ref_7000125"
DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000124".
ERROR: insert or update on table "referencing_table_7000141" violates foreign key constraint "fkey_ref_7000141"
DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000140".
CONTEXT: while executing command on localhost:57637
-- test insert to referencing while there is corresponding value in referenced table
INSERT INTO referenced_table SELECT x, x from generate_series(1,1000) as f(x);
@ -430,8 +466,8 @@ INSERT INTO referencing_table SELECT x, x from generate_series(1,500) as f(x);
-- test deletes
-- test delete from referenced table while there is corresponding value in referencing table
DELETE FROM referenced_table WHERE id > 3;
ERROR: update or delete on table "referenced_table_7000124" violates foreign key constraint "fkey_ref_7000127" on table "referencing_table_7000127"
DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000127".
ERROR: update or delete on table "referenced_table_7000140" violates foreign key constraint "fkey_ref_7000143" on table "referencing_table_7000143"
DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000143".
CONTEXT: while executing command on localhost:57637
-- test delete from referenced table while there is NO corresponding value in referencing table
DELETE FROM referenced_table WHERE id = 501;
@ -626,8 +662,8 @@ INSERT INTO referenced_table SELECT x,x FROM generate_series(1,1000) AS f(x);
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
-- Fails for non existing value inserts (serial is already incremented)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
ERROR: insert or update on table "referencing_table_7000172" violates foreign key constraint "fkey_ref_7000172"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000171".
ERROR: insert or update on table "referencing_table_7000195" violates foreign key constraint "fkey_ref_7000195"
DETAIL: Key (ref_id)=(1009) is not present in table "referenced_table_7000187".
DROP TABLE referenced_table CASCADE;
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
DROP TABLE referencing_table CASCADE;
@ -657,8 +693,8 @@ INSERT INTO referenced_table(test_column2) SELECT x FROM generate_series(1,1000)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
-- Fails for non existing value inserts (serial is already incremented)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
ERROR: insert or update on table "referencing_table_7000181" violates foreign key constraint "fkey_ref_7000181"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000180".
ERROR: insert or update on table "referencing_table_7000197" violates foreign key constraint "fkey_ref_7000197"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000196".
DROP TABLE referenced_table CASCADE;
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
DROP TABLE referencing_table CASCADE;
@ -709,8 +745,8 @@ INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x);
INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x);
-- we expect this to fail because of the foreign constraint.
INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x);
ERROR: insert or update on table "referencing_table_7000204" violates foreign key constraint "fkey_ref_7000204"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000198".
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000214".
-- currently not supported
ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref;
ERROR: alter table command is currently unsupported
@ -809,38 +845,38 @@ ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (id) REFE
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------+------------------------------------------------+------------------------------------------------
fkey_ref_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000217
foreign_key_2_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table2_7000218
fkey_ref_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000233
foreign_key_2_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000234
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220"
DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242"
DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220"
DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242"
DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220"
DETAIL: Key (id)=(1005) is not present in table "referenced_table_7000217".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "fkey_ref_7000242"
DETAIL: Key (id)=(1023) is not present in table "referenced_table_7000233".
-- should success
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x);
SELECT count(*) FROM referencing_table;
@ -936,38 +972,38 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------+------------------------------------------------+------------------------------------------------
fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table_7000237
foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table2_7000238
fkey_ref_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000253
foreign_key_2_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table2_7000254
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245"
DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260"
DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245"
DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260"
DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "fkey_ref_7000245"
DETAIL: Key (id)=(1002) is not present in table "referenced_table_7000237".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "fkey_ref_7000260"
DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000253".
-- should success
INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x);
SELECT count(*) FROM referencing_table;
@ -1069,43 +1105,43 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
--------------------------+-------------------------------------------------+------------------------------------------------
fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000263 | fkey_reference_table.referencing_table_7000263 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000264 | fkey_reference_table.referencing_table_7000264 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000265 | fkey_reference_table.referencing_table_7000265 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referenced_table_7000257
fkey_ref_to_dist_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referencing_table_7000258
fkey_ref_to_dist_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referencing_table_7000259
fkey_ref_to_dist_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referencing_table_7000260
fkey_ref_to_dist_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referencing_table_7000261
fkey_ref_to_dist_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referencing_table_7000262
fkey_ref_to_dist_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referencing_table_7000263
fkey_ref_to_dist_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referencing_table_7000264
fkey_ref_to_dist_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referencing_table_7000265
fkey_ref_7000274 | fkey_reference_table.referencing_table_7000274 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000275 | fkey_reference_table.referencing_table_7000275 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000276 | fkey_reference_table.referencing_table_7000276 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000277 | fkey_reference_table.referencing_table_7000277 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000278 | fkey_reference_table.referencing_table_7000278 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000279 | fkey_reference_table.referencing_table_7000279 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000280 | fkey_reference_table.referencing_table_7000280 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000281 | fkey_reference_table.referencing_table_7000281 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referenced_table_7000273
fkey_ref_to_dist_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referencing_table_7000274
fkey_ref_to_dist_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referencing_table_7000275
fkey_ref_to_dist_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referencing_table_7000276
fkey_ref_to_dist_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referencing_table_7000277
fkey_ref_to_dist_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referencing_table_7000278
fkey_ref_to_dist_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referencing_table_7000279
fkey_ref_to_dist_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referencing_table_7000280
fkey_ref_to_dist_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referencing_table_7000281
(24 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
-- should fail
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x);
ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272"
DETAIL: Key (id)=(2) is not present in table "referencing_table_7000264".
ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284"
DETAIL: Key (id)=(4) is not present in table "referencing_table_7000276".
-- should success
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
-- should fail
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x);
ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272"
DETAIL: Key (id)=(404) is not present in table "referencing_table_7000264".
ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284"
DETAIL: Key (id)=(408) is not present in table "referencing_table_7000276".
-- should success
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x);
DELETE FROM referenced_table WHERE test_column < 200;
@ -1203,22 +1239,22 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id, ref_i
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.referencing%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------------------+------------------------------------------------------------+------------------------------------------------
fkey_ref_7000292 | fkey_reference_table.referencing_table_7000292 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000293 | fkey_reference_table.referencing_table_7000293 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000294 | fkey_reference_table.referencing_table_7000294 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000295 | fkey_reference_table.referencing_table_7000295 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000296 | fkey_reference_table.referencing_table_7000296 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000297 | fkey_reference_table.referencing_table_7000297 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000298 | fkey_reference_table.referencing_table_7000298 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000299 | fkey_reference_table.referencing_table_7000299 | fkey_reference_table.referenced_table_7000291
referencing_referencing_table_id_fkey_7000300 | fkey_reference_table.referencing_referencing_table_7000300 | fkey_reference_table.referencing_table_7000292
referencing_referencing_table_id_fkey_7000301 | fkey_reference_table.referencing_referencing_table_7000301 | fkey_reference_table.referencing_table_7000293
referencing_referencing_table_id_fkey_7000302 | fkey_reference_table.referencing_referencing_table_7000302 | fkey_reference_table.referencing_table_7000294
referencing_referencing_table_id_fkey_7000303 | fkey_reference_table.referencing_referencing_table_7000303 | fkey_reference_table.referencing_table_7000295
referencing_referencing_table_id_fkey_7000304 | fkey_reference_table.referencing_referencing_table_7000304 | fkey_reference_table.referencing_table_7000296
referencing_referencing_table_id_fkey_7000305 | fkey_reference_table.referencing_referencing_table_7000305 | fkey_reference_table.referencing_table_7000297
referencing_referencing_table_id_fkey_7000306 | fkey_reference_table.referencing_referencing_table_7000306 | fkey_reference_table.referencing_table_7000298
referencing_referencing_table_id_fkey_7000307 | fkey_reference_table.referencing_referencing_table_7000307 | fkey_reference_table.referencing_table_7000299
fkey_ref_7000308 | fkey_reference_table.referencing_table_7000308 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000309 | fkey_reference_table.referencing_table_7000309 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000310 | fkey_reference_table.referencing_table_7000310 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000311 | fkey_reference_table.referencing_table_7000311 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000312 | fkey_reference_table.referencing_table_7000312 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000313 | fkey_reference_table.referencing_table_7000313 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000314 | fkey_reference_table.referencing_table_7000314 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000315 | fkey_reference_table.referencing_table_7000315 | fkey_reference_table.referenced_table_7000307
referencing_referencing_table_id_fkey_7000316 | fkey_reference_table.referencing_referencing_table_7000316 | fkey_reference_table.referencing_table_7000308
referencing_referencing_table_id_fkey_7000317 | fkey_reference_table.referencing_referencing_table_7000317 | fkey_reference_table.referencing_table_7000309
referencing_referencing_table_id_fkey_7000318 | fkey_reference_table.referencing_referencing_table_7000318 | fkey_reference_table.referencing_table_7000310
referencing_referencing_table_id_fkey_7000319 | fkey_reference_table.referencing_referencing_table_7000319 | fkey_reference_table.referencing_table_7000311
referencing_referencing_table_id_fkey_7000320 | fkey_reference_table.referencing_referencing_table_7000320 | fkey_reference_table.referencing_table_7000312
referencing_referencing_table_id_fkey_7000321 | fkey_reference_table.referencing_referencing_table_7000321 | fkey_reference_table.referencing_table_7000313
referencing_referencing_table_id_fkey_7000322 | fkey_reference_table.referencing_referencing_table_7000322 | fkey_reference_table.referencing_table_7000314
referencing_referencing_table_id_fkey_7000323 | fkey_reference_table.referencing_referencing_table_7000323 | fkey_reference_table.referencing_table_7000315
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(1,1000) AS f(x);
@ -1830,8 +1866,8 @@ ALTER TABLE referencing_table_4 ADD CONSTRAINT fkey FOREIGN KEY (id) REFERENCES
ALTER TABLE referencing_table_4 ADD CONSTRAINT fkey_to_ref FOREIGN KEY (value_1) REFERENCES referenced_table;
-- should fail since the data will flow to partitioning_test_4 and it has a foreign constraint to partitioning_test_0 on id column
INSERT INTO referencing_table VALUES (0, 5);
ERROR: insert or update on table "referencing_table_4_7000533" violates foreign key constraint "fkey_7000533"
DETAIL: Key (id)=(0) is not present in table "referencing_table_0_7000517".
ERROR: insert or update on table "referencing_table_4_7000549" violates foreign key constraint "fkey_7000549"
DETAIL: Key (id)=(0) is not present in table "referencing_table_0_7000533".
CONTEXT: while executing command on localhost:57638
-- should succeed on partitioning_test_0
INSERT INTO referencing_table VALUES (0, 1);
@ -1843,8 +1879,8 @@ SELECT * FROM referencing_table;
-- should fail since partitioning_test_4 has foreign constraint to referenced_table on value_1 column
INSERT INTO referencing_table VALUES (0, 5);
ERROR: insert or update on table "referencing_table_4_7000533" violates foreign key constraint "fkey_to_ref_7000533"
DETAIL: Key (value_1)=(5) is not present in table "referenced_table_7000505".
ERROR: insert or update on table "referencing_table_4_7000549" violates foreign key constraint "fkey_to_ref_7000549"
DETAIL: Key (value_1)=(5) is not present in table "referenced_table_7000521".
CONTEXT: while executing command on localhost:57638
INSERT INTO referenced_table VALUES(5,5);
-- should succeed since both of the foreign constraints are positive

View File

@ -293,6 +293,24 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A
fkey_ref_7000098 | fkey_reference_table.referencing_table_7000098 | fkey_reference_table.referenced_table_7000042
(8 rows)
DROP TABLE referencing_table;
-- check if we can add the foreign key while adding the column
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
create_distributed_table
--------------------------
(1 row)
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 * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
-- foreign keys are only supported when the replication factor = 1
SET citus.shard_replication_factor TO 2;
@ -312,6 +330,24 @@ SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' A
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
-- should fail when we add the column as well
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
create_distributed_table
--------------------------
(1 row)
ALTER TABLE referencing_table ADD COLUMN referencing_col int REFERENCES referenced_table(id) ON DELETE SET NULL;
ERROR: cannot create foreign key constraint
DETAIL: Citus Community Edition currently supports foreign key constraints only for "citus.shard_replication_factor = 1".
HINT: Please change "citus.shard_replication_factor to 1". To learn more about using foreign keys with other replication factors, please contact us at https://citusdata.com/about/contact_us.
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
------+-------+------------
(0 rows)
DROP TABLE referencing_table;
SET citus.shard_replication_factor TO 1;
-- simple create_distributed_table should work in/out transactions on tables with foreign key to reference tables
@ -325,14 +361,14 @@ SELECT create_distributed_table('referencing_table', 'ref_id');
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------+------------------------------------------------+-----------------------------------------------
referencing_table_id_fkey_7000107 | fkey_reference_table.referencing_table_7000107 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000108 | fkey_reference_table.referencing_table_7000108 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000109 | fkey_reference_table.referencing_table_7000109 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000110 | fkey_reference_table.referencing_table_7000110 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000111 | fkey_reference_table.referencing_table_7000111 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000112 | fkey_reference_table.referencing_table_7000112 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000113 | fkey_reference_table.referencing_table_7000113 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000114 | fkey_reference_table.referencing_table_7000114 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000123 | fkey_reference_table.referencing_table_7000123 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000124 | fkey_reference_table.referencing_table_7000124 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000125 | fkey_reference_table.referencing_table_7000125 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000126 | fkey_reference_table.referencing_table_7000126 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000127 | fkey_reference_table.referencing_table_7000127 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000128 | fkey_reference_table.referencing_table_7000128 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000129 | fkey_reference_table.referencing_table_7000129 | fkey_reference_table.referenced_table_7000042
referencing_table_id_fkey_7000130 | fkey_reference_table.referencing_table_7000130 | fkey_reference_table.referenced_table_7000042
(8 rows)
DROP TABLE referencing_table;
@ -356,14 +392,14 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------+------------------------------------------------+-----------------------------------------------
referencing_table_id_fkey_7000116 | fkey_reference_table.referencing_table_7000116 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000117 | fkey_reference_table.referencing_table_7000117 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000118 | fkey_reference_table.referencing_table_7000118 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000119 | fkey_reference_table.referencing_table_7000119 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000120 | fkey_reference_table.referencing_table_7000120 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000121 | fkey_reference_table.referencing_table_7000121 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000122 | fkey_reference_table.referencing_table_7000122 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000123 | fkey_reference_table.referencing_table_7000123 | fkey_reference_table.referenced_table_7000115
referencing_table_id_fkey_7000132 | fkey_reference_table.referencing_table_7000132 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000133 | fkey_reference_table.referencing_table_7000133 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000134 | fkey_reference_table.referencing_table_7000134 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000135 | fkey_reference_table.referencing_table_7000135 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000136 | fkey_reference_table.referencing_table_7000136 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000137 | fkey_reference_table.referencing_table_7000137 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000138 | fkey_reference_table.referencing_table_7000138 | fkey_reference_table.referenced_table_7000131
referencing_table_id_fkey_7000139 | fkey_reference_table.referencing_table_7000139 | fkey_reference_table.referenced_table_7000131
(8 rows)
DROP TABLE referencing_table;
@ -421,8 +457,8 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id) REFER
-- test inserts
-- test insert to referencing table while there is NO corresponding value in referenced table
INSERT INTO referencing_table VALUES(1, 1);
ERROR: insert or update on table "referencing_table_7000125" violates foreign key constraint "fkey_ref_7000125"
DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000124".
ERROR: insert or update on table "referencing_table_7000141" violates foreign key constraint "fkey_ref_7000141"
DETAIL: Key (ref_id)=(1) is not present in table "referenced_table_7000140".
CONTEXT: while executing command on localhost:57637
-- test insert to referencing while there is corresponding value in referenced table
INSERT INTO referenced_table SELECT x, x from generate_series(1,1000) as f(x);
@ -430,8 +466,8 @@ INSERT INTO referencing_table SELECT x, x from generate_series(1,500) as f(x);
-- test deletes
-- test delete from referenced table while there is corresponding value in referencing table
DELETE FROM referenced_table WHERE id > 3;
ERROR: update or delete on table "referenced_table_7000124" violates foreign key constraint "fkey_ref_7000127" on table "referencing_table_7000127"
DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000127".
ERROR: update or delete on table "referenced_table_7000140" violates foreign key constraint "fkey_ref_7000143" on table "referencing_table_7000143"
DETAIL: Key (id)=(4) is still referenced from table "referencing_table_7000143".
CONTEXT: while executing command on localhost:57637
-- test delete from referenced table while there is NO corresponding value in referencing table
DELETE FROM referenced_table WHERE id = 501;
@ -626,8 +662,8 @@ INSERT INTO referenced_table SELECT x,x FROM generate_series(1,1000) AS f(x);
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
-- Fails for non existing value inserts (serial is already incremented)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
ERROR: insert or update on table "referencing_table_7000172" violates foreign key constraint "fkey_ref_7000172"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000171".
ERROR: insert or update on table "referencing_table_7000195" violates foreign key constraint "fkey_ref_7000195"
DETAIL: Key (ref_id)=(1009) is not present in table "referenced_table_7000187".
DROP TABLE referenced_table CASCADE;
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
DROP TABLE referencing_table CASCADE;
@ -657,8 +693,8 @@ INSERT INTO referenced_table(test_column2) SELECT x FROM generate_series(1,1000)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,1000) AS f(x);
-- Fails for non existing value inserts (serial is already incremented)
INSERT INTO referencing_table(id) SELECT x FROM generate_series(1,10) AS f(x);
ERROR: insert or update on table "referencing_table_7000181" violates foreign key constraint "fkey_ref_7000181"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000180".
ERROR: insert or update on table "referencing_table_7000197" violates foreign key constraint "fkey_ref_7000197"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000196".
DROP TABLE referenced_table CASCADE;
NOTICE: drop cascades to constraint fkey_ref on table referencing_table
DROP TABLE referencing_table CASCADE;
@ -709,8 +745,8 @@ INSERT INTO referenced_table SELECT x, x FROM generate_series(0,1000) AS f(x);
INSERT INTO referencing_table SELECT x, x FROM generate_series(0,1000) AS f(x);
-- we expect this to fail because of the foreign constraint.
INSERT INTO referencing_table SELECT x, x FROM generate_series(1000,1001) AS f(x);
ERROR: insert or update on table "referencing_table_7000204" violates foreign key constraint "fkey_ref_7000204"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000198".
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220"
DETAIL: Key (ref_id)=(1001) is not present in table "referenced_table_7000214".
-- currently not supported
ALTER TABLE referencing_table VALIDATE CONSTRAINT fkey_ref;
ERROR: alter table command is currently unsupported
@ -809,38 +845,38 @@ ALTER TABLE referencing_table ADD CONSTRAINT foreign_key_2 FOREIGN KEY (id) REFE
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------+------------------------------------------------+------------------------------------------------
fkey_ref_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table_7000217
fkey_ref_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table_7000217
foreign_key_2_7000219 | fkey_reference_table.referencing_table_7000219 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000220 | fkey_reference_table.referencing_table_7000220 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000221 | fkey_reference_table.referencing_table_7000221 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000222 | fkey_reference_table.referencing_table_7000222 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000223 | fkey_reference_table.referencing_table_7000223 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000224 | fkey_reference_table.referencing_table_7000224 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000225 | fkey_reference_table.referencing_table_7000225 | fkey_reference_table.referenced_table2_7000218
foreign_key_2_7000226 | fkey_reference_table.referencing_table_7000226 | fkey_reference_table.referenced_table2_7000218
fkey_ref_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000233
fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000233
foreign_key_2_7000235 | fkey_reference_table.referencing_table_7000235 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000236 | fkey_reference_table.referencing_table_7000236 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000237 | fkey_reference_table.referencing_table_7000237 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000238 | fkey_reference_table.referencing_table_7000238 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000234
foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000234
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220"
DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242"
DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "foreign_key_2_7000220"
DETAIL: Key (id)=(5) is not present in table "referenced_table2_7000218".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "foreign_key_2_7000242"
DETAIL: Key (id)=(9) is not present in table "referenced_table2_7000234".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
ERROR: insert or update on table "referencing_table_7000220" violates foreign key constraint "fkey_ref_7000220"
DETAIL: Key (id)=(1005) is not present in table "referenced_table_7000217".
ERROR: insert or update on table "referencing_table_7000242" violates foreign key constraint "fkey_ref_7000242"
DETAIL: Key (id)=(1023) is not present in table "referenced_table_7000233".
-- should success
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(600,900) AS f(x);
SELECT count(*) FROM referencing_table;
@ -936,38 +972,38 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------+------------------------------------------------+------------------------------------------------
fkey_ref_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table_7000237
fkey_ref_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table_7000237
foreign_key_2_7000239 | fkey_reference_table.referencing_table_7000239 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000240 | fkey_reference_table.referencing_table_7000240 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000241 | fkey_reference_table.referencing_table_7000241 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000242 | fkey_reference_table.referencing_table_7000242 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000243 | fkey_reference_table.referencing_table_7000243 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000244 | fkey_reference_table.referencing_table_7000244 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000245 | fkey_reference_table.referencing_table_7000245 | fkey_reference_table.referenced_table2_7000238
foreign_key_2_7000246 | fkey_reference_table.referencing_table_7000246 | fkey_reference_table.referenced_table2_7000238
fkey_ref_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000253
fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000253
foreign_key_2_7000255 | fkey_reference_table.referencing_table_7000255 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000256 | fkey_reference_table.referencing_table_7000256 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000257 | fkey_reference_table.referencing_table_7000257 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table2_7000254
foreign_key_2_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table2_7000254
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
INSERT INTO referenced_table2 SELECT x, x+1 FROM generate_series(500,1500) AS f(x);
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,1500) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245"
DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260"
DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "foreign_key_2_7000245"
DETAIL: Key (ref_id)=(3) is not present in table "referenced_table2_7000238".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "foreign_key_2_7000260"
DETAIL: Key (ref_id)=(7) is not present in table "referenced_table2_7000254".
-- should fail
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(1000,1400) AS f(x);
ERROR: insert or update on table "referencing_table_7000245" violates foreign key constraint "fkey_ref_7000245"
DETAIL: Key (id)=(1002) is not present in table "referenced_table_7000237".
ERROR: insert or update on table "referencing_table_7000260" violates foreign key constraint "fkey_ref_7000260"
DETAIL: Key (id)=(1001) is not present in table "referenced_table_7000253".
-- should success
INSERT INTO referencing_table SELECT x, x+501 FROM generate_series(0,1000) AS f(x);
SELECT count(*) FROM referencing_table;
@ -1069,43 +1105,43 @@ COMMIT;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
name | relid | refd_relid
--------------------------+-------------------------------------------------+------------------------------------------------
fkey_ref_7000258 | fkey_reference_table.referencing_table_7000258 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000259 | fkey_reference_table.referencing_table_7000259 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000260 | fkey_reference_table.referencing_table_7000260 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000261 | fkey_reference_table.referencing_table_7000261 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000262 | fkey_reference_table.referencing_table_7000262 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000263 | fkey_reference_table.referencing_table_7000263 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000264 | fkey_reference_table.referencing_table_7000264 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000265 | fkey_reference_table.referencing_table_7000265 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referenced_table_7000257
fkey_ref_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referenced_table_7000257
fkey_ref_to_dist_7000266 | fkey_reference_table.referencing_table2_7000266 | fkey_reference_table.referencing_table_7000258
fkey_ref_to_dist_7000267 | fkey_reference_table.referencing_table2_7000267 | fkey_reference_table.referencing_table_7000259
fkey_ref_to_dist_7000268 | fkey_reference_table.referencing_table2_7000268 | fkey_reference_table.referencing_table_7000260
fkey_ref_to_dist_7000269 | fkey_reference_table.referencing_table2_7000269 | fkey_reference_table.referencing_table_7000261
fkey_ref_to_dist_7000270 | fkey_reference_table.referencing_table2_7000270 | fkey_reference_table.referencing_table_7000262
fkey_ref_to_dist_7000271 | fkey_reference_table.referencing_table2_7000271 | fkey_reference_table.referencing_table_7000263
fkey_ref_to_dist_7000272 | fkey_reference_table.referencing_table2_7000272 | fkey_reference_table.referencing_table_7000264
fkey_ref_to_dist_7000273 | fkey_reference_table.referencing_table2_7000273 | fkey_reference_table.referencing_table_7000265
fkey_ref_7000274 | fkey_reference_table.referencing_table_7000274 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000275 | fkey_reference_table.referencing_table_7000275 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000276 | fkey_reference_table.referencing_table_7000276 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000277 | fkey_reference_table.referencing_table_7000277 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000278 | fkey_reference_table.referencing_table_7000278 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000279 | fkey_reference_table.referencing_table_7000279 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000280 | fkey_reference_table.referencing_table_7000280 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000281 | fkey_reference_table.referencing_table_7000281 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referenced_table_7000273
fkey_ref_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referenced_table_7000273
fkey_ref_to_dist_7000282 | fkey_reference_table.referencing_table2_7000282 | fkey_reference_table.referencing_table_7000274
fkey_ref_to_dist_7000283 | fkey_reference_table.referencing_table2_7000283 | fkey_reference_table.referencing_table_7000275
fkey_ref_to_dist_7000284 | fkey_reference_table.referencing_table2_7000284 | fkey_reference_table.referencing_table_7000276
fkey_ref_to_dist_7000285 | fkey_reference_table.referencing_table2_7000285 | fkey_reference_table.referencing_table_7000277
fkey_ref_to_dist_7000286 | fkey_reference_table.referencing_table2_7000286 | fkey_reference_table.referencing_table_7000278
fkey_ref_to_dist_7000287 | fkey_reference_table.referencing_table2_7000287 | fkey_reference_table.referencing_table_7000279
fkey_ref_to_dist_7000288 | fkey_reference_table.referencing_table2_7000288 | fkey_reference_table.referencing_table_7000280
fkey_ref_to_dist_7000289 | fkey_reference_table.referencing_table2_7000289 | fkey_reference_table.referencing_table_7000281
(24 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(0,1000) AS f(x);
-- should fail
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,100) AS f(x);
ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272"
DETAIL: Key (id)=(2) is not present in table "referencing_table_7000264".
ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284"
DETAIL: Key (id)=(4) is not present in table "referencing_table_7000276".
-- should success
INSERT INTO referencing_table SELECT x, x+1 FROM generate_series(0,400) AS f(x);
-- should fail
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(200,500) AS f(x);
ERROR: insert or update on table "referencing_table2_7000272" violates foreign key constraint "fkey_ref_to_dist_7000272"
DETAIL: Key (id)=(404) is not present in table "referencing_table_7000264".
ERROR: insert or update on table "referencing_table2_7000284" violates foreign key constraint "fkey_ref_to_dist_7000284"
DETAIL: Key (id)=(408) is not present in table "referencing_table_7000276".
-- should success
INSERT INTO referencing_table2 SELECT x, x+1 FROM generate_series(0,300) AS f(x);
DELETE FROM referenced_table WHERE test_column < 200;
@ -1203,22 +1239,22 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (ref_id, ref_i
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.referencing%' ORDER BY 1,2,3;
name | relid | refd_relid
-----------------------------------------------+------------------------------------------------------------+------------------------------------------------
fkey_ref_7000292 | fkey_reference_table.referencing_table_7000292 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000293 | fkey_reference_table.referencing_table_7000293 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000294 | fkey_reference_table.referencing_table_7000294 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000295 | fkey_reference_table.referencing_table_7000295 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000296 | fkey_reference_table.referencing_table_7000296 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000297 | fkey_reference_table.referencing_table_7000297 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000298 | fkey_reference_table.referencing_table_7000298 | fkey_reference_table.referenced_table_7000291
fkey_ref_7000299 | fkey_reference_table.referencing_table_7000299 | fkey_reference_table.referenced_table_7000291
referencing_referencing_table_id_fkey_7000300 | fkey_reference_table.referencing_referencing_table_7000300 | fkey_reference_table.referencing_table_7000292
referencing_referencing_table_id_fkey_7000301 | fkey_reference_table.referencing_referencing_table_7000301 | fkey_reference_table.referencing_table_7000293
referencing_referencing_table_id_fkey_7000302 | fkey_reference_table.referencing_referencing_table_7000302 | fkey_reference_table.referencing_table_7000294
referencing_referencing_table_id_fkey_7000303 | fkey_reference_table.referencing_referencing_table_7000303 | fkey_reference_table.referencing_table_7000295
referencing_referencing_table_id_fkey_7000304 | fkey_reference_table.referencing_referencing_table_7000304 | fkey_reference_table.referencing_table_7000296
referencing_referencing_table_id_fkey_7000305 | fkey_reference_table.referencing_referencing_table_7000305 | fkey_reference_table.referencing_table_7000297
referencing_referencing_table_id_fkey_7000306 | fkey_reference_table.referencing_referencing_table_7000306 | fkey_reference_table.referencing_table_7000298
referencing_referencing_table_id_fkey_7000307 | fkey_reference_table.referencing_referencing_table_7000307 | fkey_reference_table.referencing_table_7000299
fkey_ref_7000308 | fkey_reference_table.referencing_table_7000308 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000309 | fkey_reference_table.referencing_table_7000309 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000310 | fkey_reference_table.referencing_table_7000310 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000311 | fkey_reference_table.referencing_table_7000311 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000312 | fkey_reference_table.referencing_table_7000312 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000313 | fkey_reference_table.referencing_table_7000313 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000314 | fkey_reference_table.referencing_table_7000314 | fkey_reference_table.referenced_table_7000307
fkey_ref_7000315 | fkey_reference_table.referencing_table_7000315 | fkey_reference_table.referenced_table_7000307
referencing_referencing_table_id_fkey_7000316 | fkey_reference_table.referencing_referencing_table_7000316 | fkey_reference_table.referencing_table_7000308
referencing_referencing_table_id_fkey_7000317 | fkey_reference_table.referencing_referencing_table_7000317 | fkey_reference_table.referencing_table_7000309
referencing_referencing_table_id_fkey_7000318 | fkey_reference_table.referencing_referencing_table_7000318 | fkey_reference_table.referencing_table_7000310
referencing_referencing_table_id_fkey_7000319 | fkey_reference_table.referencing_referencing_table_7000319 | fkey_reference_table.referencing_table_7000311
referencing_referencing_table_id_fkey_7000320 | fkey_reference_table.referencing_referencing_table_7000320 | fkey_reference_table.referencing_table_7000312
referencing_referencing_table_id_fkey_7000321 | fkey_reference_table.referencing_referencing_table_7000321 | fkey_reference_table.referencing_table_7000313
referencing_referencing_table_id_fkey_7000322 | fkey_reference_table.referencing_referencing_table_7000322 | fkey_reference_table.referencing_table_7000314
referencing_referencing_table_id_fkey_7000323 | fkey_reference_table.referencing_referencing_table_7000323 | fkey_reference_table.referencing_table_7000315
(16 rows)
INSERT INTO referenced_table SELECT x, x+1 FROM generate_series(1,1000) AS f(x);

View File

@ -513,8 +513,8 @@ ORDER BY
1,2,3,4;
nodename | nodeport | success | result
-----------+----------+---------+---------------------
localhost | 57637 | t | alter_pk_idx_220026
localhost | 57638 | t | alter_pk_idx_220026
localhost | 57637 | t | alter_pk_idx_220035
localhost | 57638 | t | alter_pk_idx_220035
(2 rows)
CREATE SCHEMA sc2;
@ -544,8 +544,8 @@ ORDER BY
1,2,3,4;
nodename | nodeport | success | result
-----------+----------+---------+---------------------
localhost | 57637 | t | alter_pk_idx_220028
localhost | 57638 | t | alter_pk_idx_220028
localhost | 57637 | t | alter_pk_idx_220037
localhost | 57638 | t | alter_pk_idx_220037
(2 rows)
-- We are running almost the same test with a slight change on the constraint name because if the constraint has a different name than the index, Postgres renames the index.
@ -579,8 +579,8 @@ ORDER BY
1,2,3,4;
nodename | nodeport | success | result
-----------+----------+---------+---------------------
localhost | 57637 | t | a_constraint_220030
localhost | 57638 | t | a_constraint_220030
localhost | 57637 | t | a_constraint_220039
localhost | 57638 | t | a_constraint_220039
(2 rows)
ALTER TABLE alter_add_prim_key DROP CONSTRAINT a_constraint;

View File

@ -38,6 +38,10 @@ CREATE FUNCTION acquire_shared_shard_lock(bigint)
RETURNS void
AS 'citus'
LANGUAGE C STRICT;
CREATE FUNCTION relation_count_in_query(text)
RETURNS int
AS 'citus'
LANGUAGE C STRICT;
-- ===================================================================
-- test distribution metadata functionality
-- ===================================================================
@ -464,5 +468,96 @@ SELECT get_shard_id_for_distribution_column('get_shardid_test_table5', -999);
0
(1 row)
SET citus.shard_count TO 2;
CREATE TABLE events_table_count (user_id int, time timestamp, event_type int, value_2 int, value_3 float, value_4 bigint);
SELECT create_distributed_table('events_table_count', 'user_id');
create_distributed_table
--------------------------
(1 row)
CREATE TABLE users_table_count (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint);
SELECT create_distributed_table('users_table_count', 'user_id');
create_distributed_table
--------------------------
(1 row)
SELECT relation_count_in_query($$-- we can support arbitrary subqueries within UNIONs
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM
( SELECT
*, random()
FROM
(SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM
( SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM (
(SELECT
*
FROM
(SELECT
events_table."time", 0 AS event, events_table."user_id"
FROM
"events_table_count" as events_table
WHERE
events_table.event_type IN (1, 2) ) events_subquery_1)
UNION
(SELECT *
FROM
(
SELECT * FROM
(
SELECT
max("events_table_count"."time"),
0 AS event,
"events_table_count"."user_id"
FROM
"events_table_count", users_table_count as "users"
WHERE
"events_table_count".user_id = users.user_id AND
"events_table_count".event_type IN (1, 2)
GROUP BY "events_table_count"."user_id"
) as events_subquery_5
) events_subquery_2)
UNION
(SELECT *
FROM
(SELECT
"events_table_count"."time", 2 AS event, "events_table_count"."user_id"
FROM
"events_table_count"
WHERE
event_type IN (3, 4) ) events_subquery_3)
UNION
(SELECT *
FROM
(SELECT
"events_table_count"."time", 3 AS event, "events_table_count"."user_id"
FROM
"events_table_count"
WHERE
event_type IN (5, 6)) events_subquery_4)
) t1
GROUP BY "t1"."user_id") AS t) "q"
INNER JOIN
(SELECT
"events_table_count"."user_id"
FROM
users_table_count as "events_table_count"
WHERE
value_1 > 0 and value_1 < 4) AS t
ON (t.user_id = q.user_id)) as final_query
GROUP BY
types
ORDER BY
types;$$);
relation_count_in_query
-------------------------
6
(1 row)
-- clear unnecessary tables;
DROP TABLE get_shardid_test_table1, get_shardid_test_table2, get_shardid_test_table3, get_shardid_test_table4, get_shardid_test_table5;
DROP TABLE get_shardid_test_table1, get_shardid_test_table2, get_shardid_test_table3, get_shardid_test_table4, get_shardid_test_table5, events_table_count;

View File

@ -147,7 +147,7 @@ ALTER EXTENSION citus UPDATE TO '7.5-7';
SHOW citus.version;
citus.version
---------------
7.5devel
7.5.1
(1 row)
-- ensure no objects were created outside pg_catalog

View File

@ -465,6 +465,10 @@ DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operatio
ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE CASCADE;
ERROR: cannot create foreign key constraint
DETAIL: SET NULL, SET DEFAULT or CASCADE is not supported in ON UPDATE operation when distribution key included in the foreign constraint.
-- test foreign constraint creation while adding the column
ALTER TABLE referencing_table ADD COLUMN referencing_col int REFERENCES referenced_table(id) ON UPDATE CASCADE;;
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
-- test foreign constraint creation with multiple subcommands
ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id) REFERENCES referenced_table(id),
ADD CONSTRAINT test_constraint FOREIGN KEY(id) REFERENCES referenced_table(test_column);

View File

@ -2735,6 +2735,22 @@ EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
ROLLBACK;
-- upsert with on conflict update distribution column is unsupported
INSERT INTO agg_events AS ae
(
user_id,
value_1_agg,
agg_time
)
SELECT user_id,
value_1,
time
FROM raw_events_first
ON conflict (user_id, value_1_agg)
DO UPDATE
SET user_id = 42
RETURNING user_id, value_1_agg;
ERROR: modifying the partition value of rows is not allowed
-- wrap in a transaction to improve performance
BEGIN;
DROP TABLE coerce_events;

View File

@ -212,7 +212,24 @@ ERROR: permission denied for relation test
ABORT;
SELECT * FROM citus_stat_statements_reset();
ERROR: permission denied for function citus_stat_statements_reset
-- table owner should be the same on the shards, even when distributing the table as superuser
SET ROLE full_access;
CREATE TABLE my_table (id integer, val integer);
RESET ROLE;
SELECT create_distributed_table('my_table', 'id');
create_distributed_table
--------------------------
(1 row)
SELECT result FROM run_command_on_workers($$SELECT tableowner FROM pg_tables WHERE tablename LIKE 'my_table_%' LIMIT 1$$);
result
-------------
full_access
full_access
(2 rows)
DROP TABLE my_table;
DROP TABLE test;
DROP USER full_access;
DROP USER read_access;

View File

@ -18,3 +18,10 @@ INSERT INTO pg_dist_authinfo VALUES (0, 'new_user', 'password=1234');
ERROR: cannot write to pg_dist_authinfo
DETAIL: Citus Community Edition does not support the use of custom authentication options.
HINT: To learn more about using advanced authentication schemes with Citus, please contact us at https://citusdata.com/about/contact_us
BEGIN;
INSERT INTO pg_dist_node VALUES (1234567890, 1234567890, 'localhost', 5432);
INSERT INTO pg_dist_poolinfo VALUES (1234567890, 'port=1234');
ERROR: cannot write to pg_dist_poolinfo
DETAIL: Citus Community Edition does not support the use of pooler options.
HINT: To learn more about using advanced pooling schemes with Citus, please contact us at https://citusdata.com/about/contact_us
ROLLBACK;

View File

@ -585,3 +585,24 @@ SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index%' ORD
-- get rid of the index
DROP INDEX another_index;
-- check if we fail properly when a column with un-supported constraint is added
-- UNIQUE, PRIMARY KEY on non-distribution column is not supported
-- CHECK, FOREIGN KEY, UNIQE, PRIMARY KEY cannot be added together with ADD COLUMN
SET citus.shard_replication_factor TO 1;
CREATE TABLE test_table_1(id int);
SELECT create_distributed_table('test_table_1', 'id');
ALTER TABLE test_table_1 ADD COLUMN test_col int UNIQUE;
ALTER TABLE test_table_1 ADD COLUMN test_col int PRIMARY KEY;
ALTER TABLE test_table_1 ADD COLUMN test_col int CHECK (test_col > 3);
CREATE TABLE reference_table(i int UNIQUE);
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;
DROP TABLE reference_table;
CREATE TABLE referenced_table(i int UNIQUE);
SELECT create_distributed_table('referenced_table', 'i');
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES referenced_table(i);
DROP TABLE referenced_table, test_table_1;

View File

@ -1153,3 +1153,51 @@ SELECT relname, reloptions FROM pg_class WHERE relname LIKE 'another_index%' ORD
\c - - - :master_port
-- get rid of the index
DROP INDEX another_index;
-- check if we fail properly when a column with un-supported constraint is added
-- UNIQUE, PRIMARY KEY on non-distribution column is not supported
-- CHECK, FOREIGN KEY, UNIQE, PRIMARY KEY cannot be added together with ADD COLUMN
SET citus.shard_replication_factor TO 1;
CREATE TABLE test_table_1(id int);
SELECT create_distributed_table('test_table_1', 'id');
create_distributed_table
--------------------------
(1 row)
ALTER TABLE test_table_1 ADD COLUMN test_col int UNIQUE;
ERROR: cannot create constraint on "test_table_1"
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
ALTER TABLE test_table_1 ADD COLUMN test_col int PRIMARY KEY;
ERROR: cannot create constraint on "test_table_1"
DETAIL: Distributed relations cannot have UNIQUE, EXCLUDE, or PRIMARY KEY constraints that do not include the partition column (with an equality operator if EXCLUDE).
ALTER TABLE test_table_1 ADD COLUMN test_col int CHECK (test_col > 3);
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 test_table_1 ADD COLUMN test_col data_type; ALTER TABLE test_table_1 ADD CONSTRAINT constraint_name CHECK (check_expression);
CREATE TABLE reference_table(i int UNIQUE);
SELECT create_reference_table('reference_table');
create_reference_table
------------------------
(1 row)
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES reference_table(i) ON DELETE 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 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;
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
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 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;
DROP TABLE reference_table;
CREATE TABLE referenced_table(i int UNIQUE);
SELECT create_distributed_table('referenced_table', 'i');
create_distributed_table
--------------------------
(1 row)
ALTER TABLE test_table_1 ADD COLUMN test_col int REFERENCES referenced_table(i);
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
DROP TABLE referenced_table, test_table_1;

View File

@ -570,6 +570,69 @@ BEGIN;
DROP TABLE test_table_2, test_table_1;
COMMIT;
-- make sure that modifications to reference tables in a CTE can
-- set the mode to sequential for the next operations
CREATE TABLE reference_table(id int PRIMARY KEY);
SELECT create_reference_table('reference_table');
CREATE TABLE distributed_table(id int PRIMARY KEY, value_1 int);
SELECT create_distributed_table('distributed_table', 'id');
ALTER TABLE
distributed_table
ADD CONSTRAINT
fkey_delete FOREIGN KEY(value_1)
REFERENCES
reference_table(id) ON DELETE CASCADE;
INSERT INTO reference_table SELECT i FROM generate_series(0, 10) i;
INSERT INTO distributed_table SELECT i, i % 10 FROM generate_series(0, 100) i;
-- this query returns 100 rows in Postgres, but not in Citus
-- see https://github.com/citusdata/citus_docs/issues/664 for the discussion
WITH t1 AS (DELETE FROM reference_table RETURNING id)
DELETE FROM distributed_table USING t1 WHERE value_1 = t1.id RETURNING *;
-- load some more data for one more test with real-time selects
INSERT INTO reference_table SELECT i FROM generate_series(0, 10) i;
INSERT INTO distributed_table SELECT i, i % 10 FROM generate_series(0, 100) i;
-- this query returns 100 rows in Postgres, but not in Citus
-- see https://github.com/citusdata/citus_docs/issues/664 for the discussion
WITH t1 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1 WHERE value_1 = t1.id;
-- this query should fail since we first to a parallel access to a distributed table
-- with t1, and then access to t2
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
t2 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1, t2 WHERE value_1 = t1.id AND value_1 = t2.id;
-- similarly this should fail since we first access to a distributed
-- table via t1, and then access to the reference table in the main query
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
DELETE FROM reference_table RETURNING id;
-- finally, make sure that we can execute the same queries
-- in the sequential mode
BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
WITH t1 AS (DELETE FROM distributed_table RETURNING id),
t2 AS (DELETE FROM reference_table RETURNING id)
SELECT count(*) FROM distributed_table, t1, t2 WHERE value_1 = t1.id AND value_1 = t2.id;
ROLLBACK;
BEGIN;
SET LOCAL citus.multi_shard_modify_mode TO 'sequential';
WITH t1 AS (DELETE FROM distributed_table RETURNING id)
DELETE FROM reference_table RETURNING id;
ROLLBACK;
RESET client_min_messages;
DROP SCHEMA test_fkey_to_ref_in_tx CASCADE;

View File

@ -133,6 +133,13 @@ ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY(id) REFERENCES
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
DROP TABLE referencing_table;
-- check if we can add the foreign key while adding the column
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
ALTER TABLE referencing_table ADD COLUMN referencing int REFERENCES referenced_table(id) ON UPDATE CASCADE;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
DROP TABLE referencing_table;
-- foreign keys are only supported when the replication factor = 1
SET citus.shard_replication_factor TO 2;
CREATE TABLE referencing_table(id int, ref_id int);
@ -140,6 +147,13 @@ SELECT create_distributed_table('referencing_table', 'ref_id');
ALTER TABLE referencing_table ADD CONSTRAINT fkey_ref FOREIGN KEY (id) REFERENCES referenced_table(id);
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
DROP TABLE referencing_table;
-- should fail when we add the column as well
CREATE TABLE referencing_table(id int, ref_id int);
SELECT create_distributed_table('referencing_table', 'ref_id');
ALTER TABLE referencing_table ADD COLUMN referencing_col int REFERENCES referenced_table(id) ON DELETE SET NULL;
SELECT * FROM table_fkeys_in_workers WHERE relid LIKE 'fkey_reference_table.%' AND refd_relid LIKE 'fkey_reference_table.%' ORDER BY 1,2,3;
DROP TABLE referencing_table;
SET citus.shard_replication_factor TO 1;
-- simple create_distributed_table should work in/out transactions on tables with foreign key to reference tables

View File

@ -51,6 +51,11 @@ CREATE FUNCTION acquire_shared_shard_lock(bigint)
AS 'citus'
LANGUAGE C STRICT;
CREATE FUNCTION relation_count_in_query(text)
RETURNS int
AS 'citus'
LANGUAGE C STRICT;
-- ===================================================================
-- test distribution metadata functionality
-- ===================================================================
@ -259,5 +264,85 @@ SELECT get_shard_id_for_distribution_column('get_shardid_test_table5', 3248);
SELECT get_shard_id_for_distribution_column('get_shardid_test_table5', 4001);
SELECT get_shard_id_for_distribution_column('get_shardid_test_table5', -999);
SET citus.shard_count TO 2;
CREATE TABLE events_table_count (user_id int, time timestamp, event_type int, value_2 int, value_3 float, value_4 bigint);
SELECT create_distributed_table('events_table_count', 'user_id');
CREATE TABLE users_table_count (user_id int, time timestamp, value_1 int, value_2 int, value_3 float, value_4 bigint);
SELECT create_distributed_table('users_table_count', 'user_id');
SELECT relation_count_in_query($$-- we can support arbitrary subqueries within UNIONs
SELECT ("final_query"."event_types") as types, count(*) AS sumOfEventType
FROM
( SELECT
*, random()
FROM
(SELECT
"t"."user_id", "t"."time", unnest("t"."collected_events") AS "event_types"
FROM
( SELECT
"t1"."user_id", min("t1"."time") AS "time", array_agg(("t1"."event") ORDER BY TIME ASC, event DESC) AS collected_events
FROM (
(SELECT
*
FROM
(SELECT
events_table."time", 0 AS event, events_table."user_id"
FROM
"events_table_count" as events_table
WHERE
events_table.event_type IN (1, 2) ) events_subquery_1)
UNION
(SELECT *
FROM
(
SELECT * FROM
(
SELECT
max("events_table_count"."time"),
0 AS event,
"events_table_count"."user_id"
FROM
"events_table_count", users_table_count as "users"
WHERE
"events_table_count".user_id = users.user_id AND
"events_table_count".event_type IN (1, 2)
GROUP BY "events_table_count"."user_id"
) as events_subquery_5
) events_subquery_2)
UNION
(SELECT *
FROM
(SELECT
"events_table_count"."time", 2 AS event, "events_table_count"."user_id"
FROM
"events_table_count"
WHERE
event_type IN (3, 4) ) events_subquery_3)
UNION
(SELECT *
FROM
(SELECT
"events_table_count"."time", 3 AS event, "events_table_count"."user_id"
FROM
"events_table_count"
WHERE
event_type IN (5, 6)) events_subquery_4)
) t1
GROUP BY "t1"."user_id") AS t) "q"
INNER JOIN
(SELECT
"events_table_count"."user_id"
FROM
users_table_count as "events_table_count"
WHERE
value_1 > 0 and value_1 < 4) AS t
ON (t.user_id = q.user_id)) as final_query
GROUP BY
types
ORDER BY
types;$$);
-- clear unnecessary tables;
DROP TABLE get_shardid_test_table1, get_shardid_test_table2, get_shardid_test_table3, get_shardid_test_table4, get_shardid_test_table5;
DROP TABLE get_shardid_test_table1, get_shardid_test_table2, get_shardid_test_table3, get_shardid_test_table4, get_shardid_test_table5, events_table_count;

View File

@ -262,6 +262,9 @@ ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id)
ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE SET DEFAULT;
ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id) REFERENCES referenced_table(id) ON UPDATE CASCADE;
-- test foreign constraint creation while adding the column
ALTER TABLE referencing_table ADD COLUMN referencing_col int REFERENCES referenced_table(id) ON UPDATE CASCADE;;
-- test foreign constraint creation with multiple subcommands
ALTER TABLE referencing_table ADD CONSTRAINT test_constraint FOREIGN KEY(ref_id) REFERENCES referenced_table(id),
ADD CONSTRAINT test_constraint FOREIGN KEY(id) REFERENCES referenced_table(test_column);

View File

@ -2104,6 +2104,22 @@ EXECUTE prepared_recursive_insert_select;
EXECUTE prepared_recursive_insert_select;
ROLLBACK;
-- upsert with on conflict update distribution column is unsupported
INSERT INTO agg_events AS ae
(
user_id,
value_1_agg,
agg_time
)
SELECT user_id,
value_1,
time
FROM raw_events_first
ON conflict (user_id, value_1_agg)
DO UPDATE
SET user_id = 42
RETURNING user_id, value_1_agg;
-- wrap in a transaction to improve performance
BEGIN;
DROP TABLE coerce_events;

View File

@ -138,8 +138,14 @@ ABORT;
SELECT * FROM citus_stat_statements_reset();
-- table owner should be the same on the shards, even when distributing the table as superuser
SET ROLE full_access;
CREATE TABLE my_table (id integer, val integer);
RESET ROLE;
SELECT create_distributed_table('my_table', 'id');
SELECT result FROM run_command_on_workers($$SELECT tableowner FROM pg_tables WHERE tablename LIKE 'my_table_%' LIMIT 1$$);
DROP TABLE my_table;
DROP TABLE test;
DROP USER full_access;
DROP USER read_access;

View File

@ -16,3 +16,8 @@ CREATE ROLE new_role;
CREATE USER new_user;
INSERT INTO pg_dist_authinfo VALUES (0, 'new_user', 'password=1234');
BEGIN;
INSERT INTO pg_dist_node VALUES (1234567890, 1234567890, 'localhost', 5432);
INSERT INTO pg_dist_poolinfo VALUES (1234567890, 'port=1234');
ROLLBACK;

View File

@ -11,13 +11,13 @@
#define CITUS_MAJORVERSION "7.5"
/* Citus version as a string */
#define CITUS_VERSION "7.5devel"
#define CITUS_VERSION "7.5.1"
/* Citus version as a number */
#define CITUS_VERSION_NUM 70500
/* A string containing the version number, platform, and C compiler */
#define CITUS_VERSION_STR "Citus 7.5devel on x86_64-windows, compiled by Visual Studio"
#define CITUS_VERSION_STR "Citus 7.5.1 on x86_64-windows, compiled by Visual Studio"
/* Define to 1 if you have the `curl' library (-lcurl). */
#define HAVE_LIBCURL 0