Merge pull request #5209 from citusdata/pg14_support

Add Pg14 support
pull/5238/head
SaitTalhaNisanci 2021-09-03 16:22:38 +03:00 committed by GitHub
commit 9f211eb874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
132 changed files with 15059 additions and 997 deletions

View File

@ -448,6 +448,10 @@ workflows:
name: build-13
pg_major: 13
image_tag: '13.4'
- build:
name: build-14
pg_major: 14
image_tag: '14beta3-dev202108191715'
- check-style
- check-sql-snapshots
@ -600,6 +604,80 @@ workflows:
make: check-failure
requires: [build-13]
- test-citus:
name: 'test-14_check-multi'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-multi
requires: [build-14]
- test-citus:
name: 'test-14_check-multi-1'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-multi-1
requires: [build-14]
- test-citus:
name: 'test-14_check-mx'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-multi-mx
requires: [build-14]
- test-citus:
name: 'test-14_check-vanilla'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-vanilla
requires: [build-14]
- test-citus:
name: 'test-14_check-isolation'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-isolation
requires: [build-14]
- test-citus:
name: 'test-14_check-worker'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-worker
requires: [build-14]
- test-citus:
name: 'test-14_check-operations'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-operations
requires: [build-14]
- test-citus:
name: 'test-14_check-follower-cluster'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-follower-cluster
requires: [build-14]
- test-citus:
name: 'test-14_check-columnar'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-columnar
requires: [build-14]
- test-citus:
name: 'test-14_check-columnar-isolation'
pg_major: 14
image_tag: '14beta3-dev202108191715'
make: check-columnar-isolation
requires: [build-14]
- tap-test-citus:
name: 'test_14_tap-recovery'
pg_major: 14
image_tag: '14beta3-dev202108191715'
suite: recovery
requires: [build-14]
- test-citus:
name: 'test-14_check-failure'
pg_major: 14
image: citus/failtester
image_tag: '14beta3-dev202108191715'
make: check-failure
requires: [build-14]
- test-pg-upgrade:
name: 'test-12-13_check-pg-upgrade'
old_pg_major: 12
@ -607,6 +685,20 @@ workflows:
image_tag: '12.8-13.4'
requires: [build-12,build-13]
- test-pg-upgrade:
name: 'test-12-14_check-pg-upgrade'
old_pg_major: 12
new_pg_major: 14
image_tag: '12-13-14-dev202108191715'
requires: [build-12,build-14]
- test-pg-upgrade:
name: 'test-13-14_check-pg-upgrade'
old_pg_major: 13
new_pg_major: 14
image_tag: '12-13-14-dev202108191715'
requires: [build-13,build-14]
- test-citus-upgrade:
name: test-12_check-citus-upgrade
pg_major: 12

1
.gitattributes vendored
View File

@ -30,6 +30,7 @@ src/backend/distributed/utils/pg11_snprintf.c -citus-style
src/backend/distributed/deparser/ruleutils_11.c -citus-style
src/backend/distributed/deparser/ruleutils_12.c -citus-style
src/backend/distributed/deparser/ruleutils_13.c -citus-style
src/backend/distributed/deparser/ruleutils_14.c -citus-style
src/backend/distributed/commands/index_pg_source.c -citus-style
src/include/distributed/citus_nodes.h -citus-style

2
configure vendored
View File

@ -2555,7 +2555,7 @@ if test -z "$version_num"; then
as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5
fi
if test "$version_num" != '12' -a "$version_num" != '13'; then
if test "$version_num" != '12' -a "$version_num" != '13' -a "$version_num" != '14'; then
as_fn_error $? "Citus is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5

View File

@ -74,7 +74,7 @@ if test -z "$version_num"; then
AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.])
fi
if test "$version_num" != '12' -a "$version_num" != '13'; then
if test "$version_num" != '12' -a "$version_num" != '13' -a "$version_num" != '14'; then
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
else
AC_MSG_NOTICE([building against PostgreSQL $version_num])

View File

@ -17,6 +17,7 @@
#include "catalog/pg_type.h"
#include "distributed/pg_version_constants.h"
#include "distributed/tuplestore.h"
#include "distributed/version_compat.h"
#include "miscadmin.h"
#include "storage/fd.h"
#include "storage/smgr.h"
@ -161,5 +162,5 @@ MemoryContextTotals(MemoryContext context, MemoryContextCounters *counters)
MemoryContextTotals(child, counters);
}
context->methods->stats(context, NULL, NULL, counters);
context->methods->stats_compat(context, NULL, NULL, counters, true);
}

View File

@ -64,6 +64,7 @@ typedef struct
{
Relation rel;
EState *estate;
ResultRelInfo *resultRelInfo;
} ModifyState;
/* RowNumberLookupMode to be used in StripeMetadataLookupRowNumber */
@ -1314,12 +1315,20 @@ StartModifyRelation(Relation rel)
{
EState *estate = create_estate_for_relation(rel);
#if PG_VERSION_NUM >= PG_VERSION_14
ResultRelInfo *resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel, 1, NULL, 0);
#else
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
#endif
/* ExecSimpleRelationInsert, ... require caller to open indexes */
ExecOpenIndices(estate->es_result_relation_info, false);
ExecOpenIndices(resultRelInfo, false);
ModifyState *modifyState = palloc(sizeof(ModifyState));
modifyState->rel = rel;
modifyState->estate = estate;
modifyState->resultRelInfo = resultRelInfo;
return modifyState;
}
@ -1341,7 +1350,7 @@ InsertTupleAndEnforceConstraints(ModifyState *state, Datum *values, bool *nulls)
ExecStoreHeapTuple(tuple, slot, false);
/* use ExecSimpleRelationInsert to enforce constraints */
ExecSimpleRelationInsert(state->estate, slot);
ExecSimpleRelationInsert_compat(state->resultRelInfo, state->estate, slot);
}
@ -1353,7 +1362,7 @@ static void
DeleteTupleAndEnforceConstraints(ModifyState *state, HeapTuple heapTuple)
{
EState *estate = state->estate;
ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
ResultRelInfo *resultRelInfo = state->resultRelInfo;
ItemPointer tid = &(heapTuple->t_self);
simple_heap_delete(state->rel, tid);
@ -1369,10 +1378,15 @@ DeleteTupleAndEnforceConstraints(ModifyState *state, HeapTuple heapTuple)
static void
FinishModifyRelation(ModifyState *state)
{
ExecCloseIndices(state->estate->es_result_relation_info);
ExecCloseIndices(state->resultRelInfo);
AfterTriggerEndQuery(state->estate);
#if PG_VERSION_NUM >= PG_VERSION_14
ExecCloseResultRelations(state->estate);
ExecCloseRangeTableRelations(state->estate);
#else
ExecCleanUpTriggerState(state->estate);
#endif
ExecResetTupleTable(state->estate->es_tupleTable, false);
FreeExecutorState(state->estate);
@ -1401,12 +1415,14 @@ create_estate_for_relation(Relation rel)
rte->rellockmode = AccessShareLock;
ExecInitRangeTable(estate, list_make1(rte));
#if PG_VERSION_NUM < PG_VERSION_14
ResultRelInfo *resultRelInfo = makeNode(ResultRelInfo);
InitResultRelInfo(resultRelInfo, rel, 1, NULL, 0);
estate->es_result_relations = resultRelInfo;
estate->es_num_result_relations = 1;
estate->es_result_relation_info = resultRelInfo;
#endif
estate->es_output_cid = GetCurrentCommandId(true);

View File

@ -118,6 +118,9 @@ static void ColumnarTableAMObjectAccessHook(ObjectAccessType access, Oid classId
void *arg);
static void ColumnarProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14
bool readOnlyTree,
#endif
ProcessUtilityContext context,
ParamListInfo params,
struct QueryEnvironment *queryEnv,
@ -634,6 +637,16 @@ columnar_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
}
#if PG_VERSION_NUM >= PG_VERSION_14
static TransactionId
columnar_index_delete_tuples(Relation rel,
TM_IndexDeleteOp *delstate)
{
elog(ERROR, "columnar_index_delete_tuples not implemented");
}
#else
static TransactionId
columnar_compute_xid_horizon_for_tuples(Relation rel,
ItemPointerData *tids,
@ -643,6 +656,9 @@ columnar_compute_xid_horizon_for_tuples(Relation rel,
}
#endif
static void
columnar_tuple_insert(Relation relation, TupleTableSlot *slot, CommandId cid,
int options, BulkInsertState bistate)
@ -953,7 +969,7 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
int elevel = (params->options & VACOPT_VERBOSE) ? INFO : DEBUG2;
/* this should have been resolved by vacuum.c until now */
Assert(params->truncate != VACOPT_TERNARY_DEFAULT);
Assert(params->truncate != VACOPTVALUE_UNSPECIFIED);
LogRelationStats(rel, elevel);
@ -961,7 +977,7 @@ columnar_vacuum_rel(Relation rel, VacuumParams *params,
* We don't have updates, deletes, or concurrent updates, so all we
* care for now is truncating the unused space at the end of storage.
*/
if (params->truncate == VACOPT_TERNARY_ENABLED)
if (params->truncate == VACOPTVALUE_ENABLED)
{
TruncateColumnar(rel, elevel);
}
@ -1290,7 +1306,8 @@ columnar_index_build_range_scan(Relation columnarRelation,
if (!IsBootstrapProcessingMode() && !indexInfo->ii_Concurrent)
{
/* ignore lazy VACUUM's */
OldestXmin = GetOldestXmin(columnarRelation, PROCARRAY_FLAGS_VACUUM);
OldestXmin = GetOldestNonRemovableTransactionId_compat(columnarRelation,
PROCARRAY_FLAGS_VACUUM);
}
Snapshot snapshot = { 0 };
@ -1636,8 +1653,8 @@ ColumnarReadMissingRowsIntoIndex(TableScanDesc scan, Relation indexRelation,
Relation columnarRelation = scan->rs_rd;
IndexUniqueCheck indexUniqueCheck =
indexInfo->ii_Unique ? UNIQUE_CHECK_YES : UNIQUE_CHECK_NO;
index_insert(indexRelation, indexValues, indexNulls, columnarItemPointer,
columnarRelation, indexUniqueCheck, indexInfo);
index_insert_compat(indexRelation, indexValues, indexNulls, columnarItemPointer,
columnarRelation, indexUniqueCheck, false, indexInfo);
validateIndexState->tups_inserted += 1;
}
@ -1993,12 +2010,22 @@ ColumnarTableAMObjectAccessHook(ObjectAccessType access, Oid classId, Oid object
static void
ColumnarProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14
bool readOnlyTree,
#endif
ProcessUtilityContext context,
ParamListInfo params,
struct QueryEnvironment *queryEnv,
DestReceiver *dest,
QueryCompletionCompat *completionTag)
{
#if PG_VERSION_NUM >= PG_VERSION_14
if (readOnlyTree)
{
pstmt = copyObject(pstmt);
}
#endif
Node *parsetree = pstmt->utilityStmt;
if (IsA(parsetree, IndexStmt))
@ -2021,8 +2048,8 @@ ColumnarProcessUtility(PlannedStmt *pstmt,
RelationClose(rel);
}
PrevProcessUtilityHook(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
PrevProcessUtilityHook_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
}
@ -2096,7 +2123,11 @@ static const TableAmRoutine columnar_am_methods = {
.tuple_get_latest_tid = columnar_get_latest_tid,
.tuple_tid_valid = columnar_tuple_tid_valid,
.tuple_satisfies_snapshot = columnar_tuple_satisfies_snapshot,
#if PG_VERSION_NUM >= PG_VERSION_14
.index_delete_tuples = columnar_index_delete_tuples,
#else
.compute_xid_horizon_for_tuples = columnar_compute_xid_horizon_for_tuples,
#endif
.tuple_insert = columnar_tuple_insert,
.tuple_insert_speculative = columnar_tuple_insert_speculative,

View File

@ -16,6 +16,7 @@
#include "access/tsmapi.h"
#if PG_VERSION_NUM >= 130000
#include "access/heaptoast.h"
#include "common/hashfn.h"
#else
#include "access/tuptoaster.h"
#endif
@ -132,9 +133,10 @@ columnar_init_write_state(Relation relation, TupleDesc tupdesc,
"Column Store Write State Management Context",
ALLOCSET_DEFAULT_SIZES);
HASHCTL info;
uint32 hashFlags = (HASH_ELEM | HASH_CONTEXT);
uint32 hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT);
memset(&info, 0, sizeof(info));
info.keysize = sizeof(Oid);
info.hash = oid_hash;
info.entrysize = sizeof(WriteStateMapEntry);
info.hcxt = WriteStateContext;

View File

@ -11,6 +11,9 @@
*/
#include "postgres.h"
#include "funcapi.h"
#include "distributed/pg_version_constants.h"
#include "catalog/pg_proc.h"
#include "commands/defrem.h"
@ -46,6 +49,9 @@
static bool CallFuncExprRemotely(CallStmt *callStmt,
DistObjectCacheEntry *procedure,
FuncExpr *funcExpr, DestReceiver *dest);
#if PG_VERSION_NUM >= PG_VERSION_14
static bool FunctionHasOutOnlyParameter(Oid functionOid);
#endif
/*
* CallDistributedProcedureRemotely calls a stored procedure on the worker if possible.
@ -142,12 +148,26 @@ CallFuncExprRemotely(CallStmt *callStmt, DistObjectCacheEntry *procedure,
return false;
}
#if PG_VERSION_NUM >= PG_VERSION_14
/*
* We might need to add outargs to the funcExpr->args so that they can
* be pushed down. We can implement in the future.
*/
if (FunctionHasOutOnlyParameter(funcExpr->funcid))
{
ereport(DEBUG1, (errmsg("not pushing down procedures with OUT parameters")));
return false;
}
#endif
ereport(DEBUG1, (errmsg("pushing down the procedure")));
/* build remote command with fully qualified names */
StringInfo callCommand = makeStringInfo();
appendStringInfo(callCommand, "CALL %s", pg_get_rule_expr((Node *) funcExpr));
appendStringInfo(callCommand, "CALL %s", pg_get_rule_expr((Node *) funcExpr));
{
Tuplestorestate *tupleStore = tuplestore_begin_heap(true, false, work_mem);
TupleDesc tupleDesc = CallStmtResultDesc(callStmt);
@ -207,3 +227,53 @@ CallFuncExprRemotely(CallStmt *callStmt, DistObjectCacheEntry *procedure,
return true;
}
#if PG_VERSION_NUM >= PG_VERSION_14
/*
* FunctionHasOutOnlyParameter is a helper function which takes
* a function Oid and returns true if the input function has at least
* one OUT parameter.
*/
static bool
FunctionHasOutOnlyParameter(Oid functionOid)
{
Oid *argTypes = NULL;
char **argNames = NULL;
char *argModes = NULL;
HeapTuple proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionOid));
if (!HeapTupleIsValid(proctup))
{
elog(ERROR, "cache lookup failed for function %u", functionOid);
}
int numberOfArgs = get_func_arg_info(proctup, &argTypes, &argNames, &argModes);
if (argModes == NULL)
{
/* short circuit, all arguments are IN */
ReleaseSysCache(proctup);
return false;
}
int argIndex = 0;
for (; argIndex < numberOfArgs; ++argIndex)
{
if (argModes[argIndex] == PROARGMODE_OUT)
{
ReleaseSysCache(proctup);
return true;
}
}
ReleaseSysCache(proctup);
return false;
}
#endif

View File

@ -251,7 +251,9 @@ GetDependencyCreateDDLCommands(const ObjectAddress *dependency)
*/
Assert(false);
ereport(ERROR, (errmsg("unsupported object %s for distribution by citus",
getObjectTypeDescription(dependency)),
getObjectTypeDescription_compat(dependency,
/* missingOk: */ false)),
errdetail(
"citus tries to recreate an unsupported object on its workers"),
errhint("please report a bug as this should not be happening")));

View File

@ -15,6 +15,7 @@
#include "distributed/commands.h"
#include "distributed/deparser.h"
#include "distributed/pg_version_constants.h"
#include "distributed/version_compat.h"
static DistributeObjectOps NoDistributeOps = {
.deparse = NULL,
@ -772,7 +773,7 @@ GetDistributeObjectOps(Node *node)
case T_AlterTableStmt:
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
switch (stmt->relkind)
switch (AlterTableStmtObjType_compat(stmt))
{
case OBJECT_TYPE:
{

View File

@ -1613,7 +1613,8 @@ PreprocessAlterFunctionDependsStmt(Node *node, const char *queryString,
* workers
*/
const char *functionName = getObjectIdentity(&address);
const char *functionName =
getObjectIdentity_compat(&address, /* missingOk: */ false);
ereport(ERROR, (errmsg("distrtibuted functions are not allowed to depend on an "
"extension"),
errdetail("Function \"%s\" is already distributed. Functions from "
@ -1807,8 +1808,8 @@ GenerateBackupNameForProcCollision(const ObjectAddress *address)
List *newProcName = list_make2(namespace, makeString(newName));
/* don't need to rename if the input arguments don't match */
FuncCandidateList clist = FuncnameGetCandidates(newProcName, numargs, NIL, false,
false, true);
FuncCandidateList clist = FuncnameGetCandidates_compat(newProcName, numargs, NIL,
false, false, false, true);
for (; clist; clist = clist->next)
{
if (memcmp(clist->args, argtypes, sizeof(Oid) * numargs) == 0)
@ -1932,8 +1933,10 @@ ErrorIfFunctionDependsOnExtension(const ObjectAddress *functionAddress)
if (IsObjectAddressOwnedByExtension(functionAddress, &extensionAddress))
{
char *functionName = getObjectIdentity(functionAddress);
char *extensionName = getObjectIdentity(&extensionAddress);
char *functionName =
getObjectIdentity_compat(functionAddress, /* missingOk: */ false);
char *extensionName =
getObjectIdentity_compat(&extensionAddress, /* missingOk: */ false);
ereport(ERROR, (errmsg("unable to create a distributed function from functions "
"owned by an extension"),
errdetail("Function \"%s\" has a dependency on extension \"%s\". "

View File

@ -18,6 +18,7 @@
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_class.h"
#include "commands/defrem.h"
#include "commands/tablecmds.h"
#include "distributed/citus_ruleutils.h"
#include "distributed/commands.h"
@ -528,8 +529,8 @@ PreprocessReindexStmt(Node *node, const char *reindexCommand,
{
Relation relation = NULL;
Oid relationId = InvalidOid;
LOCKMODE lockmode = reindexStatement->concurrent ? ShareUpdateExclusiveLock :
AccessExclusiveLock;
LOCKMODE lockmode = IsReindexWithParam_compat(reindexStatement, "concurrently") ?
ShareUpdateExclusiveLock : AccessExclusiveLock;
MemoryContext relationContext = NULL;
Assert(reindexStatement->kind == REINDEX_OBJECT_INDEX ||
@ -538,7 +539,8 @@ PreprocessReindexStmt(Node *node, const char *reindexCommand,
if (reindexStatement->kind == REINDEX_OBJECT_INDEX)
{
struct ReindexIndexCallbackState state;
state.concurrent = reindexStatement->concurrent;
state.concurrent = IsReindexWithParam_compat(reindexStatement,
"concurrently");
state.locked_table_oid = InvalidOid;
Oid indOid = RangeVarGetRelidExtended(reindexStatement->relation,
@ -589,8 +591,10 @@ PreprocessReindexStmt(Node *node, const char *reindexCommand,
{
DDLJob *ddlJob = palloc0(sizeof(DDLJob));
ddlJob->targetRelationId = relationId;
ddlJob->concurrentIndexCmd = reindexStatement->concurrent;
ddlJob->startNewTransaction = reindexStatement->concurrent;
ddlJob->concurrentIndexCmd = IsReindexWithParam_compat(reindexStatement,
"concurrently");
ddlJob->startNewTransaction = IsReindexWithParam_compat(reindexStatement,
"concurrently");
ddlJob->commandString = reindexCommand;
ddlJob->taskList = CreateReindexTaskList(relationId, reindexStatement);

View File

@ -209,13 +209,12 @@ DoLocalCopy(StringInfo buffer, Oid relationId, int64 shardId, CopyStmt *copyStat
Oid shardOid = GetTableLocalShardOid(relationId, shardId);
Relation shard = table_open(shardOid, RowExclusiveLock);
ParseState *pState = make_parsestate(NULL);
/* p_rtable of pState is set so that we can check constraints. */
pState->p_rtable = CreateRangeTable(shard, ACL_INSERT);
CopyState cstate = BeginCopyFrom(pState, shard, NULL, false,
ReadFromLocalBufferCallback,
copyStatement->attlist, copyStatement->options);
(void) addRangeTableEntryForRelation(pState, shard, AccessShareLock,
NULL, false, false);
CopyFromState cstate = BeginCopyFrom_compat(pState, shard, NULL, NULL, false,
ReadFromLocalBufferCallback,
copyStatement->attlist,
copyStatement->options);
CopyFrom(cstate);
EndCopyFrom(cstate);

View File

@ -50,6 +50,7 @@
#include "postgres.h"
#include "libpq-fe.h"
#include "miscadmin.h"
#include "pgstat.h"
#include <arpa/inet.h> /* for htons */
#include <netinet/in.h> /* for htons */
@ -67,6 +68,7 @@
#include "catalog/pg_type.h"
#include "commands/copy.h"
#include "commands/defrem.h"
#include "commands/progress.h"
#include "distributed/citus_safe_lib.h"
#include "distributed/commands/multi_copy.h"
#include "distributed/commands/utility_hook.h"
@ -267,7 +269,9 @@ static CopyCoercionData * ColumnCoercionPaths(TupleDesc destTupleDescriptor,
Oid *finalColumnTypeArray);
static FmgrInfo * TypeOutputFunctions(uint32 columnCount, Oid *typeIdArray,
bool binaryFormat);
#if PG_VERSION_NUM < PG_VERSION_14
static List * CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist);
#endif
static bool CopyStatementHasFormat(CopyStmt *copyStatement, char *formatName);
static void CitusCopyFrom(CopyStmt *copyStatement, QueryCompletionCompat *completionTag);
static HTAB * CreateConnectionStateHash(MemoryContext memoryContext);
@ -520,13 +524,14 @@ CopyToExistingShards(CopyStmt *copyStatement, QueryCompletionCompat *completionT
}
/* initialize copy state to read from COPY data source */
CopyState copyState = BeginCopyFrom(NULL,
copiedDistributedRelation,
copyStatement->filename,
copyStatement->is_program,
NULL,
copyStatement->attlist,
copyStatement->options);
CopyFromState copyState = BeginCopyFrom_compat(NULL,
copiedDistributedRelation,
NULL,
copyStatement->filename,
copyStatement->is_program,
NULL,
copyStatement->attlist,
copyStatement->options);
/* set up callback to identify error line number */
errorCallback.callback = CopyFromErrorCallback;
@ -556,7 +561,11 @@ CopyToExistingShards(CopyStmt *copyStatement, QueryCompletionCompat *completionT
dest->receiveSlot(tupleTableSlot, dest);
processedRowCount += 1;
++processedRowCount;
#if PG_VERSION_NUM >= PG_VERSION_14
pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED, processedRowCount);
#endif
}
EndCopyFrom(copyState);
@ -617,13 +626,14 @@ CopyToNewShards(CopyStmt *copyStatement, QueryCompletionCompat *completionTag, O
(ShardConnections *) palloc0(sizeof(ShardConnections));
/* initialize copy state to read from COPY data source */
CopyState copyState = BeginCopyFrom(NULL,
distributedRelation,
copyStatement->filename,
copyStatement->is_program,
NULL,
copyStatement->attlist,
copyStatement->options);
CopyFromState copyState = BeginCopyFrom_compat(NULL,
distributedRelation,
NULL,
copyStatement->filename,
copyStatement->is_program,
NULL,
copyStatement->attlist,
copyStatement->options);
CopyOutState copyOutState = (CopyOutState) palloc0(sizeof(CopyOutStateData));
copyOutState->delim = (char *) delimiterCharacter;
@ -736,6 +746,10 @@ CopyToNewShards(CopyStmt *copyStatement, QueryCompletionCompat *completionTag, O
}
processedRowCount += 1;
#if PG_VERSION_NUM >= PG_VERSION_14
pgstat_progress_update_param(PROGRESS_COPY_TUPLES_PROCESSED, processedRowCount);
#endif
}
/*
@ -1802,24 +1816,8 @@ CreateEmptyShard(char *relationName)
static void
SendCopyBegin(CopyOutState cstate)
{
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
{
/* new way */
StringInfoData buf;
int natts = list_length(cstate->attnumlist);
int16 format = (cstate->binary ? 1 : 0);
int i;
pq_beginmessage(&buf, 'H');
pq_sendbyte(&buf, format); /* overall format */
pq_sendint16(&buf, natts);
for (i = 0; i < natts; i++)
pq_sendint16(&buf, format); /* per-column formats */
pq_endmessage(&buf);
cstate->copy_dest = COPY_NEW_FE;
}
else
{
#if PG_VERSION_NUM < PG_VERSION_14
if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3) {
/* old way */
if (cstate->binary)
ereport(ERROR,
@ -1829,7 +1827,21 @@ SendCopyBegin(CopyOutState cstate)
/* grottiness needed for old COPY OUT protocol */
pq_startcopyout();
cstate->copy_dest = COPY_OLD_FE;
return;
}
#endif
StringInfoData buf;
int natts = list_length(cstate->attnumlist);
int16 format = (cstate->binary ? 1 : 0);
int i;
pq_beginmessage(&buf, 'H');
pq_sendbyte(&buf, format); /* overall format */
pq_sendint16(&buf, natts);
for (i = 0; i < natts; i++)
pq_sendint16(&buf, format); /* per-column formats */
pq_endmessage(&buf);
cstate->copy_dest = COPY_FRONTEND;
}
@ -1837,20 +1849,20 @@ SendCopyBegin(CopyOutState cstate)
static void
SendCopyEnd(CopyOutState cstate)
{
if (cstate->copy_dest == COPY_NEW_FE)
{
/* Shouldn't have any unsent data */
Assert(cstate->fe_msgbuf->len == 0);
/* Send Copy Done message */
pq_putemptymessage('c');
}
else
#if PG_VERSION_NUM < PG_VERSION_14
if (cstate->copy_dest != COPY_NEW_FE)
{
CopySendData(cstate, "\\.", 2);
/* Need to flush out the trailer (this also appends a newline) */
CopySendEndOfRow(cstate, true);
pq_endcopyout(false);
return;
}
#endif
/* Shouldn't have any unsent data */
Assert(cstate->fe_msgbuf->len == 0);
/* Send Copy Done message */
pq_putemptymessage('c');
}
@ -1904,6 +1916,7 @@ CopySendEndOfRow(CopyOutState cstate, bool includeEndOfLine)
switch (cstate->copy_dest)
{
#if PG_VERSION_NUM < PG_VERSION_14
case COPY_OLD_FE:
/* The FE/BE protocol uses \n as newline for all platforms */
if (!cstate->binary && includeEndOfLine)
@ -1917,7 +1930,8 @@ CopySendEndOfRow(CopyOutState cstate, bool includeEndOfLine)
errmsg("connection lost during COPY to stdout")));
}
break;
case COPY_NEW_FE:
#endif
case COPY_FRONTEND:
/* The FE/BE protocol uses \n as newline for all platforms */
if (!cstate->binary && includeEndOfLine)
CopySendChar(cstate, '\n');
@ -2979,6 +2993,13 @@ ProcessCopyStmt(CopyStmt *copyStatement, QueryCompletionCompat *completionTag, c
{
if (copyStatement->whereClause)
{
/*
* Update progress reporting for tuples progressed so that the
* progress is reflected on pg_stat_progress_copy. Citus currently
* does not support COPY .. WHERE clause so TUPLES_EXCLUDED is not
* handled. When we remove this check, we should implement progress
* reporting as well.
*/
ereport(ERROR, (errmsg(
"Citus does not support COPY FROM with WHERE")));
}
@ -3143,6 +3164,7 @@ CitusCopyTo(CopyStmt *copyStatement, QueryCompletionCompat *completionTag)
PQclear(result);
tuplesSent += ForwardCopyDataFromConnection(copyOutState, connection);
break;
}
@ -3275,6 +3297,8 @@ CreateRangeTable(Relation rel, AclMode requiredAccess)
}
#if PG_VERSION_NUM < PG_VERSION_14
/* Helper for CheckCopyPermissions(), copied from postgres */
static List *
CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
@ -3356,6 +3380,9 @@ CopyGetAttnums(TupleDesc tupDesc, Relation rel, List *attnamelist)
}
#endif
/*
* CreateConnectionStateHash constructs a hash table which maps from socket
* number to CopyConnectionState, passing the provided MemoryContext to

View File

@ -595,7 +595,7 @@ PreprocessAlterSequenceOwnerStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
ObjectAddress sequenceAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(&sequenceAddress))
@ -623,7 +623,7 @@ ObjectAddress
AlterSequenceOwnerStmtObjectAddress(Node *node, bool missing_ok)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
RangeVar *sequence = stmt->relation;
Oid seqOid = RangeVarGetRelid(sequence, NoLock, missing_ok);
@ -643,7 +643,7 @@ List *
PostprocessAlterSequenceOwnerStmt(Node *node, const char *queryString)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
ObjectAddress sequenceAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(&sequenceAddress))

View File

@ -442,8 +442,8 @@ GetExplicitStatisticsCommandList(Oid relationId)
foreach_oid(statisticsId, statisticsIdList)
{
/* we need create commands for already created stats before distribution */
char *createStatisticsCommand = pg_get_statisticsobj_worker(statisticsId,
false);
char *createStatisticsCommand = pg_get_statisticsobj_worker_compat(statisticsId,
false, false);
explicitStatisticsCommandList =
lappend(explicitStatisticsCommandList,

View File

@ -536,7 +536,7 @@ PreprocessAlterTableStmt(Node *node, const char *alterTableCommand,
if (get_rel_relkind(leftRelationId) == RELKIND_SEQUENCE)
{
AlterTableStmt *stmtCopy = copyObject(alterTableStatement);
stmtCopy->relkind = OBJECT_SEQUENCE;
AlterTableStmtObjType_compat(stmtCopy) = OBJECT_SEQUENCE;
return PreprocessAlterSequenceOwnerStmt((Node *) stmtCopy, alterTableCommand,
processUtilityContext);
}
@ -1629,7 +1629,7 @@ PostprocessAlterTableStmt(AlterTableStmt *alterTableStatement)
*/
if (get_rel_relkind(relationId) == RELKIND_SEQUENCE)
{
alterTableStatement->relkind = OBJECT_SEQUENCE;
AlterTableStmtObjType_compat(alterTableStatement) = OBJECT_SEQUENCE;
PostprocessAlterSequenceOwnerStmt((Node *) alterTableStatement, NULL);
return;
}
@ -2380,6 +2380,15 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
break;
}
#if PG_VERSION_NUM >= PG_VERSION_14
case AT_DetachPartitionFinalize:
{
ereport(ERROR, (errmsg("ALTER TABLE .. DETACH PARTITION .. FINALIZE "
"commands are currently unsupported.")));
break;
}
#endif
case AT_DetachPartition:
{
/* we only allow partitioning commands if they are only subcommand */
@ -2391,7 +2400,16 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
errhint("You can issue each subcommand "
"separately.")));
}
#if PG_VERSION_NUM >= PG_VERSION_14
PartitionCmd *partitionCommand = (PartitionCmd *) command->def;
if (partitionCommand->concurrent)
{
ereport(ERROR, (errmsg("ALTER TABLE .. DETACH PARTITION .. "
"CONCURRENTLY commands are currently "
"unsupported.")));
}
#endif
ErrorIfCitusLocalTablePartitionCommand(command, relationId);
break;
@ -2427,15 +2445,19 @@ ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement)
case AT_ReplicaIdentity:
case AT_ValidateConstraint:
case AT_DropConstraint: /* we do the check for invalidation in AlterTableDropsForeignKey */
{
/*
* We will not perform any special check for:
* ALTER TABLE .. ALTER COLUMN .. SET NOT NULL
* ALTER TABLE .. REPLICA IDENTITY ..
* ALTER TABLE .. VALIDATE CONSTRAINT ..
*/
break;
}
#if PG_VERSION_NUM >= PG_VERSION_14
case AT_SetCompression:
#endif
{
/*
* We will not perform any special check for:
* ALTER TABLE .. ALTER COLUMN .. SET NOT NULL
* ALTER TABLE .. REPLICA IDENTITY ..
* ALTER TABLE .. VALIDATE CONSTRAINT ..
* ALTER TABLE .. ALTER COLUMN .. SET COMPRESSION ..
*/
break;
}
case AT_SetRelOptions: /* SET (...) */
case AT_ResetRelOptions: /* RESET (...) */

View File

@ -245,7 +245,7 @@ static bool
ReceiveCopyData(StringInfo copyData)
{
bool copyDone = true;
const int unlimitedSize = 0;
const int unlimitedSize = PQ_LARGE_MESSAGE_LIMIT;
HOLD_CANCEL_INTERRUPTS();
pq_startmsgread();

View File

@ -206,7 +206,7 @@ PreprocessAlterTypeStmt(Node *node, const char *queryString,
ProcessUtilityContext processUtilityContext)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
ObjectAddress typeAddress = GetObjectAddressFromParseTree((Node *) stmt, false);
if (!ShouldPropagateObject(&typeAddress))
@ -789,7 +789,7 @@ ObjectAddress
AlterTypeStmtObjectAddress(Node *node, bool missing_ok)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
TypeName *typeName = MakeTypeNameFromRangeVar(stmt->relation);
Oid typeOid = LookupTypeNameOid(NULL, typeName, missing_ok);
@ -973,7 +973,8 @@ CreateTypeDDLCommandsIdempotent(const ObjectAddress *typeAddress)
/* add owner ship change so the creation command can be run as a different user */
const char *username = GetUserNameFromId(GetTypeOwner(typeAddress->objectId), false);
initStringInfo(&buf);
appendStringInfo(&buf, ALTER_TYPE_OWNER_COMMAND, getObjectIdentity(typeAddress),
appendStringInfo(&buf, ALTER_TYPE_OWNER_COMMAND,
getObjectIdentity_compat(typeAddress, false),
quote_identifier(username));
ddlCommands = lappend(ddlCommands, buf.data);

View File

@ -111,8 +111,8 @@ ProcessUtilityParseTree(Node *node, const char *queryString, ProcessUtilityConte
plannedStmt->commandType = CMD_UTILITY;
plannedStmt->utilityStmt = node;
ProcessUtility(plannedStmt, queryString, context, params, NULL, dest,
completionTag);
ProcessUtility_compat(plannedStmt, queryString, false, context, params, NULL, dest,
completionTag);
}
@ -128,13 +128,25 @@ ProcessUtilityParseTree(Node *node, const char *queryString, ProcessUtilityConte
void
multi_ProcessUtility(PlannedStmt *pstmt,
const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14
bool readOnlyTree,
#endif
ProcessUtilityContext context,
ParamListInfo params,
struct QueryEnvironment *queryEnv,
DestReceiver *dest,
QueryCompletionCompat *completionTag)
{
Node *parsetree = pstmt->utilityStmt;
Node *parsetree;
#if PG_VERSION_NUM >= PG_VERSION_14
if (readOnlyTree)
{
pstmt = copyObject(pstmt);
}
#endif
parsetree = pstmt->utilityStmt;
if (IsA(parsetree, TransactionStmt) ||
IsA(parsetree, LockStmt) ||
@ -154,8 +166,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
* that state. Since we never need to intercept transaction statements,
* skip our checks and immediately fall into standard_ProcessUtility.
*/
standard_ProcessUtility(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
return;
}
@ -173,8 +185,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
* Ensure that utility commands do not behave any differently until CREATE
* EXTENSION is invoked.
*/
standard_ProcessUtility(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
return;
}
@ -205,8 +217,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
PG_TRY();
{
standard_ProcessUtility(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
StoredProcedureLevel -= 1;
}
@ -229,8 +241,8 @@ multi_ProcessUtility(PlannedStmt *pstmt,
PG_TRY();
{
standard_ProcessUtility(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
DoBlockLevel -= 1;
}
@ -484,8 +496,8 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
if (IsA(parsetree, AlterTableStmt))
{
AlterTableStmt *alterTableStmt = (AlterTableStmt *) parsetree;
if (alterTableStmt->relkind == OBJECT_TABLE ||
alterTableStmt->relkind == OBJECT_FOREIGN_TABLE)
if (AlterTableStmtObjType_compat(alterTableStmt) == OBJECT_TABLE ||
AlterTableStmtObjType_compat(alterTableStmt) == OBJECT_FOREIGN_TABLE)
{
ErrorIfAlterDropsPartitionColumn(alterTableStmt);
@ -566,8 +578,8 @@ ProcessUtilityInternal(PlannedStmt *pstmt,
citusCanBeUpdatedToAvailableVersion = !InstalledAndAvailableVersionsSame();
}
standard_ProcessUtility(pstmt, queryString, context,
params, queryEnv, dest, completionTag);
standard_ProcessUtility_compat(pstmt, queryString, false, context,
params, queryEnv, dest, completionTag);
/*
* if we are running ALTER EXTENSION citus UPDATE (to "<version>") command, we may need

View File

@ -39,8 +39,8 @@
typedef struct CitusVacuumParams
{
int options;
VacOptTernaryValue truncate;
VacOptTernaryValue index_cleanup;
VacOptValue truncate;
VacOptValue index_cleanup;
#if PG_VERSION_NUM >= PG_VERSION_13
int nworkers;
@ -346,8 +346,8 @@ DeparseVacuumStmtPrefix(CitusVacuumParams vacuumParams)
/* if no flags remain, exit early */
if (vacuumFlags == 0 &&
vacuumParams.truncate == VACOPT_TERNARY_DEFAULT &&
vacuumParams.index_cleanup == VACOPT_TERNARY_DEFAULT
vacuumParams.truncate == VACOPTVALUE_UNSPECIFIED &&
vacuumParams.index_cleanup == VACOPTVALUE_UNSPECIFIED
#if PG_VERSION_NUM >= PG_VERSION_13
&& vacuumParams.nworkers == VACUUM_PARALLEL_NOTSET
#endif
@ -388,19 +388,24 @@ DeparseVacuumStmtPrefix(CitusVacuumParams vacuumParams)
{
appendStringInfoString(vacuumPrefix, "SKIP_LOCKED,");
}
if (vacuumParams.truncate != VACOPT_TERNARY_DEFAULT)
#if PG_VERSION_NUM >= PG_VERSION_14
if (vacuumFlags & VACOPT_PROCESS_TOAST)
{
appendStringInfoString(vacuumPrefix, "PROCESS_TOAST,");
}
#endif
if (vacuumParams.truncate != VACOPTVALUE_UNSPECIFIED)
{
appendStringInfoString(vacuumPrefix,
vacuumParams.truncate == VACOPT_TERNARY_ENABLED ?
vacuumParams.truncate == VACOPTVALUE_ENABLED ?
"TRUNCATE," : "TRUNCATE false,"
);
}
if (vacuumParams.index_cleanup != VACOPT_TERNARY_DEFAULT)
if (vacuumParams.index_cleanup != VACOPTVALUE_UNSPECIFIED)
{
appendStringInfoString(vacuumPrefix,
vacuumParams.index_cleanup == VACOPT_TERNARY_ENABLED ?
vacuumParams.index_cleanup == VACOPTVALUE_ENABLED ?
"INDEX_CLEANUP," : "INDEX_CLEANUP false,"
);
}
@ -504,10 +509,13 @@ VacuumStmtParams(VacuumStmt *vacstmt)
bool freeze = false;
bool full = false;
bool disable_page_skipping = false;
#if PG_VERSION_NUM >= PG_VERSION_14
bool process_toast = false;
#endif
/* Set default value */
params.index_cleanup = VACOPT_TERNARY_DEFAULT;
params.truncate = VACOPT_TERNARY_DEFAULT;
params.index_cleanup = VACOPTVALUE_UNSPECIFIED;
params.truncate = VACOPTVALUE_UNSPECIFIED;
#if PG_VERSION_NUM >= PG_VERSION_13
params.nworkers = VACUUM_PARALLEL_NOTSET;
#endif
@ -549,15 +557,21 @@ VacuumStmtParams(VacuumStmt *vacstmt)
{
disable_page_skipping = defGetBoolean(opt);
}
#if PG_VERSION_NUM >= PG_VERSION_14
else if (strcmp(opt->defname, "process_toast") == 0)
{
process_toast = defGetBoolean(opt);
}
#endif
else if (strcmp(opt->defname, "index_cleanup") == 0)
{
params.index_cleanup = defGetBoolean(opt) ? VACOPT_TERNARY_ENABLED :
VACOPT_TERNARY_DISABLED;
params.index_cleanup = defGetBoolean(opt) ? VACOPTVALUE_ENABLED :
VACOPTVALUE_DISABLED;
}
else if (strcmp(opt->defname, "truncate") == 0)
{
params.truncate = defGetBoolean(opt) ? VACOPT_TERNARY_ENABLED :
VACOPT_TERNARY_DISABLED;
params.truncate = defGetBoolean(opt) ? VACOPTVALUE_ENABLED :
VACOPTVALUE_DISABLED;
}
#if PG_VERSION_NUM >= PG_VERSION_13
else if (strcmp(opt->defname, "parallel") == 0)
@ -599,6 +613,9 @@ VacuumStmtParams(VacuumStmt *vacstmt)
(analyze ? VACOPT_ANALYZE : 0) |
(freeze ? VACOPT_FREEZE : 0) |
(full ? VACOPT_FULL : 0) |
#if PG_VERSION_NUM >= PG_VERSION_14
(process_toast ? VACOPT_PROCESS_TOAST : 0) |
#endif
(disable_page_skipping ? VACOPT_DISABLE_PAGE_SKIPPING : 0);
return params;
}

View File

@ -22,6 +22,9 @@
#include "access/skey.h"
#include "access/stratnum.h"
#include "access/sysattr.h"
#if PG_VERSION_NUM >= PG_VERSION_14
#include "access/toast_compression.h"
#endif
#include "access/tupdesc.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
@ -39,6 +42,7 @@
#include "commands/defrem.h"
#include "commands/extension.h"
#include "distributed/citus_ruleutils.h"
#include "distributed/commands.h"
#include "distributed/listutils.h"
#include "distributed/multi_partitioning_utils.h"
#include "distributed/metadata_cache.h"
@ -77,6 +81,7 @@ static void AppendStorageParametersToString(StringInfo stringBuffer,
List *optionList);
static void simple_quote_literal(StringInfo buf, const char *val);
static char * flatten_reloptions(Oid relid);
static void AddVacuumParams(ReindexStmt *reindexStmt, StringInfo buffer);
/*
@ -380,6 +385,14 @@ pg_get_tableschemadef_string(Oid tableRelationId, bool includeSequenceDefaults,
appendStringInfoString(&buffer, " NOT NULL");
}
#if PG_VERSION_NUM >= PG_VERSION_14
if (CompressionMethodIsValid(attributeForm->attcompression))
{
appendStringInfo(&buffer, " COMPRESSION %s",
GetCompressionMethodName(attributeForm->attcompression));
}
#endif
if (attributeForm->attcollation != InvalidOid &&
attributeForm->attcollation != DEFAULT_COLLATION_OID)
{
@ -740,7 +753,8 @@ deparse_shard_reindex_statement(ReindexStmt *origStmt, Oid distrelid, int64 shar
{
ReindexStmt *reindexStmt = copyObject(origStmt); /* copy to avoid modifications */
char *relationName = NULL;
const char *concurrentlyString = reindexStmt->concurrent ? "CONCURRENTLY " : "";
const char *concurrentlyString =
IsReindexWithParam_compat(reindexStmt, "concurrently") ? "CONCURRENTLY " : "";
if (reindexStmt->kind == REINDEX_OBJECT_INDEX ||
@ -753,11 +767,7 @@ deparse_shard_reindex_statement(ReindexStmt *origStmt, Oid distrelid, int64 shar
}
appendStringInfoString(buffer, "REINDEX ");
if (reindexStmt->options == REINDEXOPT_VERBOSE)
{
appendStringInfoString(buffer, "(VERBOSE) ");
}
AddVacuumParams(reindexStmt, buffer);
switch (reindexStmt->kind)
{
@ -801,6 +811,80 @@ deparse_shard_reindex_statement(ReindexStmt *origStmt, Oid distrelid, int64 shar
}
/*
* IsReindexWithParam_compat returns true if the given parameter
* exists for the given reindexStmt.
*/
bool
IsReindexWithParam_compat(ReindexStmt *reindexStmt, char *param)
{
#if PG_VERSION_NUM < PG_VERSION_14
if (strcmp(param, "concurrently") == 0)
{
return reindexStmt->concurrent;
}
else if (strcmp(param, "verbose") == 0)
{
return reindexStmt->options & REINDEXOPT_VERBOSE;
}
return false;
#else
DefElem *opt = NULL;
foreach_ptr(opt, reindexStmt->params)
{
if (strcmp(opt->defname, param) == 0)
{
return defGetBoolean(opt);
}
}
return false;
#endif
}
/*
* AddVacuumParams adds vacuum params to the given buffer.
*/
static void
AddVacuumParams(ReindexStmt *reindexStmt, StringInfo buffer)
{
StringInfo temp = makeStringInfo();
if (IsReindexWithParam_compat(reindexStmt, "verbose"))
{
appendStringInfoString(temp, "VERBOSE");
}
#if PG_VERSION_NUM >= PG_VERSION_14
char *tableSpaceName = NULL;
DefElem *opt = NULL;
foreach_ptr(opt, reindexStmt->params)
{
if (strcmp(opt->defname, "tablespace") == 0)
{
tableSpaceName = defGetString(opt);
break;
}
}
if (tableSpaceName)
{
if (temp->len > 0)
{
appendStringInfo(temp, ", TABLESPACE %s", tableSpaceName);
}
else
{
appendStringInfo(temp, "TABLESPACE %s", tableSpaceName);
}
}
#endif
if (temp->len > 0)
{
appendStringInfo(buffer, "(%s) ", temp->data);
}
}
/* deparse_index_columns appends index or include parameters to the provided buffer */
static void
deparse_index_columns(StringInfo buffer, List *indexParameterList, List *deparseContext)
@ -1020,7 +1104,7 @@ contain_nextval_expression_walker(Node *node, void *context)
{
FuncExpr *funcExpr = (FuncExpr *) node;
if (funcExpr->funcid == F_NEXTVAL_OID)
if (funcExpr->funcid == F_NEXTVAL)
{
return true;
}
@ -1196,6 +1280,8 @@ simple_quote_literal(StringInfo buf, const char *val)
*
* CURRENT_USER - resolved to the user name of the current role being used
* SESSION_USER - resolved to the user name of the user that opened the session
* CURRENT_ROLE - same as CURRENT_USER, resolved to the user name of the current role being used
* Postgres treats CURRENT_ROLE is equivalent to CURRENT_USER, and we follow the same approach.
*
* withQuoteIdentifier is used, because if the results will be used in a query the quotes are needed but if not there
* should not be extra quotes.
@ -1212,6 +1298,9 @@ RoleSpecString(RoleSpec *spec, bool withQuoteIdentifier)
spec->rolename;
}
#if PG_VERSION_NUM >= PG_VERSION_14
case ROLESPEC_CURRENT_ROLE:
#endif
case ROLESPEC_CURRENT_USER:
{
return withQuoteIdentifier ?

View File

@ -15,6 +15,7 @@
#include "catalog/namespace.h"
#include "distributed/deparser.h"
#include "distributed/version_compat.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
@ -193,7 +194,7 @@ DeparseAlterSequenceOwnerStmt(Node *node)
StringInfoData str = { 0 };
initStringInfo(&str);
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
AppendAlterSequenceOwnerStmt(&str, stmt);
@ -208,7 +209,7 @@ DeparseAlterSequenceOwnerStmt(Node *node)
static void
AppendAlterSequenceOwnerStmt(StringInfo buf, AlterTableStmt *stmt)
{
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
RangeVar *seq = stmt->relation;
char *qualifiedSequenceName = quote_qualified_identifier(seq->schemaname,
seq->relname);

View File

@ -12,6 +12,8 @@
*/
#include "postgres.h"
#include "distributed/pg_version_constants.h"
#include "distributed/citus_ruleutils.h"
#include "distributed/deparser.h"
#include "distributed/listutils.h"
@ -232,6 +234,35 @@ AppendStatTypes(StringInfo buf, CreateStatsStmt *stmt)
}
#if PG_VERSION_NUM >= PG_VERSION_14
static void
AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt)
{
StatsElem *column = NULL;
foreach_ptr(column, stmt->exprs)
{
if (!column->name)
{
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg(
"only simple column references are allowed in CREATE STATISTICS")));
}
const char *columnName = quote_identifier(column->name);
appendStringInfoString(buf, columnName);
if (column != llast(stmt->exprs))
{
appendStringInfoString(buf, ", ");
}
}
}
#else
static void
AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt)
{
@ -259,6 +290,8 @@ AppendColumnNames(StringInfo buf, CreateStatsStmt *stmt)
}
#endif
static void
AppendTableName(StringInfo buf, CreateStatsStmt *stmt)
{

View File

@ -12,6 +12,7 @@
#include "postgres.h"
#include "distributed/deparser.h"
#include "distributed/version_compat.h"
#include "nodes/nodes.h"
#include "nodes/parsenodes.h"
#include "parser/parse_type.h"
@ -63,7 +64,7 @@ DeparseAlterTableStmt(Node *node)
StringInfoData str = { 0 };
initStringInfo(&str);
Assert(stmt->relkind == OBJECT_TABLE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TABLE);
AppendAlterTableStmt(&str, stmt);
return str.data;
@ -82,7 +83,7 @@ AppendAlterTableStmt(StringInfo buf, AlterTableStmt *stmt)
stmt->relation->relname);
ListCell *cmdCell = NULL;
Assert(stmt->relkind == OBJECT_TABLE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TABLE);
appendStringInfo(buf, "ALTER TABLE %s", identifier);
foreach(cmdCell, stmt->cmds)

View File

@ -26,6 +26,7 @@
#include "distributed/citus_ruleutils.h"
#include "distributed/commands.h"
#include "distributed/deparser.h"
#include "distributed/version_compat.h"
#define AlterEnumIsRename(stmt) (stmt->oldVal != NULL)
#define AlterEnumIsAddValue(stmt) (stmt->oldVal == NULL)
@ -121,7 +122,7 @@ DeparseAlterTypeStmt(Node *node)
StringInfoData str = { 0 };
initStringInfo(&str);
Assert(stmt->relkind == OBJECT_TYPE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
AppendAlterTypeStmt(&str, stmt);
@ -136,7 +137,7 @@ AppendAlterTypeStmt(StringInfo buf, AlterTableStmt *stmt)
stmt->relation->relname);
ListCell *cmdCell = NULL;
Assert(stmt->relkind == OBJECT_TYPE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
appendStringInfo(buf, "ALTER TYPE %s", identifier);
foreach(cmdCell, stmt->cmds)

View File

@ -18,6 +18,7 @@
#include "postgres.h"
#include "distributed/deparser.h"
#include "distributed/version_compat.h"
#include "parser/parse_func.h"
#include "utils/lsyscache.h"
@ -31,7 +32,7 @@ void
QualifyAlterSequenceOwnerStmt(Node *node)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_SEQUENCE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_SEQUENCE);
RangeVar *seq = stmt->relation;

View File

@ -25,6 +25,7 @@
#include "catalog/pg_type.h"
#include "distributed/commands.h"
#include "distributed/deparser.h"
#include "distributed/version_compat.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "utils/syscache.h"
@ -125,7 +126,7 @@ void
QualifyAlterTypeStmt(Node *node)
{
AlterTableStmt *stmt = castNode(AlterTableStmt, node);
Assert(stmt->relkind == OBJECT_TYPE);
Assert(AlterTableStmtObjType_compat(stmt) == OBJECT_TYPE);
if (stmt->relation->schemaname == NULL)
{

File diff suppressed because it is too large Load Diff

View File

@ -410,8 +410,9 @@ ReadFileIntoTupleStore(char *fileName, char *copyFormat, TupleDesc tupleDescript
location);
copyOptions = lappend(copyOptions, copyOption);
CopyState copyState = BeginCopyFrom(NULL, stubRelation, fileName, false, NULL,
NULL, copyOptions);
CopyFromState copyState = BeginCopyFrom_compat(NULL, stubRelation, NULL,
fileName, false, NULL,
NULL, copyOptions);
while (true)
{

View File

@ -75,8 +75,12 @@ citus_unmark_object_distributed(PG_FUNCTION_ARGS)
{
ereport(ERROR, (errmsg("object still exists"),
errdetail("the %s \"%s\" still exists",
getObjectTypeDescription(&address),
getObjectIdentity(&address)),
getObjectTypeDescription_compat(&address,
/* missingOk: */ false),
getObjectIdentity_compat(&address,
/* missingOk: */ false)),
errhint("drop the object via a DROP command")));
}

View File

@ -688,6 +688,7 @@ ShardsMatchingDeleteCriteria(Oid relationId, List *shardIntervalList,
Assert(deleteCriteria != NULL);
List *deleteCriteriaList = list_make1(deleteCriteria);
/* walk over shard list and check if shards can be dropped */
ShardInterval *shardInterval = NULL;
foreach_ptr(shardInterval, shardIntervalList)
@ -703,9 +704,17 @@ ShardsMatchingDeleteCriteria(Oid relationId, List *shardIntervalList,
Expr *lessThanExpr = (Expr *) linitial(andExpr->args);
Expr *greaterThanExpr = (Expr *) lsecond(andExpr->args);
RestrictInfo *lessThanRestrictInfo = make_simple_restrictinfo(lessThanExpr);
RestrictInfo *greaterThanRestrictInfo = make_simple_restrictinfo(
greaterThanExpr);
/*
* passing NULL for plannerInfo will be problematic if we have placeholder
* vars. However, it won't be the case here because we are building
* the expression from shard intervals which don't have placeholder vars.
* Note that this is only the case with PG14 as the parameter doesn't exist
* prior to that.
*/
RestrictInfo *lessThanRestrictInfo = make_simple_restrictinfo_compat(NULL,
lessThanExpr);
RestrictInfo *greaterThanRestrictInfo = make_simple_restrictinfo_compat(NULL,
greaterThanExpr);
restrictInfoList = lappend(restrictInfoList, lessThanRestrictInfo);
restrictInfoList = lappend(restrictInfoList, greaterThanRestrictInfo);

View File

@ -747,7 +747,16 @@ RouterModifyTaskForShardInterval(Query *originalQuery,
continue;
}
shardRestrictionList = make_simple_restrictinfo((Expr *) shardOpExpressions);
/*
* passing NULL for plannerInfo will be problematic if we have placeholder
* vars. However, it won't be the case here because we are building
* the expression from shard intervals which don't have placeholder vars.
* Note that this is only the case with PG14 as the parameter doesn't exist
* prior to that.
*/
shardRestrictionList = make_simple_restrictinfo_compat(NULL,
(Expr *) shardOpExpressions);
extendedBaseRestrictInfo = lappend(extendedBaseRestrictInfo,
shardRestrictionList);

View File

@ -11,6 +11,8 @@
#include "libpq-fe.h"
#include "miscadmin.h"
#include "distributed/pg_version_constants.h"
#include "access/htup_details.h"
#include "access/xact.h"
#include "catalog/namespace.h"
@ -251,7 +253,13 @@ NonPushableInsertSelectExplainScan(CustomScanState *node, List *ancestors,
/* explain the inner SELECT query */
IntoClause *into = NULL;
ParamListInfo params = NULL;
char *queryString = NULL;
/*
* With PG14, we need to provide a string here,
* for now we put an empty string, which is valid according to postgres.
*/
char *queryString = pstrdup("");
ExplainOneQuery(queryCopy, 0, into, es, queryString, params, NULL);
ExplainCloseGroup("Select Query", "Select Query", false, es);
@ -278,7 +286,12 @@ ExplainSubPlans(DistributedPlan *distributedPlan, ExplainState *es)
PlannedStmt *plan = subPlan->plan;
IntoClause *into = NULL;
ParamListInfo params = NULL;
char *queryString = NULL;
/*
* With PG14, we need to provide a string here,
* for now we put an empty string, which is valid according to postgres.
*/
char *queryString = pstrdup("");
instr_time planduration;
#if PG_VERSION_NUM >= PG_VERSION_13
@ -1024,8 +1037,8 @@ worker_save_query_explain_analyze(PG_FUNCTION_ARGS)
TupleDesc tupleDescriptor = NULL;
Tuplestorestate *tupleStore = SetupTuplestore(fcinfo, &tupleDescriptor);
DestReceiver *tupleStoreDest = CreateTuplestoreDestReceiver();
SetTuplestoreDestReceiverParams(tupleStoreDest, tupleStore,
CurrentMemoryContext, false);
SetTuplestoreDestReceiverParams_compat(tupleStoreDest, tupleStore,
CurrentMemoryContext, false, NULL, NULL);
List *parseTreeList = pg_parse_query(queryString);
if (list_length(parseTreeList) != 1)
@ -1241,10 +1254,8 @@ CitusExplainOneQuery(Query *query, int cursorOptions, IntoClause *into,
/* plan the query */
PlannedStmt *plan = pg_plan_query_compat(query, NULL, cursorOptions, params);
INSTR_TIME_SET_CURRENT(planduration);
INSTR_TIME_SUBTRACT(planduration, planstart);
#if PG_VERSION_NUM >= PG_VERSION_13
/* calc differences of buffer counters. */

View File

@ -1847,7 +1847,11 @@ MasterAggregateExpression(Aggref *originalAggregate,
{
/* array_cat_agg() takes anyarray as input */
catAggregateName = ARRAY_CAT_AGGREGATE_NAME;
#if PG_VERSION_NUM >= PG_VERSION_14
catInputType = ANYCOMPATIBLEARRAYOID;
#else
catInputType = ANYARRAYOID;
#endif
}
else if (aggregateType == AGGREGATE_JSONB_AGG ||
aggregateType == AGGREGATE_JSONB_OBJECT_AGG)
@ -1882,7 +1886,26 @@ MasterAggregateExpression(Aggref *originalAggregate,
newMasterAggregate->args = list_make1(catAggArgument);
newMasterAggregate->aggfilter = NULL;
newMasterAggregate->aggtranstype = InvalidOid;
newMasterAggregate->aggargtypes = list_make1_oid(ANYARRAYOID);
if (aggregateType == AGGREGATE_ARRAY_AGG)
{
#if PG_VERSION_NUM >= PG_VERSION_14
/*
* Postgres expects the type of the array here such as INT4ARRAYOID.
* Hence we set it to workerReturnType. If we set this to
* ANYCOMPATIBLEARRAYOID then we will get the following error:
* "argument declared anycompatiblearray is not an array but type anycompatiblearray"
*/
newMasterAggregate->aggargtypes = list_make1_oid(workerReturnType);
#else
newMasterAggregate->aggargtypes = list_make1_oid(ANYARRAYOID);
#endif
}
else
{
newMasterAggregate->aggargtypes = list_make1_oid(ANYARRAYOID);
}
newMasterAggregate->aggsplit = AGGSPLIT_SIMPLE;
newMasterExpression = (Expr *) newMasterAggregate;
@ -3585,8 +3608,8 @@ static Oid
CitusFunctionOidWithSignature(char *functionName, int numargs, Oid *argtypes)
{
List *aggregateName = list_make2(makeString("pg_catalog"), makeString(functionName));
FuncCandidateList clist = FuncnameGetCandidates(aggregateName, numargs, NIL, false,
false, true);
FuncCandidateList clist = FuncnameGetCandidates_compat(aggregateName, numargs, NIL,
false, false, false, true);
for (; clist; clist = clist->next)
{

View File

@ -2054,7 +2054,8 @@ GetRestrictInfoListForRelation(RangeTblEntry *rangeTblEntry,
* If the restriction involves multiple tables, we cannot add it to
* input relation's expression list.
*/
Relids varnos = pull_varnos((Node *) restrictionClause);
Relids varnos = pull_varnos_compat(relationRestriction->plannerInfo,
(Node *) restrictionClause);
if (bms_num_members(varnos) != 1)
{
continue;

View File

@ -28,3 +28,5 @@ CREATE FUNCTION pg_catalog.citus_drop_all_shards(logicalrelid regclass,
COMMENT ON FUNCTION pg_catalog.citus_drop_all_shards(regclass, text, text, boolean)
IS 'drop all shards in a relation and update metadata';
#include "udfs/citus_drop_trigger/10.2-1.sql";
#include "udfs/citus_prepare_pg_upgrade/10.2-1.sql"
#include "udfs/citus_finish_pg_upgrade/10.2-1.sql"

View File

@ -320,9 +320,23 @@ CREATE TRIGGER dist_shard_cache_invalidate
-- Citus aggregates
DO $proc$
BEGIN
IF substring(current_Setting('server_version'), '\d+')::int >= 14 THEN
EXECUTE $$
CREATE AGGREGATE array_cat_agg(anycompatiblearray) (SFUNC = array_cat, STYPE = anycompatiblearray);
COMMENT ON AGGREGATE array_cat_agg(anycompatiblearray)
IS 'concatenate input arrays into a single array';
$$;
ELSE
EXECUTE $$
CREATE AGGREGATE array_cat_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray);
COMMENT ON AGGREGATE array_cat_agg(anyarray)
IS 'concatenate input arrays into a single array';
$$;
END IF;
END$proc$;
GRANT SELECT ON pg_catalog.pg_dist_partition TO public;
GRANT SELECT ON pg_catalog.pg_dist_shard TO public;

View File

@ -0,0 +1,141 @@
CREATE OR REPLACE FUNCTION pg_catalog.citus_finish_pg_upgrade()
RETURNS void
LANGUAGE plpgsql
SET search_path = pg_catalog
AS $cppu$
DECLARE
table_name regclass;
command text;
trigger_name text;
BEGIN
IF substring(current_Setting('server_version'), '\d+')::int >= 14 THEN
EXECUTE $cmd$
CREATE AGGREGATE array_cat_agg(anycompatiblearray) (SFUNC = array_cat, STYPE = anycompatiblearray);
COMMENT ON AGGREGATE array_cat_agg(anycompatiblearray)
IS 'concatenate input arrays into a single array';
$cmd$;
ELSE
EXECUTE $cmd$
CREATE AGGREGATE array_cat_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray);
COMMENT ON AGGREGATE array_cat_agg(anyarray)
IS 'concatenate input arrays into a single array';
$cmd$;
END IF;
/*
* Citus creates the array_cat_agg but because of a compatibility
* issue between pg13-pg14, we drop and create it during upgrade.
* And as Citus creates it, there needs to be a dependency to the
* Citus extension, so we create that dependency here.
* We are not using:
* ALTER EXENSION citus DROP/CREATE AGGREGATE array_cat_agg
* because we don't have an easy way to check if the aggregate
* exists with anyarray type or anycompatiblearray type.
*/
INSERT INTO pg_depend
SELECT
'pg_proc'::regclass::oid as classid,
(SELECT oid FROM pg_proc WHERE proname = 'array_cat_agg') as objid,
0 as objsubid,
'pg_extension'::regclass::oid as refclassid,
(select oid from pg_extension where extname = 'citus') as refobjid,
0 as refobjsubid ,
'e' as deptype;
--
-- restore citus catalog tables
--
INSERT INTO pg_catalog.pg_dist_partition SELECT * FROM public.pg_dist_partition;
INSERT INTO pg_catalog.pg_dist_shard SELECT * FROM public.pg_dist_shard;
INSERT INTO pg_catalog.pg_dist_placement SELECT * FROM public.pg_dist_placement;
INSERT INTO pg_catalog.pg_dist_node_metadata SELECT * FROM public.pg_dist_node_metadata;
INSERT INTO pg_catalog.pg_dist_node SELECT * FROM public.pg_dist_node;
INSERT INTO pg_catalog.pg_dist_local_group SELECT * FROM public.pg_dist_local_group;
INSERT INTO pg_catalog.pg_dist_transaction SELECT * FROM public.pg_dist_transaction;
INSERT INTO pg_catalog.pg_dist_colocation SELECT * FROM public.pg_dist_colocation;
-- enterprise catalog tables
INSERT INTO pg_catalog.pg_dist_authinfo SELECT * FROM public.pg_dist_authinfo;
INSERT INTO pg_catalog.pg_dist_poolinfo SELECT * FROM public.pg_dist_poolinfo;
INSERT INTO pg_catalog.pg_dist_rebalance_strategy SELECT
name,
default_strategy,
shard_cost_function::regprocedure::regproc,
node_capacity_function::regprocedure::regproc,
shard_allowed_on_node_function::regprocedure::regproc,
default_threshold,
minimum_threshold,
improvement_threshold
FROM public.pg_dist_rebalance_strategy;
--
-- drop backup tables
--
DROP TABLE public.pg_dist_authinfo;
DROP TABLE public.pg_dist_colocation;
DROP TABLE public.pg_dist_local_group;
DROP TABLE public.pg_dist_node;
DROP TABLE public.pg_dist_node_metadata;
DROP TABLE public.pg_dist_partition;
DROP TABLE public.pg_dist_placement;
DROP TABLE public.pg_dist_poolinfo;
DROP TABLE public.pg_dist_shard;
DROP TABLE public.pg_dist_transaction;
DROP TABLE public.pg_dist_rebalance_strategy;
--
-- reset sequences
--
PERFORM setval('pg_catalog.pg_dist_shardid_seq', (SELECT MAX(shardid)+1 AS max_shard_id FROM pg_dist_shard), false);
PERFORM setval('pg_catalog.pg_dist_placement_placementid_seq', (SELECT MAX(placementid)+1 AS max_placement_id FROM pg_dist_placement), false);
PERFORM setval('pg_catalog.pg_dist_groupid_seq', (SELECT MAX(groupid)+1 AS max_group_id FROM pg_dist_node), false);
PERFORM setval('pg_catalog.pg_dist_node_nodeid_seq', (SELECT MAX(nodeid)+1 AS max_node_id FROM pg_dist_node), false);
PERFORM setval('pg_catalog.pg_dist_colocationid_seq', (SELECT MAX(colocationid)+1 AS max_colocation_id FROM pg_dist_colocation), false);
--
-- register triggers
--
FOR table_name IN SELECT logicalrelid FROM pg_catalog.pg_dist_partition
LOOP
trigger_name := 'truncate_trigger_' || table_name::oid;
command := 'create trigger ' || trigger_name || ' after truncate on ' || table_name || ' execute procedure pg_catalog.citus_truncate_trigger()';
EXECUTE command;
command := 'update pg_trigger set tgisinternal = true where tgname = ' || quote_literal(trigger_name);
EXECUTE command;
END LOOP;
--
-- set dependencies
--
INSERT INTO pg_depend
SELECT
'pg_class'::regclass::oid as classid,
p.logicalrelid::regclass::oid as objid,
0 as objsubid,
'pg_extension'::regclass::oid as refclassid,
(select oid from pg_extension where extname = 'citus') as refobjid,
0 as refobjsubid ,
'n' as deptype
FROM pg_catalog.pg_dist_partition p;
-- restore pg_dist_object from the stable identifiers
TRUNCATE citus.pg_dist_object;
INSERT INTO citus.pg_dist_object (classid, objid, objsubid, distribution_argument_index, colocationid)
SELECT
address.classid,
address.objid,
address.objsubid,
naming.distribution_argument_index,
naming.colocationid
FROM
public.pg_dist_object naming,
pg_catalog.pg_get_object_address(naming.type, naming.object_names, naming.object_args) address;
DROP TABLE public.pg_dist_object;
END;
$cppu$;
COMMENT ON FUNCTION pg_catalog.citus_finish_pg_upgrade()
IS 'perform tasks to restore citus settings from a location that has been prepared before pg_upgrade';

View File

@ -8,6 +8,42 @@ DECLARE
command text;
trigger_name text;
BEGIN
IF substring(current_Setting('server_version'), '\d+')::int >= 14 THEN
EXECUTE $cmd$
CREATE AGGREGATE array_cat_agg(anycompatiblearray) (SFUNC = array_cat, STYPE = anycompatiblearray);
COMMENT ON AGGREGATE array_cat_agg(anycompatiblearray)
IS 'concatenate input arrays into a single array';
$cmd$;
ELSE
EXECUTE $cmd$
CREATE AGGREGATE array_cat_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray);
COMMENT ON AGGREGATE array_cat_agg(anyarray)
IS 'concatenate input arrays into a single array';
$cmd$;
END IF;
/*
* Citus creates the array_cat_agg but because of a compatibility
* issue between pg13-pg14, we drop and create it during upgrade.
* And as Citus creates it, there needs to be a dependency to the
* Citus extension, so we create that dependency here.
* We are not using:
* ALTER EXENSION citus DROP/CREATE AGGREGATE array_cat_agg
* because we don't have an easy way to check if the aggregate
* exists with anyarray type or anycompatiblearray type.
*/
INSERT INTO pg_depend
SELECT
'pg_proc'::regclass::oid as classid,
(SELECT oid FROM pg_proc WHERE proname = 'array_cat_agg') as objid,
0 as objsubid,
'pg_extension'::regclass::oid as refclassid,
(select oid from pg_extension where extname = 'citus') as refobjid,
0 as refobjsubid ,
'e' as deptype;
--
-- restore citus catalog tables
--

View File

@ -0,0 +1,74 @@
CREATE OR REPLACE FUNCTION pg_catalog.citus_prepare_pg_upgrade()
RETURNS void
LANGUAGE plpgsql
SET search_path = pg_catalog
AS $cppu$
BEGIN
DELETE FROM pg_depend WHERE
objid IN (SELECT oid FROM pg_proc WHERE proname = 'array_cat_agg') AND
refobjid IN (select oid from pg_extension where extname = 'citus');
/*
* We are dropping the aggregates because postgres 14 changed
* array_cat type from anyarray to anycompatiblearray. When
* upgrading to pg14, spegifically when running pg_restore on
* array_cat_agg we would get an error. So we drop the aggregate
* and create the right one on citus_finish_pg_upgrade.
*/
DROP AGGREGATE IF EXISTS array_cat_agg(anyarray);
DROP AGGREGATE IF EXISTS array_cat_agg(anycompatiblearray);
--
-- Drop existing backup tables
--
DROP TABLE IF EXISTS public.pg_dist_partition;
DROP TABLE IF EXISTS public.pg_dist_shard;
DROP TABLE IF EXISTS public.pg_dist_placement;
DROP TABLE IF EXISTS public.pg_dist_node_metadata;
DROP TABLE IF EXISTS public.pg_dist_node;
DROP TABLE IF EXISTS public.pg_dist_local_group;
DROP TABLE IF EXISTS public.pg_dist_transaction;
DROP TABLE IF EXISTS public.pg_dist_colocation;
DROP TABLE IF EXISTS public.pg_dist_authinfo;
DROP TABLE IF EXISTS public.pg_dist_poolinfo;
DROP TABLE IF EXISTS public.pg_dist_rebalance_strategy;
DROP TABLE IF EXISTS public.pg_dist_object;
--
-- backup citus catalog tables
--
CREATE TABLE public.pg_dist_partition AS SELECT * FROM pg_catalog.pg_dist_partition;
CREATE TABLE public.pg_dist_shard AS SELECT * FROM pg_catalog.pg_dist_shard;
CREATE TABLE public.pg_dist_placement AS SELECT * FROM pg_catalog.pg_dist_placement;
CREATE TABLE public.pg_dist_node_metadata AS SELECT * FROM pg_catalog.pg_dist_node_metadata;
CREATE TABLE public.pg_dist_node AS SELECT * FROM pg_catalog.pg_dist_node;
CREATE TABLE public.pg_dist_local_group AS SELECT * FROM pg_catalog.pg_dist_local_group;
CREATE TABLE public.pg_dist_transaction AS SELECT * FROM pg_catalog.pg_dist_transaction;
CREATE TABLE public.pg_dist_colocation AS SELECT * FROM pg_catalog.pg_dist_colocation;
-- enterprise catalog tables
CREATE TABLE public.pg_dist_authinfo AS SELECT * FROM pg_catalog.pg_dist_authinfo;
CREATE TABLE public.pg_dist_poolinfo AS SELECT * FROM pg_catalog.pg_dist_poolinfo;
CREATE TABLE public.pg_dist_rebalance_strategy AS SELECT
name,
default_strategy,
shard_cost_function::regprocedure::text,
node_capacity_function::regprocedure::text,
shard_allowed_on_node_function::regprocedure::text,
default_threshold,
minimum_threshold,
improvement_threshold
FROM pg_catalog.pg_dist_rebalance_strategy;
-- store upgrade stable identifiers on pg_dist_object catalog
CREATE TABLE public.pg_dist_object AS SELECT
address.type,
address.object_names,
address.object_args,
objects.distribution_argument_index,
objects.colocationid
FROM citus.pg_dist_object objects,
pg_catalog.pg_identify_object_as_address(objects.classid, objects.objid, objects.objsubid) address;
END;
$cppu$;
COMMENT ON FUNCTION pg_catalog.citus_prepare_pg_upgrade()
IS 'perform tasks to copy citus settings to a location that could later be restored after pg_upgrade is done';

View File

@ -4,6 +4,19 @@ CREATE OR REPLACE FUNCTION pg_catalog.citus_prepare_pg_upgrade()
SET search_path = pg_catalog
AS $cppu$
BEGIN
DELETE FROM pg_depend WHERE
objid IN (SELECT oid FROM pg_proc WHERE proname = 'array_cat_agg') AND
refobjid IN (select oid from pg_extension where extname = 'citus');
/*
* We are dropping the aggregates because postgres 14 changed
* array_cat type from anyarray to anycompatiblearray. When
* upgrading to pg14, spegifically when running pg_restore on
* array_cat_agg we would get an error. So we drop the aggregate
* and create the right one on citus_finish_pg_upgrade.
*/
DROP AGGREGATE IF EXISTS array_cat_agg(anyarray);
DROP AGGREGATE IF EXISTS array_cat_agg(anycompatiblearray);
--
-- Drop existing backup tables
--

View File

@ -168,6 +168,17 @@ fake_tuple_satisfies_snapshot(Relation rel, TupleTableSlot *slot,
}
#if PG_VERSION_NUM >= PG_VERSION_14
static TransactionId
fake_index_delete_tuples(Relation rel,
TM_IndexDeleteOp *delstate)
{
elog(ERROR, "fake_index_delete_tuples not implemented");
return InvalidTransactionId;
}
#else
static TransactionId
fake_compute_xid_horizon_for_tuples(Relation rel,
ItemPointerData *tids,
@ -178,6 +189,9 @@ fake_compute_xid_horizon_for_tuples(Relation rel,
}
#endif
/* ----------------------------------------------------------------------------
* Functions for manipulations of physical tuples for fake AM.
* ----------------------------------------------------------------------------
@ -556,7 +570,11 @@ static const TableAmRoutine fake_methods = {
.tuple_get_latest_tid = fake_get_latest_tid,
.tuple_tid_valid = fake_tuple_tid_valid,
.tuple_satisfies_snapshot = fake_tuple_satisfies_snapshot,
#if PG_VERSION_NUM >= PG_VERSION_14
.index_delete_tuples = fake_index_delete_tuples,
#else
.compute_xid_horizon_for_tuples = fake_compute_xid_horizon_for_tuples,
#endif
.relation_set_new_filenode = fake_relation_set_new_filenode,
.relation_nontransactional_truncate = fake_relation_nontransactional_truncate,

View File

@ -19,6 +19,7 @@
#include "pgstat.h"
#include "distributed/transaction_management.h"
#include "distributed/version_compat.h"
static Size MemoryContextTotalSpace(MemoryContext context);
@ -47,7 +48,8 @@ MemoryContextTotalSpace(MemoryContext context)
Size totalSpace = 0;
MemoryContextCounters totals = { 0 };
TopTransactionContext->methods->stats(TopTransactionContext, NULL, NULL, &totals);
TopTransactionContext->methods->stats_compat(TopTransactionContext, NULL, NULL,
&totals, true);
totalSpace += totals.totalspace;
for (MemoryContext child = context->firstchild;

View File

@ -371,7 +371,7 @@ StoreAllActiveTransactions(Tuplestorestate *tupleStore, TupleDesc tupleDescripto
memset(values, 0, sizeof(values));
memset(isNulls, false, sizeof(isNulls));
if (is_member_of_role(userId, DEFAULT_ROLE_MONITOR))
if (is_member_of_role(userId, ROLE_PG_MONITOR))
{
showAllTransactions = true;
}

View File

@ -456,14 +456,12 @@ BuildLocalWaitGraph(void)
static bool
IsProcessWaitingForSafeOperations(PGPROC *proc)
{
if (proc->waitStatus != STATUS_WAITING)
if (proc->waitStatus != PROC_WAIT_STATUS_WAITING)
{
return false;
}
/* get the transaction that the backend associated with */
PGXACT *pgxact = &ProcGlobal->allPgXact[proc->pgprocno];
if (pgxact->vacuumFlags & PROC_IS_AUTOVACUUM)
if (pgproc_statusflags_compat(proc) & PROC_IS_AUTOVACUUM)
{
return true;
}
@ -715,7 +713,7 @@ AddProcToVisit(PROCStack *remaining, PGPROC *proc)
bool
IsProcessWaitingForLock(PGPROC *proc)
{
return proc->waitStatus == STATUS_WAITING;
return proc->waitStatus == PROC_WAIT_STATUS_WAITING;
}

View File

@ -12,6 +12,7 @@
#include "distributed/insert_select_planner.h"
#include "distributed/metadata_cache.h"
#include "distributed/multi_router_planner.h"
#include "distributed/version_compat.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_type.h"
@ -526,8 +527,9 @@ FixFunctionArgumentsWalker(Node *expr, void *context)
elog(ERROR, "cache lookup failed for function %u", funcExpr->funcid);
}
funcExpr->args = expand_function_arguments(funcExpr->args,
funcExpr->funcresulttype, func_tuple);
funcExpr->args = expand_function_arguments_compat(funcExpr->args, false,
funcExpr->funcresulttype,
func_tuple);
ReleaseSysCache(func_tuple);
}

View File

@ -45,10 +45,14 @@ FunctionOidExtended(const char *schemaName, const char *functionName, int argume
const bool findVariadics = false;
const bool findDefaults = false;
FuncCandidateList functionList = FuncnameGetCandidates(qualifiedFunctionNameList,
argumentCount,
argumentList, findVariadics,
findDefaults, true);
FuncCandidateList functionList = FuncnameGetCandidates_compat(
qualifiedFunctionNameList,
argumentCount,
argumentList,
findVariadics,
findDefaults,
false,
true);
if (functionList == NULL)
{

View File

@ -135,7 +135,13 @@ ListToHashSet(List *itemList, Size keySize, bool isStringList)
info.entrysize = keySize;
info.hcxt = CurrentMemoryContext;
if (!isStringList)
if (isStringList)
{
#if PG_VERSION_NUM >= PG_VERSION_14
flags |= HASH_STRINGS;
#endif
}
else
{
flags |= HASH_BLOBS;
}

View File

@ -539,7 +539,7 @@ IsParentTable(Oid relationId)
Oid
PartitionParentOid(Oid partitionOid)
{
Oid partitionParentOid = get_partition_parent(partitionOid);
Oid partitionParentOid = get_partition_parent_compat(partitionOid, false);
return partitionParentOid;
}
@ -590,7 +590,7 @@ PartitionList(Oid parentRelationId)
ereport(ERROR, (errmsg("\"%s\" is not a parent table", relationName)));
}
PartitionDesc partDesc = RelationGetPartitionDesc(rel);
PartitionDesc partDesc = RelationGetPartitionDesc_compat(rel, true);
Assert(partDesc != NULL);
int partitionCount = partDesc->nparts;
@ -623,7 +623,7 @@ GenerateDetachPartitionCommand(Oid partitionTableId)
ereport(ERROR, (errmsg("\"%s\" is not a partition", relationName)));
}
Oid parentId = get_partition_parent(partitionTableId);
Oid parentId = get_partition_parent_compat(partitionTableId, false);
char *tableQualifiedName = generate_qualified_relation_name(partitionTableId);
char *parentTableQualifiedName = generate_qualified_relation_name(parentId);
@ -717,7 +717,7 @@ GenerateAlterTableAttachPartitionCommand(Oid partitionTableId)
ereport(ERROR, (errmsg("\"%s\" is not a partition", relationName)));
}
Oid parentId = get_partition_parent(partitionTableId);
Oid parentId = get_partition_parent_compat(partitionTableId, false);
char *tableQualifiedName = generate_qualified_relation_name(partitionTableId);
char *parentTableQualifiedName = generate_qualified_relation_name(parentId);

View File

@ -12,6 +12,31 @@
#ifndef COLUMNAR_COMPAT_H
#define COLUMNAR_COMPAT_H
#include "distributed/pg_version_constants.h"
#if PG_VERSION_NUM >= PG_VERSION_14
#define ColumnarProcessUtility_compat(a, b, c, d, e, f, g, h) \
ColumnarProcessUtility(a, b, c, d, e, f, g, h)
#define PrevProcessUtilityHook_compat(a, b, c, d, e, f, g, h) \
PrevProcessUtilityHook(a, b, c, d, e, f, g, h)
#define GetOldestNonRemovableTransactionId_compat(a, b) \
GetOldestNonRemovableTransactionId(a)
#define ExecSimpleRelationInsert_compat(a, b, c) \
ExecSimpleRelationInsert(a, b, c)
#define index_insert_compat(a, b, c, d, e, f, g, h) \
index_insert(a, b, c, d, e, f, g, h)
#else
#define ColumnarProcessUtility_compat(a, b, c, d, e, f, g, h) \
ColumnarProcessUtility(a, b, d, e, f, g, h)
#define PrevProcessUtilityHook_compat(a, b, c, d, e, f, g, h) \
PrevProcessUtilityHook(a, b, d, e, f, g, h)
#define GetOldestNonRemovableTransactionId_compat(a, b) GetOldestXmin(a, b)
#define ExecSimpleRelationInsert_compat(a, b, c) \
ExecSimpleRelationInsert(b, c)
#define index_insert_compat(a, b, c, d, e, f, g, h) \
index_insert(a, b, c, d, e, f, h)
#endif
#define ACLCHECK_OBJECT_TABLE OBJECT_TABLE
#define ExplainPropertyLong(qlabel, value, es) \

View File

@ -50,7 +50,12 @@ char * pg_get_rule_expr(Node *expression);
extern void deparse_shard_query(Query *query, Oid distrelid, int64 shardid,
StringInfo buffer);
extern char * pg_get_triggerdef_command(Oid triggerId);
#if PG_VERSION_NUM >= PG_VERSION_14
extern char * pg_get_statisticsobj_worker(Oid statextid, bool columns_only,
bool missing_ok);
#else
extern char * pg_get_statisticsobj_worker(Oid statextid, bool missing_ok);
#endif
extern char * generate_relation_name(Oid relid, List *namespaces);
extern char * generate_qualified_relation_name(Oid relid);
extern char * generate_operator_name(Oid operid, Oid arg1, Oid arg2);

View File

@ -288,6 +288,7 @@ extern void ErrorIfUnsupportedAlterIndexStmt(AlterTableStmt *alterTableStatement
extern void MarkIndexValid(IndexStmt *indexStmt);
extern List * ExecuteFunctionOnEachTableIndex(Oid relationId, PGIndexProcessor
pgIndexProcessor, int flags);
extern bool IsReindexWithParam_compat(ReindexStmt *stmt, char *paramName);
/* objectaddress.c - forward declarations */
extern ObjectAddress CreateExtensionStmtObjectAddress(Node *stmt, bool missing_ok);

View File

@ -31,8 +31,12 @@
typedef enum CitusCopyDest
{
COPY_FILE, /* to/from file (or a piped program) */
#if PG_VERSION_NUM >= PG_VERSION_14
COPY_FRONTEND, /* to frontend */
#else
COPY_OLD_FE, /* to/from frontend (2.0 protocol) */
COPY_NEW_FE, /* to/from frontend (3.0 protocol) */
#endif
COPY_CALLBACK /* to/from callback function */
} CitusCopyDest;

View File

@ -64,6 +64,9 @@ typedef struct DDLJob
extern void multi_ProcessUtility(PlannedStmt *pstmt, const char *queryString,
#if PG_VERSION_NUM >= PG_VERSION_14
bool readOnlyTree,
#endif
ProcessUtilityContext context, ParamListInfo params,
struct QueryEnvironment *queryEnv, DestReceiver *dest,
QueryCompletionCompat *completionTag

View File

@ -14,5 +14,6 @@
#define PG_VERSION_12 120000
#define PG_VERSION_13 130000
#define PG_VERSION_14 140000
#define PG_VERSION_15 150000
#endif /* PG_VERSION_CONSTANTS */

View File

@ -30,6 +30,64 @@
#include "tcop/tcopprot.h"
#endif
#if PG_VERSION_NUM >= PG_VERSION_14
#define AlterTableStmtObjType_compat(a) ((a)->objtype)
#define getObjectTypeDescription_compat(a, b) getObjectTypeDescription(a, b)
#define getObjectIdentity_compat(a, b) getObjectIdentity(a, b)
/* for MemoryContextMethods->stats */
#define stats_compat(a, b, c, d, e) stats(a, b, c, d, e)
#define FuncnameGetCandidates_compat(a, b, c, d, e, f, g) \
FuncnameGetCandidates(a, b, c, d, e, f, g)
#define expand_function_arguments_compat(a, b, c, d) expand_function_arguments(a, b, c, d)
#define BeginCopyFrom_compat(a, b, c, d, e, f, g, h) BeginCopyFrom(a, b, c, d, e, f, g, h)
#define standard_ProcessUtility_compat(a, b, c, d, e, f, g, h) \
standard_ProcessUtility(a, b, c, d, e, f, g, h)
#define ProcessUtility_compat(a, b, c, d, e, f, g, h) \
ProcessUtility(a, b, c, d, e, f, g, h)
#define SetTuplestoreDestReceiverParams_compat(a, b, c, d, e, f) \
SetTuplestoreDestReceiverParams(a, b, c, d, e, f)
#define pgproc_statusflags_compat(pgproc) ((pgproc)->statusFlags)
#define get_partition_parent_compat(a, b) get_partition_parent(a, b)
#define RelationGetPartitionDesc_compat(a, b) RelationGetPartitionDesc(a, b)
#define make_simple_restrictinfo_compat(a, b) make_simple_restrictinfo(a, b)
#define pull_varnos_compat(a, b) pull_varnos(a, b)
#define pg_get_statisticsobj_worker_compat(a, b, c) pg_get_statisticsobj_worker(a, b, c)
#else
#define AlterTableStmtObjType_compat(a) ((a)->relkind)
#define F_NEXTVAL F_NEXTVAL_OID
#define ROLE_PG_MONITOR DEFAULT_ROLE_MONITOR
#define PROC_WAIT_STATUS_WAITING STATUS_WAITING
#define getObjectTypeDescription_compat(a, b) getObjectTypeDescription(a)
#define getObjectIdentity_compat(a, b) getObjectIdentity(a)
/* for MemoryContextMethods->stats */
#define stats_compat(a, b, c, d, e) stats(a, b, c, d)
#define FuncnameGetCandidates_compat(a, b, c, d, e, f, g) \
FuncnameGetCandidates(a, b, c, d, e, g)
#define expand_function_arguments_compat(a, b, c, d) expand_function_arguments(a, c, d)
#define VacOptValue VacOptTernaryValue
#define VACOPTVALUE_UNSPECIFIED VACOPT_TERNARY_DEFAULT
#define VACOPTVALUE_DISABLED VACOPT_TERNARY_DISABLED
#define VACOPTVALUE_ENABLED VACOPT_TERNARY_ENABLED
#define CopyFromState CopyState
#define BeginCopyFrom_compat(a, b, c, d, e, f, g, h) BeginCopyFrom(a, b, d, e, f, g, h)
#define standard_ProcessUtility_compat(a, b, c, d, e, f, g, h) \
standard_ProcessUtility(a, b, d, e, f, g, h)
#define ProcessUtility_compat(a, b, c, d, e, f, g, h) ProcessUtility(a, b, d, e, f, g, h)
#define COPY_FRONTEND COPY_NEW_FE
#define SetTuplestoreDestReceiverParams_compat(a, b, c, d, e, f) \
SetTuplestoreDestReceiverParams(a, b, c, d)
#define pgproc_statusflags_compat(pgproc) \
((&ProcGlobal->allPgXact[(pgproc)->pgprocno])->vacuumFlags)
#define get_partition_parent_compat(a, b) get_partition_parent(a)
#define RelationGetPartitionDesc_compat(a, b) RelationGetPartitionDesc(a)
#define PQ_LARGE_MESSAGE_LIMIT 0
#define make_simple_restrictinfo_compat(a, b) make_simple_restrictinfo(b)
#define pull_varnos_compat(a, b) pull_varnos(b)
#define pg_get_statisticsobj_worker_compat(a, b, c) pg_get_statisticsobj_worker(a, c)
#endif
#if PG_VERSION_NUM >= PG_VERSION_13
#define lnext_compat(l, r) lnext(l, r)
#define list_delete_cell_compat(l, c, p) list_delete_cell(l, c)

View File

@ -52,12 +52,19 @@ ISOLATION_BUILDDIR=build/specs
# ex: make print-generated_isolation_files
print-% : ; @echo $* = $($*)
.PHONY: create-symbolic-link
.PHONY: create-symbolic-link create-tablespaces
create-symbolic-link:
mkdir -p $(citus_abs_srcdir)/build
ln -fsn $(citus_abs_srcdir)/expected $(citus_abs_srcdir)/build/
create-tablespaces:
rm -rf $(citus_abs_srcdir)/tmp_check/ts1
mkdir -p $(citus_abs_srcdir)/tmp_check/ts1
rm -rf $(citus_abs_srcdir)/tmp_check/ts0
mkdir -p $(citus_abs_srcdir)/tmp_check/ts0
rm -rf $(citus_abs_srcdir)/tmp_check/ts2
mkdir -p $(citus_abs_srcdir)/tmp_check/ts2
# How this target works:
# cpp is used before running isolation tests to preprocess spec files.
@ -106,7 +113,7 @@ check-base: all
-- $(MULTI_REGRESS_OPTS) --schedule=$(citus_abs_srcdir)/base_schedule $(EXTRA_TESTS)
# check-minimal only sets up the cluster
check-minimal: all
check-minimal: all create-tablespaces
$(pg_regress_multi_check) --load-extension=citus \
-- $(MULTI_REGRESS_OPTS) --schedule=$(citus_abs_srcdir)/minimal_schedule $(EXTRA_TESTS)
@ -235,3 +242,5 @@ clean-upgrade-artifacts:
clean distclean maintainer-clean:
rm -f $(output_files) $(input_files)
rm -rf tmp_check/
all: create-tablespaces

View File

@ -6,4 +6,4 @@ test: multi_test_helpers multi_test_helpers_superuser multi_create_fdw columnar_
test: multi_test_catalog_views
test: multi_create_table multi_behavioral_analytics_create_table
test: multi_create_table_superuser multi_behavioral_analytics_create_table_superuser
test: multi_load_data multi_load_data_superuser
test: multi_load_data multi_load_data_superuser tablespace

View File

@ -176,7 +176,7 @@ s/relation with OID [0-9]+ does not exist/relation with OID XXXX does not exist/
/^DEBUG: EventTriggerInvoke [0-9]+$/d
# ignore DEBUG1 messages that Postgres generates
/^DEBUG: rehashing catalog cache id [0-9]+$/d
/^DEBUG: rehashing catalog cache id .*$/d
# ignore JIT related messages
/^DEBUG: probing availability of JIT.*/d
@ -229,3 +229,19 @@ s/ERROR: parallel workers for vacuum must/ERROR: parallel vacuum degree must/g
# ignore PL/pgSQL line numbers that differ on Mac builds
s/(CONTEXT: PL\/pgSQL function .* line )([0-9]+)/\1XX/g
# can be removed after dropping PG13 support
s/ERROR: parallel workers for vacuum must be between/ERROR: parallel vacuum degree must be between/g
s/ERROR: fake_fetch_row_version not implemented/ERROR: fake_tuple_update not implemented/g
s/ERROR: COMMIT is not allowed in an SQL function/ERROR: COMMIT is not allowed in a SQL function/g
s/ERROR: ROLLBACK is not allowed in an SQL function/ERROR: ROLLBACK is not allowed in a SQL function/g
/.*Async-Capable.*/d
/.*Async Capable.*/d
/Parent Relationship/d
/Parent-Relationship/d
s/function array_cat_agg\(anyarray\) anyarray/function array_cat_agg\(anycompatiblearray\) anycompatiblearray/g
s/function array_cat_agg\(anycompatiblearray\)/function array_cat_agg\(anyarray\)/g
s/TRIM\(BOTH FROM value\)/btrim\(value\)/g
s/pg14\.idx.*/pg14\.xxxxx/g
s/CREATE TABLESPACE test_tablespace LOCATION.*/CREATE TABLESPACE test_tablespace LOCATION XXXX/g

View File

@ -20,4 +20,5 @@
/multi_mx_copy_data.out
/multi_outer_join.out
/multi_outer_join_reference.out
/tablespace.out
/worker_copy.out

View File

@ -360,7 +360,7 @@ SELECT create_distributed_table('referencing_dist_table', 'a', colocate_with:='r
SET client_min_messages TO WARNING;
SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM pg_constraint
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1;
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
Referencing Table | Definition
---------------------------------------------------------------------
referencing_dist_table | FOREIGN KEY (a) REFERENCES table_with_references(a1)
@ -375,12 +375,12 @@ SELECT alter_distributed_table('table_with_references', shard_count := 12, casca
(1 row)
SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM pg_constraint
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1;
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
Referencing Table | Definition
---------------------------------------------------------------------
referencing_dist_table | FOREIGN KEY (a) REFERENCES table_with_references(a1)
table_with_references | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)
table_with_references | FOREIGN KEY (a1) REFERENCES referenced_dist_table(a)
table_with_references | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)
(3 rows)
SELECT alter_distributed_table('table_with_references', shard_count := 10, cascade_to_colocated := false);
@ -392,7 +392,7 @@ WARNING: foreign key referencing_dist_table_a_fkey will be dropped
(1 row)
SELECT conrelid::regclass::text AS "Referencing Table", pg_get_constraintdef(oid, true) AS "Definition" FROM pg_constraint
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1;
WHERE (conrelid::regclass::text = 'table_with_references' OR confrelid::regclass::text = 'table_with_references') AND contype = 'f' ORDER BY 1,2;
Referencing Table | Definition
---------------------------------------------------------------------
table_with_references | FOREIGN KEY (a2) REFERENCES referenced_ref_table(a)

View File

@ -2,11 +2,18 @@ CREATE SCHEMA alter_role;
CREATE SCHEMA ",CitUs,.TeeN!?";
-- test if the passowrd of the extension owner can be upgraded
ALTER ROLE CURRENT_USER PASSWORD 'password123' VALID UNTIL 'infinity';
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,-1,md5891d7d5079424b1cb973187d354d78de,Infinity)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,-1,md5891d7d5079424b1cb973187d354d78de,Infinity)")
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,-1,Infinity)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,-1,Infinity)")
(2 rows)
SELECT workers.result = pg_authid.rolpassword AS password_is_same FROM run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = current_user$$) workers, pg_authid WHERE pg_authid.rolname = current_user;
password_is_same
---------------------------------------------------------------------
t
t
(2 rows)
-- test if the password and some connection settings are propagated when a node gets added
@ -16,11 +23,18 @@ SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlog
---------------------------------------------------------------------
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,66,md568701dc40be546e0357027fb0109338c,2032)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,66,md568701dc40be546e0357027fb0109338c,2032)")
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,66,2032)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,66,2032)")
(2 rows)
SELECT workers.result = pg_authid.rolpassword AS password_is_same FROM run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = current_user$$) workers, pg_authid WHERE pg_authid.rolname = current_user;
password_is_same
---------------------------------------------------------------------
t
t
(2 rows)
SELECT master_remove_node('localhost', :worker_1_port);
@ -35,10 +49,16 @@ SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlog
---------------------------------------------------------------------
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,2052)")
(1 row)
SELECT workers.result = pg_authid.rolpassword AS password_is_same FROM run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = current_user$$) workers, pg_authid WHERE pg_authid.rolname = current_user;
password_is_same
---------------------------------------------------------------------
t
(1 row)
SELECT 1 FROM master_add_node('localhost', :worker_1_port);
@ -52,11 +72,18 @@ SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlog
---------------------------------------------------------------------
(0 rows)
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, rolpassword, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
SELECT run_command_on_workers($$SELECT row(rolname, rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin, rolreplication, rolbypassrls, rolconnlimit, EXTRACT (year FROM rolvaliduntil)) FROM pg_authid WHERE rolname = current_user$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,md53e559cc1fcf0c70f1f8e05c9a79c3133,2052)")
(localhost,57637,t,"(postgres,t,t,t,t,t,t,t,0,2052)")
(localhost,57638,t,"(postgres,t,t,t,t,t,t,t,0,2052)")
(2 rows)
SELECT workers.result = pg_authid.rolpassword AS password_is_same FROM run_command_on_workers($$SELECT rolpassword FROM pg_authid WHERE rolname = current_user$$) workers, pg_authid WHERE pg_authid.rolname = current_user;
password_is_same
---------------------------------------------------------------------
t
t
(2 rows)
-- check user, database and postgres wide SET settings.

View File

@ -86,9 +86,9 @@ SELECT citus_add_local_table_to_metadata('citus_local_table_2');
-- also create indexes on them
CREATE INDEX citus_local_table_1_idx ON citus_local_table_1(a);
NOTICE: executing the command locally: CREATE INDEX citus_local_table_1_idx_1504001 ON citus_local_tables_test_schema.citus_local_table_1_1504001 USING btree (a )
NOTICE: executing the command locally: CREATE INDEX citus_local_table_1_idx_1504001 ON citus_local_tables_test_schema.citus_local_table_1_1504001 USING btree (a )
CREATE INDEX citus_local_table_2_idx ON citus_local_table_2(a);
NOTICE: executing the command locally: CREATE INDEX citus_local_table_2_idx_1504002 ON citus_local_tables_test_schema.citus_local_table_2_1504002 USING btree (a )
NOTICE: executing the command locally: CREATE INDEX citus_local_table_2_idx_1504002 ON citus_local_tables_test_schema.citus_local_table_2_1504002 USING btree (a )
-- drop them for next tests
DROP TABLE citus_local_table_1, citus_local_table_2;
NOTICE: executing the command locally: DROP TABLE IF EXISTS citus_local_tables_test_schema.citus_local_table_2_xxxxx CASCADE
@ -416,10 +416,10 @@ NOTICE: identifier "LocalTabLE.1!?!90123456789012345678901234567890123456789012
CREATE UNIQUE INDEX uniqueIndex ON "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" (id);
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
-- ingest some data before citus_add_local_table_to_metadata
set client_min_messages to ERROR;
INSERT INTO "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" VALUES (1, 1, (1, row_to_json(row(1,1)))::local_type, row_to_json(row(1,1), true)),
(2, 1, (2, row_to_json(row(2,2)))::local_type, row_to_json(row(2,2), 'false'));
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
reset client_min_messages;
-- create a replica identity before citus_add_local_table_to_metadata
ALTER TABLE "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" REPLICA IDENTITY USING INDEX uniqueIndex;
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
@ -445,10 +445,10 @@ SELECT citus_add_local_table_to_metadata('"LocalTabLE.1!?!9012345678901234567890
-- create some objects after citus_add_local_table_to_metadata
CREATE INDEX "my!Index2" ON "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789"(id) WITH ( fillfactor = 90 ) WHERE id < 20;
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
NOTICE: executing the command locally: CREATE INDEX "my!Index2_1504036" ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id ) WITH (fillfactor = '90' )WHERE (id < 20)
NOTICE: executing the command locally: CREATE INDEX "my!Index2_1504036" ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id ) WITH (fillfactor = '90' )WHERE (id < 20)
CREATE UNIQUE INDEX uniqueIndex2 ON "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789"(id);
NOTICE: identifier "LocalTabLE.1!?!9012345678901234567890123456789012345678901234567890123456789" will be truncated to "LocalTabLE.1!?!901234567890123456789012345678901234567890123456"
NOTICE: executing the command locally: CREATE UNIQUE INDEX uniqueindex2_1504036 ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id )
NOTICE: executing the command locally: CREATE UNIQUE INDEX uniqueindex2_1504036 ON "CiTUS!LocalTables"."LocalTabLE.1!?!9012345678901234567890123456789_7e923997_1504036" USING btree (id )
---------------------------------------------------------------------
---- utility command execution ----
---------------------------------------------------------------------
@ -563,7 +563,7 @@ ORDER BY 1;
(2 rows)
CREATE UNIQUE INDEX citus_local_table_1_idx ON citus_local_table_1(b);
NOTICE: executing the command locally: CREATE UNIQUE INDEX citus_local_table_1_idx_1504027 ON citus_local_tables_test_schema.citus_local_table_1_1504027 USING btree (b )
NOTICE: executing the command locally: CREATE UNIQUE INDEX citus_local_table_1_idx_1504027 ON citus_local_tables_test_schema.citus_local_table_1_1504027 USING btree (b )
-- show that we successfully defined the unique index
SELECT indexrelid::regclass, indrelid::regclass, indkey
FROM pg_index
@ -621,7 +621,7 @@ SELECT citus_add_local_table_to_metadata('citus_local_table_4');
INSERT INTO citus_local_table_4 VALUES (1), (2), (3);
NOTICE: executing the command locally: INSERT INTO citus_local_tables_test_schema.citus_local_table_4_xxxx AS citus_table_alias (a) VALUES (1), (2), (3)
CREATE INDEX citus_local_table_4_idx ON citus_local_table_4(a);
NOTICE: executing the command locally: CREATE INDEX citus_local_table_4_idx_xxxxxx ON citus_local_tables_test_schema.citus_local_table_4_xxxx USING btree (a )
NOTICE: executing the command locally: CREATE INDEX citus_local_table_4_idx_xxxxxx ON citus_local_tables_test_schema.citus_local_table_4_xxxx USING btree (a )
SELECT citus_table_size('citus_local_table_4');
citus_table_size
---------------------------------------------------------------------
@ -677,7 +677,7 @@ FROM pg_dist_partition WHERE logicalrelid = 'citus_local_table_4'::regclass;
(1 row)
SELECT column_name_to_column('citus_local_table_4', 'a');
column_name_to_column
column_name_to_column
---------------------------------------------------------------------
{VAR :varno 1 :varattno 1 :vartype 23 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1}
(1 row)

View File

@ -20,11 +20,11 @@ REINDEX INDEX CONCURRENTLY t_idx;
Indexes:
"t_idx" btree (a, b)
explain insert into t values (1, 2);
QUERY PLAN
explain (COSTS OFF) insert into t values (1, 2);
QUERY PLAN
---------------------------------------------------------------------
Insert on t (cost=0.00..0.01 rows=1 width=8)
-> Result (cost=0.00..0.01 rows=1 width=8)
Insert on t
-> Result
(2 rows)
insert into t values (1, 2);
@ -34,11 +34,11 @@ SELECT * FROM t;
1 | 2
(1 row)
explain insert into t values (1, 2);
QUERY PLAN
explain (COSTS OFF) insert into t values (1, 2);
QUERY PLAN
---------------------------------------------------------------------
Insert on t (cost=0.00..0.01 rows=1 width=8)
-> Result (cost=0.00..0.01 rows=1 width=8)
Insert on t
-> Result
(2 rows)
insert into t values (3, 4);

View File

@ -130,6 +130,9 @@ FROM
(2 rows)
-- DISTINCT w/wout distribution key
-- there seems to be an issue with SELECT DISTINCT ROW with PG14
-- so we add an alternative output that gives an error, this should
-- be removed after the issue is fixed on PG14.
SELECT DISTINCT(col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
FROM
data_types_table

View File

@ -0,0 +1,182 @@
CREATE SCHEMA data_types;
SET search_path TO data_types;
Create or replace function test_jsonb() returns jsonb as
$$
begin
return '{"test_json": "test"}';
end;
$$ language plpgsql;
CREATE TABLE data_types_table
(
dist_key bigint PRIMARY KEY,
col1 int[], col2 int[][], col3 int [][][],
col4 varchar[], col5 varchar[][], col6 varchar [][][],
col70 bit, col7 bit[], col8 bit[][], col9 bit [][][],
col10 bit varying(10),
col11 bit varying(10)[], col12 bit varying(10)[][], col13 bit varying(10)[][][],
col14 bytea, col15 bytea[], col16 bytea[][], col17 bytea[][][],
col18 boolean, col19 boolean[], col20 boolean[][], col21 boolean[][][],
col22 inet, col23 inet[], col24 inet[][], col25 inet[][][],
col26 macaddr, col27 macaddr[], col28 macaddr[][], col29 macaddr[][][],
col30 numeric, col32 numeric[], col33 numeric[][], col34 numeric[][][],
col35 jsonb, col36 jsonb[], col37 jsonb[][], col38 jsonb[][][]
);
CREATE TABLE data_types_table_local AS SELECT * FROM data_types_table;
SELECT create_distributed_table('data_types_table', 'dist_key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO data_types_table (dist_key,col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col30, col32, col33, col34, col35, col36, col37, col38)
VALUES (1,ARRAY[1], ARRAY[ARRAY[0,0,0]], ARRAY[ARRAY[ARRAY[0,0,0]]], ARRAY['1'], ARRAY[ARRAY['0','0','0']], ARRAY[ARRAY[ARRAY['0','0','0']]], '1', ARRAY[b'1'], ARRAY[ARRAY[b'0',b'0',b'0']], ARRAY[ARRAY[ARRAY[b'0',b'0',b'0']]], '11101',ARRAY[b'1'], ARRAY[ARRAY[b'01',b'01',b'01']], ARRAY[ARRAY[ARRAY[b'011',b'110',b'0000']]], '\xb4a8e04c0b', ARRAY['\xb4a8e04c0b'::BYTEA], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA, '\xb4a8e04c0b'::BYTEA, '\xb4a8e04c0b'::BYTEA]], ARRAY[ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]]], '1', ARRAY[TRUE], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[ARRAY[1::boolean,TRUE,FALSE]]], INET '192.168.1/24', ARRAY[INET '192.168.1.1'], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']]],MACADDR '08:00:2b:01:02:03', ARRAY[MACADDR '08:00:2b:01:02:03'], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']]], 690, ARRAY[1.1], ARRAY[ARRAY[0,0.111,0.15]], ARRAY[ARRAY[ARRAY[0,0,0]]], test_jsonb(), ARRAY[test_jsonb()], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]]]),
(2,ARRAY[1,2,3], ARRAY[ARRAY[1,2,3], ARRAY[5,6,7]], ARRAY[ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]], ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]]], ARRAY['1','2','3'], ARRAY[ARRAY['1','2','3'], ARRAY['5','6','7']], ARRAY[ARRAY[ARRAY['1','2','3']], ARRAY[ARRAY['5','6','7']], ARRAY[ARRAY['1','2','3']], ARRAY[ARRAY['5','6','7']]], '0', ARRAY[b'1',b'0',b'0'], ARRAY[ARRAY[b'1',b'1',b'0'], ARRAY[b'0',b'0',b'1']], ARRAY[ARRAY[ARRAY[b'1',b'1',b'1']], ARRAY[ARRAY[b'1','0','0']], ARRAY[ARRAY[b'1','1','1']], ARRAY[ARRAY[b'0','0','0']]], '00010', ARRAY[b'11',b'10',b'01'], ARRAY[ARRAY[b'11',b'010',b'101'], ARRAY[b'101',b'01111',b'1000001']], ARRAY[ARRAY[ARRAY[b'10000',b'111111',b'1101010101']], ARRAY[ARRAY[b'1101010','0','1']], ARRAY[ARRAY[b'1','1','11111111']], ARRAY[ARRAY[b'0000000','0','0']]], '\xb4a8e04c0b', ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA], ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]]], 'true', ARRAY[1::boolean,TRUE,FALSE], ARRAY[ARRAY[1::boolean,TRUE,FALSE], ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]]],'0.0.0.0/32', ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24'], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']]], '0800.2b01.0203', ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203'], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']]], 0.99, ARRAY[1.1,2.22,3.33], ARRAY[ARRAY[1.55,2.66,3.88], ARRAY[11.5,10101.6,7111.1]], ARRAY[ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]], ARRAY[ARRAY[1.1,2.1,3]], ARRAY[ARRAY[5.0,6.0,7.0]]],test_jsonb(), ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()], ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]]]);
-- insert the same data to the local node as well
INSERT INTO data_types_table_local (dist_key,col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col30, col32, col33, col34, col35, col36, col37, col38)
VALUES (1,ARRAY[1], ARRAY[ARRAY[0,0,0]], ARRAY[ARRAY[ARRAY[0,0,0]]], ARRAY['1'], ARRAY[ARRAY['0','0','0']], ARRAY[ARRAY[ARRAY['0','0','0']]], '1', ARRAY[b'1'], ARRAY[ARRAY[b'0',b'0',b'0']], ARRAY[ARRAY[ARRAY[b'0',b'0',b'0']]], '11101',ARRAY[b'1'], ARRAY[ARRAY[b'01',b'01',b'01']], ARRAY[ARRAY[ARRAY[b'011',b'110',b'0000']]], '\xb4a8e04c0b', ARRAY['\xb4a8e04c0b'::BYTEA], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA, '\xb4a8e04c0b'::BYTEA, '\xb4a8e04c0b'::BYTEA]], ARRAY[ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]]], '1', ARRAY[TRUE], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[ARRAY[1::boolean,TRUE,FALSE]]], INET '192.168.1/24', ARRAY[INET '192.168.1.1'], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']]],MACADDR '08:00:2b:01:02:03', ARRAY[MACADDR '08:00:2b:01:02:03'], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']]], 690, ARRAY[1.1], ARRAY[ARRAY[0,0.111,0.15]], ARRAY[ARRAY[ARRAY[0,0,0]]], test_jsonb(), ARRAY[test_jsonb()], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]]]),
(2,ARRAY[1,2,3], ARRAY[ARRAY[1,2,3], ARRAY[5,6,7]], ARRAY[ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]], ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]]], ARRAY['1','2','3'], ARRAY[ARRAY['1','2','3'], ARRAY['5','6','7']], ARRAY[ARRAY[ARRAY['1','2','3']], ARRAY[ARRAY['5','6','7']], ARRAY[ARRAY['1','2','3']], ARRAY[ARRAY['5','6','7']]], '0', ARRAY[b'1',b'0',b'0'], ARRAY[ARRAY[b'1',b'1',b'0'], ARRAY[b'0',b'0',b'1']], ARRAY[ARRAY[ARRAY[b'1',b'1',b'1']], ARRAY[ARRAY[b'1','0','0']], ARRAY[ARRAY[b'1','1','1']], ARRAY[ARRAY[b'0','0','0']]], '00010', ARRAY[b'11',b'10',b'01'], ARRAY[ARRAY[b'11',b'010',b'101'], ARRAY[b'101',b'01111',b'1000001']], ARRAY[ARRAY[ARRAY[b'10000',b'111111',b'1101010101']], ARRAY[ARRAY[b'1101010','0','1']], ARRAY[ARRAY[b'1','1','11111111']], ARRAY[ARRAY[b'0000000','0','0']]], '\xb4a8e04c0b', ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA], ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]], ARRAY[ARRAY['\xb4a8e04c0b'::BYTEA,'\x18a232a678'::BYTEA,'\x38b2697632'::BYTEA]]], 'true', ARRAY[1::boolean,TRUE,FALSE], ARRAY[ARRAY[1::boolean,TRUE,FALSE], ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]], ARRAY[ARRAY[1::boolean,TRUE,FALSE]]],'0.0.0.0/32', ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24'], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']], ARRAY[ARRAY[INET '0.0.0.0', '0.0.0.0/32', '::ffff:fff0:1', '192.168.1/24']]], '0800.2b01.0203', ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203'], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']], ARRAY[ARRAY[MACADDR '08002b-010203', MACADDR '08002b-010203', '08002b010203']]], 0.99, ARRAY[1.1,2.22,3.33], ARRAY[ARRAY[1.55,2.66,3.88], ARRAY[11.5,10101.6,7111.1]], ARRAY[ARRAY[ARRAY[1,2,3]], ARRAY[ARRAY[5,6,7]], ARRAY[ARRAY[1.1,2.1,3]], ARRAY[ARRAY[5.0,6.0,7.0]]],test_jsonb(), ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()], ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]], ARRAY[ARRAY[test_jsonb(),test_jsonb(),test_jsonb(),test_jsonb()]]]);
-- different query/planning executiom types
-- compare results with Postgres
SELECT * FROM data_types_table
EXCEPT
SELECT * FROM data_types_table_local;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38
---------------------------------------------------------------------
(0 rows)
SELECT * FROM data_types_table_local
EXCEPT
SELECT * FROM data_types_table;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38
---------------------------------------------------------------------
(0 rows)
WITH cte_1 AS (SELECT * FROM data_types_table LIMIT 100000),
cte_2 AS (SELECT * FROM data_types_table_local LIMIT 100000)
SELECT * FROM cte_1
EXCEPT
SELECT * FROM cte_2;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38
---------------------------------------------------------------------
(0 rows)
WITH cte_1 AS (SELECT * FROM data_types_table LIMIT 100000),
cte_2 AS (SELECT * FROM data_types_table_local LIMIT 100000)
SELECT * FROM cte_2
EXCEPT
SELECT * FROM cte_1;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38
---------------------------------------------------------------------
(0 rows)
SELECT * FROM (SELECT *, random() > 100 FROM data_types_table) as foo
EXCEPT
SELECT * FROM (SELECT *, random() > 100 FROM data_types_table_local) as bar;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38 | ?column?
---------------------------------------------------------------------
(0 rows)
SELECT * FROM (SELECT *, random() > 100 FROM data_types_table_local) as bar
EXCEPT
SELECT * FROM (SELECT *, random() > 100 FROM data_types_table) as foo;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38 | ?column?
---------------------------------------------------------------------
(0 rows)
-- GROUP BY w/wout the dist key
SELECT
count(*)
FROM
data_types_table
GROUP BY
col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38;
count
---------------------------------------------------------------------
1
1
(2 rows)
SELECT
count(*)
FROM
data_types_table
GROUP BY
dist_key, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38;
count
---------------------------------------------------------------------
1
1
(2 rows)
-- window function w/wout distribution key
SELECT
count(*) OVER (PARTITION BY col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
FROM
data_types_table;
count
---------------------------------------------------------------------
1
1
(2 rows)
SELECT
count(*) OVER (PARTITION BY dist_key, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
FROM
data_types_table;
count
---------------------------------------------------------------------
1
1
(2 rows)
-- DISTINCT w/wout distribution key
-- there seems to be an issue with SELECT DISTINCT ROW with PG14
-- so we add an alternative output that gives an error, this should
-- be removed after the issue is fixed on PG14.
SELECT DISTINCT(col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
FROM
data_types_table
ORDER BY 1 DESC;
ERROR: could not identify a hash function for type bit
CONTEXT: while executing command on localhost:xxxxx
SELECT DISTINCT(dist_key, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
FROM
data_types_table
ORDER BY 1 DESC;
ERROR: could not identify a hash function for type bit
CONTEXT: while executing command on localhost:xxxxx
-- count DISTINCT w/wout dist key
SELECT count(DISTINCT(col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38))
FROM
data_types_table
ORDER BY 1 DESC;
count
---------------------------------------------------------------------
2
(1 row)
SELECT count(DISTINCT(dist_key, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38))
FROM
data_types_table
ORDER BY 1 DESC;
count
---------------------------------------------------------------------
2
(1 row)
-- also test with RETURNING
ALTER TABLE data_types_table ADD COLUMN useless_column INT;
UPDATE data_types_table SET useless_column = 1 RETURNING *;
dist_key | col1 | col2 | col3 | col4 | col5 | col6 | col70 | col7 | col8 | col9 | col10 | col11 | col12 | col13 | col14 | col15 | col16 | col17 | col18 | col19 | col20 | col21 | col22 | col23 | col24 | col25 | col26 | col27 | col28 | col29 | col30 | col32 | col33 | col34 | col35 | col36 | col37 | col38 | useless_column
---------------------------------------------------------------------
1 | {1} | {{0,0,0}} | {{{0,0,0}}} | {1} | {{0,0,0}} | {{{0,0,0}}} | 1 | {1} | {{0,0,0}} | {{{0,0,0}}} | 11101 | {1} | {{01,01,01}} | {{{011,110,0000}}} | \xb4a8e04c0b | {"\\xb4a8e04c0b"} | {{"\\xb4a8e04c0b","\\xb4a8e04c0b","\\xb4a8e04c0b"}} | {{{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}}} | t | {t} | {{t,t,f}} | {{{t,t,f}}} | 192.168.1.0/24 | {192.168.1.1} | {{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}} | {{{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}}} | 08:00:2b:01:02:03 | {08:00:2b:01:02:03} | {{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}} | {{{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}}} | 690 | {1.1} | {{0,0.111,0.15}} | {{{0,0,0}}} | {"test_json": "test"} | {"{\"test_json\": \"test\"}"} | {{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}} | {{{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}}} | 1
2 | {1,2,3} | {{1,2,3},{5,6,7}} | {{{1,2,3}},{{5,6,7}},{{1,2,3}},{{5,6,7}}} | {1,2,3} | {{1,2,3},{5,6,7}} | {{{1,2,3}},{{5,6,7}},{{1,2,3}},{{5,6,7}}} | 0 | {1,0,0} | {{1,1,0},{0,0,1}} | {{{1,1,1}},{{1,0,0}},{{1,1,1}},{{0,0,0}}} | 00010 | {11,10,01} | {{11,010,101},{101,01111,1000001}} | {{{10000,111111,1101010101}},{{1101010,0,1}},{{1,1,11111111}},{{0000000,0,0}}} | \xb4a8e04c0b | {"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"} | {{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"},{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}} | {{{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}},{{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}},{{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}},{{"\\xb4a8e04c0b","\\x18a232a678","\\x38b2697632"}}} | t | {t,t,f} | {{t,t,f},{t,t,f}} | {{{t,t,f}},{{t,t,f}},{{t,t,f}},{{t,t,f}}} | 0.0.0.0 | {0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24} | {{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}} | {{{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}},{{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}},{{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}},{{0.0.0.0,0.0.0.0,::ffff:255.240.0.1,192.168.1.0/24}}} | 08:00:2b:01:02:03 | {08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03} | {{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}} | {{{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}},{{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}},{{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}},{{08:00:2b:01:02:03,08:00:2b:01:02:03,08:00:2b:01:02:03}}} | 0.99 | {1.1,2.22,3.33} | {{1.55,2.66,3.88},{11.5,10101.6,7111.1}} | {{{1,2,3}},{{5,6,7}},{{1.1,2.1,3}},{{5.0,6.0,7.0}}} | {"test_json": "test"} | {"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"} | {{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"},{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}} | {{{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}},{{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}},{{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}},{{"{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}","{\"test_json\": \"test\"}"}}} | 1
(2 rows)
-- three methods of INSERT .. SELECT
INSERT INTO data_types_table SELECT * FROM data_types_table ON CONFLICT (dist_key) DO UPDATE SET useless_column = 10;
INSERT INTO data_types_table SELECT * FROM data_types_table LIMIT 100000 ON CONFLICT (dist_key) DO UPDATE SET useless_column = 10;
INSERT INTO data_types_table (dist_key, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38)
SELECT dist_key+1, col1, col2, col3, col4, col5, col6, col70, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17, col18, col19, col20, col21, col22, col23, col24, col25, col26, col27, col28, col29, col32, col33, col34, col35, col36, col37, col38 FROM data_types_table ON CONFLICT (dist_key) DO UPDATE SET useless_column = 10;
SET client_min_messages TO ERROR;
DROP SCHEMA data_types CASCADE;

View File

@ -343,20 +343,6 @@ SELECT public.verify_function_is_same_on_workers('function_tests.eq(macaddr,maca
t
(1 row)
ALTER FUNCTION eq(macaddr,macaddr) SET "citus.setting;'" TO 'hello '' world';
SELECT public.verify_function_is_same_on_workers('function_tests.eq(macaddr,macaddr)');
verify_function_is_same_on_workers
---------------------------------------------------------------------
t
(1 row)
ALTER FUNCTION eq(macaddr,macaddr) RESET "citus.setting;'";
SELECT public.verify_function_is_same_on_workers('function_tests.eq(macaddr,macaddr)');
verify_function_is_same_on_workers
---------------------------------------------------------------------
t
(1 row)
ALTER FUNCTION eq(macaddr,macaddr) SET search_path TO 'sch'';ma', public;
SELECT public.verify_function_is_same_on_workers('function_tests.eq(macaddr,macaddr)');
verify_function_is_same_on_workers
@ -540,9 +526,6 @@ SELECT * FROM run_command_on_workers('SELECT function_tests2.sum2(id) FROM (sele
localhost | 57638 | f | ERROR: function function_tests2.sum2(integer) does not exist
(2 rows)
-- postgres doesn't accept parameter names in the regprocedure input
SELECT create_distributed_function('eq_with_param_names(val1 macaddr, macaddr)', 'val1');
ERROR: invalid type name "val1 macaddr"
-- invalid distribution_arg_name
SELECT create_distributed_function('eq_with_param_names(macaddr, macaddr)', distribution_arg_name:='test');
ERROR: cannot distribute the function "eq_with_param_names" since the distribution argument is not valid

View File

@ -226,78 +226,55 @@ EXPLAIN (COSTS FALSE) INSERT INTO sensors_2003 VALUES (3, '2003-01-01', row_to_j
-> Result
(7 rows)
SELECT public.explain_has_single_task(
$$
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors WHERE measureid = 3 AND eventdatetime = '2000-02-02';
QUERY PLAN
$$
);
explain_has_single_task
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Aggregate
-> Index Only Scan using sensors_2000_pkey_2580005 on sensors_2000_2580005 sensors
Index Cond: ((measureid = 3) AND (eventdatetime = '2000-02-02'::date))
(8 rows)
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2000 WHERE measureid = 3;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Aggregate
-> Bitmap Heap Scan on sensors_2000_2580005 sensors_xxx
Recheck Cond: (measureid = 3)
-> Bitmap Index Scan on sensors_2000_pkey_2580005
Index Cond: (measureid = 3)
(10 rows)
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2001 WHERE measureid = 3;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Aggregate
-> Bitmap Heap Scan on sensors_2001_2580009 sensors_xxx
Recheck Cond: (measureid = 3)
-> Bitmap Index Scan on sensors_2001_pkey_2580009
Index Cond: (measureid = 3)
(10 rows)
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2002 WHERE measureid = 3;
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Aggregate
-> Bitmap Heap Scan on sensors_2002_2580013 sensors_xxx
Recheck Cond: (measureid = 3)
-> Bitmap Index Scan on sensors_2002_pkey_2580013
Index Cond: (measureid = 3)
(10 rows)
t
(1 row)
SELECT public.explain_has_single_task(
$$
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2003 WHERE measureid = 3;
QUERY PLAN
$$
);
explain_has_single_task
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 1
Tasks Shown: All
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Aggregate
-> Bitmap Heap Scan on sensors_2003_2580017 sensors_xxx
Recheck Cond: (measureid = 3)
-> Bitmap Index Scan on sensors_2003_pkey_2580017
Index Cond: (measureid = 3)
(10 rows)
t
(1 row)
SELECT public.explain_has_single_task(
$$
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2000 WHERE measureid = 3;
$$
);
explain_has_single_task
---------------------------------------------------------------------
t
(1 row)
SELECT public.explain_has_single_task(
$$
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2001 WHERE measureid = 3;
$$
);
explain_has_single_task
---------------------------------------------------------------------
t
(1 row)
SELECT public.explain_has_single_task(
$$
EXPLAIN (COSTS FALSE) SELECT count(*) FROM sensors_2002 WHERE measureid = 3;
$$
);
explain_has_single_task
---------------------------------------------------------------------
t
(1 row)
-- execute 7 times to make sure it is re-cached
EXECUTE drop_col_prepare_insert(3, '2000-10-01', row_to_json(row(1)));

View File

@ -31,31 +31,6 @@ SELECT count(1) FROM copy_test;
4
(1 row)
SELECT citus.dump_network_traffic();
dump_network_traffic
---------------------------------------------------------------------
(0,coordinator,"[initial message]")
(0,worker,"['AuthenticationOk()', 'ParameterStatus(application_name=citus)', 'ParameterStatus(client_encoding=UTF8)', 'ParameterStatus(DateStyle=ISO, MDY)', 'ParameterStatus(integer_datetimes=on)', 'ParameterStatus(IntervalStyle=postgres)', 'ParameterStatus(is_superuser=on)', 'ParameterStatus(server_encoding=UTF8)', 'ParameterStatus(server_version=XXX)', 'ParameterStatus(session_authorization=postgres)', 'ParameterStatus(standard_conforming_strings=on)', 'ParameterStatus(TimeZone=XXX)', 'BackendKeyData(XXX)', 'ReadyForQuery(state=idle)']")
(0,coordinator,"[""Query(query=SELECT worker_apply_shard_ddl_command (100400, 'CREATE TABLE public.copy_test (key integer, value integer) '))""]")
(0,worker,"[""RowDescription(fieldcount=1,fields=['F(name=worker_apply_shard_ddl_command,tableoid=0,colattrnum=0,typoid=2278,typlen=4,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=idle)']")
(0,coordinator,"[""Query(query=SELECT worker_apply_shard_ddl_command (100400, 'ALTER TABLE public.copy_test OWNER TO postgres'))""]")
(0,worker,"[""RowDescription(fieldcount=1,fields=['F(name=worker_apply_shard_ddl_command,tableoid=0,colattrnum=0,typoid=2278,typlen=4,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=idle)']")
(0,coordinator,"[""Query(query=BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(0, XX, 'XXXX-XX-XX XX:XX:XX.XXXXXX-XX');)""]")
(0,worker,"['CommandComplete(command=BEGIN)', ""RowDescription(fieldcount=1,fields=['F(name=assign_distributed_transaction_id,tableoid=0,colattrnum=0,typoid=2278,typlen=4,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"[""Query(query=COPY public.copy_test_XXXXXX FROM STDIN WITH (format 'binary'))""]")
(0,worker,"[""Backend(type=G,body=b'\\\\x01\\\\x00\\\\x02\\\\x00\\\\x01\\\\x00\\\\x01')""]")
(0,coordinator,"[""CopyData(data=b'PGCOPY\\\\n\\\\xff\\\\r\\\\n\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x01')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x04')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\t')"", ""CopyData(data=b'\\\\xff\\\\xff')"", 'CopyDone()']")
(0,worker,"['CommandComplete(command=COPY 4)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"[""Query(query=SELECT pg_table_size('public.copy_test_XXXXXX'))""]")
(0,worker,"[""RowDescription(fieldcount=1,fields=['F(name=pg_table_size,tableoid=0,colattrnum=0,typoid=20,typlen=8,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"['Query(query=SELECT min(key), max(key) FROM public.copy_test_XXXXXX)']")
(0,worker,"[""RowDescription(fieldcount=2,fields=['F(name=min,tableoid=0,colattrnum=0,typoid=23,typlen=4,typmod=-1,format_code=0)', 'F(name=max,tableoid=0,colattrnum=0,typoid=23,typlen=4,typmod=-1,format_code=0)'])"", 'DataRow(columncount=2,columns=[""C(length=0,value=b\\'\\')"", ""C(length=1,value=b\\'0\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"['Query(query=COMMIT)']")
(0,worker,"['CommandComplete(command=COMMIT)', 'ReadyForQuery(state=idle)']")
(0,coordinator,"['Query(query=SELECT count(1) AS count FROM public.copy_test_XXXXXX copy_test WHERE true)']")
(0,worker,"[""RowDescription(fieldcount=1,fields=['F(name=count,tableoid=0,colattrnum=0,typoid=20,typlen=8,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=idle)']")
(20 rows)
---- all of the following tests test behavior with 2 shard placements ----
SHOW citus.shard_replication_factor;
citus.shard_replication_factor

View File

@ -32,25 +32,6 @@ SELECT count(1) FROM copy_test;
4
(1 row)
SELECT citus.dump_network_traffic();
dump_network_traffic
---------------------------------------------------------------------
(0,coordinator,"[initial message]")
(0,worker,"['AuthenticationOk()', 'ParameterStatus(application_name=citus)', 'ParameterStatus(client_encoding=UTF8)', 'ParameterStatus(DateStyle=ISO, MDY)', 'ParameterStatus(integer_datetimes=on)', 'ParameterStatus(IntervalStyle=postgres)', 'ParameterStatus(is_superuser=on)', 'ParameterStatus(server_encoding=UTF8)', 'ParameterStatus(server_version=XXX)', 'ParameterStatus(session_authorization=postgres)', 'ParameterStatus(standard_conforming_strings=on)', 'ParameterStatus(TimeZone=XXX)', 'BackendKeyData(XXX)', 'ReadyForQuery(state=idle)']")
(0,coordinator,"[""Query(query=BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(0, XX, 'XXXX-XX-XX XX:XX:XX.XXXXXX-XX');)""]")
(0,worker,"['CommandComplete(command=BEGIN)', ""RowDescription(fieldcount=1,fields=['F(name=assign_distributed_transaction_id,tableoid=0,colattrnum=0,typoid=2278,typlen=4,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"[""Query(query=COPY public.copy_test_XXXXXX (key, value) FROM STDIN WITH (format 'binary'))""]")
(0,worker,"[""Backend(type=G,body=b'\\\\x01\\\\x00\\\\x02\\\\x00\\\\x01\\\\x00\\\\x01')""]")
(0,coordinator,"[""CopyData(data=b'PGCOPY\\\\n\\\\xff\\\\r\\\\n\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x00')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x01\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x01')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x04')"", ""CopyData(data=b'\\\\x00\\\\x02\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\x03\\\\x00\\\\x00\\\\x00\\\\x04\\\\x00\\\\x00\\\\x00\\\\t')"", ""CopyData(data=b'\\\\xff\\\\xff')"", 'CopyDone()']")
(0,worker,"['CommandComplete(command=COPY 4)', 'ReadyForQuery(state=in_transaction_block)']")
(0,coordinator,"['Query(query=COMMIT)']")
(0,worker,"['CommandComplete(command=COMMIT)', 'ReadyForQuery(state=idle)']")
(1,coordinator,"[initial message]")
(1,worker,"['AuthenticationOk()', 'ParameterStatus(application_name=citus)', 'ParameterStatus(client_encoding=UTF8)', 'ParameterStatus(DateStyle=ISO, MDY)', 'ParameterStatus(integer_datetimes=on)', 'ParameterStatus(IntervalStyle=postgres)', 'ParameterStatus(is_superuser=on)', 'ParameterStatus(server_encoding=UTF8)', 'ParameterStatus(server_version=XXX)', 'ParameterStatus(session_authorization=postgres)', 'ParameterStatus(standard_conforming_strings=on)', 'ParameterStatus(TimeZone=XXX)', 'BackendKeyData(XXX)', 'ReadyForQuery(state=idle)']")
(1,coordinator,"['Query(query=SELECT count(1) AS count FROM public.copy_test_XXXXXX copy_test)']")
(1,worker,"[""RowDescription(fieldcount=1,fields=['F(name=count,tableoid=0,colattrnum=0,typoid=20,typlen=8,typmod=-1,format_code=0)'])"", 'DataRow(columncount=1,columns=[""C(length=0,value=b\\'\\')""])', 'CommandComplete(command=SELECT 1)', 'ReadyForQuery(state=idle)']")
(14 rows)
-- ==== kill the connection when we try to start a transaction ====
-- the query should abort
SELECT citus.mitmproxy('conn.onQuery(query="assign_distributed_transaction").killall()');

View File

@ -1209,7 +1209,6 @@ ON CONFLICT(c1, c2, c3, c4, c5, c6)
DO UPDATE SET
cardinality = enriched.cardinality + excluded.cardinality,
sum = enriched.sum + excluded.sum;
DEBUG: rehashing catalog cache id 14 for pg_opclass; 17 tups, 8 buckets at character 224
DEBUG: INSERT target table and the source relation of the SELECT partition column value must be colocated in distributed INSERT ... SELECT
DEBUG: Router planner cannot handle multi-shard select queries
DEBUG: performing repartitioned INSERT ... SELECT

View File

@ -199,7 +199,7 @@ step s1-add-node-1:
(1 row)
step s2-create-extension-with-schema1:
CREATE extension seg with schema schema1;
CREATE extension seg with version "1.3" schema schema1;
<waiting ...>
step s1-commit:
COMMIT;
@ -317,7 +317,7 @@ step s1-add-node-1:
(1 row)
step s1-create-extension-with-schema2:
CREATE extension seg with schema schema2;
CREATE extension seg with version "1.3" schema schema2;
step s1-begin:
BEGIN;
@ -399,7 +399,7 @@ step s1-remove-node-1:
(1 row)
step s2-create-extension-with-schema1:
CREATE extension seg with schema schema1;
CREATE extension seg with version "1.3" schema schema1;
<waiting ...>
step s1-commit:
COMMIT;
@ -674,7 +674,7 @@ step s2-begin:
BEGIN;
step s2-create-extension-with-schema1:
CREATE extension seg with schema schema1;
CREATE extension seg with version "1.3" schema schema1;
step s1-add-node-1:
SELECT 1 FROM master_add_node('localhost', 57637);
@ -742,7 +742,7 @@ step s2-add-node-1:
(1 row)
step s2-create-extension-with-schema2:
CREATE extension seg with schema schema2;
CREATE extension seg with version "1.3" schema schema2;
step s2-begin:
BEGIN;

View File

@ -56,6 +56,8 @@ master_update_node
step s2-abort: ABORT;
step s1-abort: ABORT;
FATAL: terminating connection due to administrator command
FATAL: terminating connection due to administrator command
SSL connection has been closed unexpectedly
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.

View File

@ -47,7 +47,9 @@ step s2-abort: ABORT;
step s1-abort: ABORT;
WARNING: this step had a leftover error message
FATAL: terminating connection due to administrator command
SSL connection has been closed unexpectedly
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
master_remove_node

View File

@ -162,20 +162,18 @@ SELECT * FROM composite_type_partitioned_table WHERE id = 123;
123 | (123,456)
(1 row)
EXPLAIN (ANALYZE TRUE, COSTS FALSE, VERBOSE TRUE, TIMING FALSE, SUMMARY FALSE)
EXPLAIN (ANALYZE TRUE, COSTS FALSE, VERBOSE FALSE, TIMING FALSE, SUMMARY FALSE)
INSERT INTO composite_type_partitioned_table VALUES (123, '(123, 456)'::other_composite_type);
QUERY PLAN
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=0 loops=1)
Task Count: 1
Tasks Shown: All
-> Task
Query: INSERT INTO public.composite_type_partitioned_table_530003 (id, col) VALUES (123, '(123,456)'::public.test_composite_type)
Node: host=localhost port=xxxxx dbname=regression
-> Insert on public.composite_type_partitioned_table_530003 (actual rows=0 loops=1)
-> Insert on composite_type_partitioned_table_530003 (actual rows=0 loops=1)
-> Result (actual rows=1 loops=1)
Output: 123, '(123,456)'::test_composite_type
(9 rows)
(7 rows)
SELECT run_command_on_coordinator_and_workers($cf$
DROP CAST (other_composite_type as test_composite_type);
@ -206,20 +204,18 @@ $cf$);
(1 row)
INSERT INTO composite_type_partitioned_table VALUES (456, '(456, 678)'::other_composite_type);
EXPLAIN (ANALYZE TRUE, COSTS FALSE, VERBOSE TRUE, TIMING FALSE, SUMMARY FALSE)
EXPLAIN (ANALYZE TRUE, COSTS FALSE, VERBOSE FALSE, TIMING FALSE, SUMMARY FALSE)
INSERT INTO composite_type_partitioned_table VALUES (123, '(456, 678)'::other_composite_type);
QUERY PLAN
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=0 loops=1)
Task Count: 1
Tasks Shown: All
-> Task
Query: INSERT INTO public.composite_type_partitioned_table_530000 (id, col) VALUES (123, '(456,678)'::public.other_composite_type)
Node: host=localhost port=xxxxx dbname=regression
-> Insert on public.composite_type_partitioned_table_530000 (actual rows=0 loops=1)
-> Insert on composite_type_partitioned_table_530000 (actual rows=0 loops=1)
-> Result (actual rows=1 loops=1)
Output: 123, '(456,678)'::test_composite_type
(9 rows)
(7 rows)
-- create and distribute a table on enum type column
CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed');

View File

@ -70,7 +70,7 @@ SELECT create_distributed_function('add(int,int)');
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add CALLED ON NULL INPUT
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) CALLED ON NULL INPUT;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) CALLED ON NULL INPUT;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -83,7 +83,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add RETURNS NULL ON NULL INPUT
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) STRICT;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) STRICT;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -94,7 +94,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add STRICT
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) STRICT;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) STRICT;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -105,7 +105,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add IMMUTABLE
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) IMMUTABLE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) IMMUTABLE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -116,7 +116,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add STABLE
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) STABLE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) STABLE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -127,7 +127,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add VOLATILE
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) VOLATILE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) VOLATILE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -138,7 +138,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add LEAKPROOF
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) LEAKPROOF;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) LEAKPROOF;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -149,7 +149,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add NOT LEAKPROOF
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) NOT LEAKPROOF;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) NOT LEAKPROOF;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -162,7 +162,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add EXTERNAL SECURITY INVOKER
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SECURITY INVOKER;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SECURITY INVOKER;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -173,7 +173,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SECURITY INVOKER
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SECURITY INVOKER;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SECURITY INVOKER;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -184,7 +184,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add EXTERNAL SECURITY DEFINER
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SECURITY DEFINER;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SECURITY DEFINER;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -195,7 +195,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SECURITY DEFINER
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SECURITY DEFINER;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SECURITY DEFINER;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -206,7 +206,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add PARALLEL UNSAFE
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) PARALLEL UNSAFE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) PARALLEL UNSAFE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -217,7 +217,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add PARALLEL RESTRICTED
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) PARALLEL RESTRICTED;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) PARALLEL RESTRICTED;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -228,7 +228,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add PARALLEL SAFE
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) PARALLEL SAFE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) PARALLEL SAFE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -240,7 +240,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add COST 1234
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) COST 1234.000000;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) COST 1234.000000;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -251,7 +251,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add COST 1234.5
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) COST 1234.500000;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) COST 1234.500000;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -262,7 +262,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SET log_min_messages = ERROR
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET log_min_messages = 'error';
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET log_min_messages = 'error';
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -273,7 +273,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SET log_min_messages TO DEFAULT
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET log_min_messages TO DEFAULT;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET log_min_messages TO DEFAULT;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -284,7 +284,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SET log_min_messages FROM CURRENT
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET log_min_messages FROM CURRENT;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET log_min_messages FROM CURRENT;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -295,7 +295,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET TIME ZONE INTERVAL '-08:00' HOUR TO MINUTE;
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET TIME ZONE INTERVAL '@ 8 hours ago';
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET TIME ZONE INTERVAL '@ 8 hours ago';
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -306,7 +306,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET TIME ZONE '-7';
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET timezone = '-7';
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET timezone = '-7';
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -314,56 +314,10 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
(localhost,57638,t,"ALTER FUNCTION")
(2 rows)
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET "citus.setting;'" TO 'hello '' world';
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET "citus.setting;'" = 'hello '' world';
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"ALTER FUNCTION")
(localhost,57638,t,"ALTER FUNCTION")
(2 rows)
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET "citus.setting;'" TO -3.2;
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET "citus.setting;'" = -3.2;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"ALTER FUNCTION")
(localhost,57638,t,"ALTER FUNCTION")
(2 rows)
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET "citus.setting;'" TO -32;
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET "citus.setting;'" = -32;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"ALTER FUNCTION")
(localhost,57638,t,"ALTER FUNCTION")
(2 rows)
-- This raises an error about only accepting one item,
-- that's okay, we're just testing that we don't produce bad syntax.
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add(int, int) SET "citus.setting;'" TO 'hello '' world', 'second '' item';
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET "citus.setting;'" = 'hello '' world', 'second '' item';
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
(localhost,57637,f,"ERROR: SET citus.setting;' takes only one argument")
(localhost,57638,f,"ERROR: SET citus.setting;' takes only one argument")
(2 rows)
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add RESET log_min_messages
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) RESET log_min_messages;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) RESET log_min_messages;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -374,7 +328,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add RESET ALL
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) RESET ALL;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) RESET ALL;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -386,7 +340,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add RENAME TO summation
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) RENAME TO summation;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) RENAME TO summation;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -401,7 +355,7 @@ ALTER FUNCTION add RENAME TO summation;
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION summation RENAME TO add
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.summation(integer, integer) RENAME TO add;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.summation(integer,integer) RENAME TO add;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -424,7 +378,7 @@ SELECT run_command_on_workers('CREATE ROLE function_role');
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add OWNER TO function_role
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) OWNER TO function_role;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) OWNER TO function_role;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -435,7 +389,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add OWNER TO missing_role
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) OWNER TO missing_role;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) OWNER TO missing_role;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -447,7 +401,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add SET SCHEMA public
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) SET SCHEMA public;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) SET SCHEMA public;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -460,7 +414,7 @@ ALTER FUNCTION add SET SCHEMA public;
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION public.add SET SCHEMA function_tests
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION public.add(integer, integer) SET SCHEMA function_tests;
INFO: Propagating deparsed query: ALTER FUNCTION public.add(integer,integer) SET SCHEMA function_tests;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -472,7 +426,7 @@ ALTER FUNCTION public.add SET SCHEMA function_tests;
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add DEPENDS ON EXTENSION citus
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) DEPENDS ON EXTENSION citus;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) DEPENDS ON EXTENSION citus;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -484,7 +438,7 @@ CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION pg_catalog.get_shard_id_for_distribution_column(table_name regclass, distribution_value "any") PARALLEL SAFE;
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION pg_catalog.get_shard_id_for_distribution_column(pg_catalog.regclass, pg_catalog."any") PARALLEL SAFE;
INFO: Propagating deparsed query: ALTER FUNCTION pg_catalog.get_shard_id_for_distribution_column(pg_catalog.regclass,pg_catalog."any") PARALLEL SAFE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------
@ -498,14 +452,14 @@ DROP FUNCTION add(int,int);
$cmd$);
deparse_test
---------------------------------------------------------------------
DROP FUNCTION function_tests.add(integer, integer);
DROP FUNCTION function_tests.add(integer,integer);
(1 row)
-- have multiple actions in a single query
SELECT deparse_and_run_on_workers($cmd$
ALTER FUNCTION add volatile leakproof SECURITY DEFINER PARALLEL unsafe;
$cmd$);
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer, integer) VOLATILE LEAKPROOF SECURITY DEFINER PARALLEL UNSAFE;
INFO: Propagating deparsed query: ALTER FUNCTION function_tests.add(integer,integer) VOLATILE LEAKPROOF SECURITY DEFINER PARALLEL UNSAFE;
CONTEXT: PL/pgSQL function deparse_and_run_on_workers(text) line XX at RAISE
deparse_and_run_on_workers
---------------------------------------------------------------------

View File

@ -81,13 +81,11 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Node Type": "Aggregate",
"Strategy": "Hashed",
"Partial Mode": "Simple",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
"Parent Relationship": "Outer",
"Custom Plan Provider": "Citus Adaptive",
"Parallel Aware": false,
"Distributed Query": {
@ -109,7 +107,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "lineitem_290000",
"Alias": "lineitem"
@ -154,7 +151,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Node-Type>Aggregate</Node-Type>
<Strategy>Hashed</Strategy>
<Partial-Mode>Simple</Partial-Mode>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Group-Key>
<Item>remote_scan.l_quantity</Item>
@ -162,7 +158,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Custom Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Custom-Plan-Provider>Citus Adaptive</Custom-Plan-Provider>
<Parallel-Aware>false</Parallel-Aware>
<Distributed-Query>
@ -186,7 +181,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>lineitem_290000</Relation-Name>
<Alias>lineitem</Alias>
@ -226,13 +220,11 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- Node Type: "Aggregate"
Strategy: "Hashed"
Partial Mode: "Simple"
Parent Relationship: "Outer"
Parallel Aware: false
Group Key:
- "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
Custom Plan Provider: "Citus Adaptive"
Parallel Aware: false
Distributed Query:
@ -251,7 +243,6 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- "l_quantity"
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "lineitem_290000"
Alias: "lineitem"
@ -1093,7 +1084,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Custom Scan",
"Parent Relationship": "Outer",
"Custom Plan Provider": "Citus Adaptive",
"Parallel Aware": false,
"Distributed Query": {
@ -1142,7 +1132,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Custom Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Custom-Plan-Provider>Citus Adaptive</Custom-Plan-Provider>
<Parallel-Aware>false</Parallel-Aware>
<Distributed-Query>
@ -1201,7 +1190,6 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Parallel Aware: false
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
Custom Plan Provider: "Citus Adaptive"
Parallel Aware: false
Distributed Query:
@ -1284,14 +1272,14 @@ Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
\set VERBOSITY TERSE
PREPARE multi_shard_query_param(int) AS UPDATE lineitem SET l_quantity = $1;
BEGIN;
EXPLAIN EXECUTE multi_shard_query_param(5);
Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
EXPLAIN (COSTS OFF) EXECUTE multi_shard_query_param(5);
Custom Scan (Citus Adaptive)
Task Count: 2
Tasks Shown: One of 2
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Update on lineitem_290000 lineitem (cost=0.00..176.00 rows=6000 width=140)
-> Seq Scan on lineitem_290000 lineitem (cost=0.00..176.00 rows=6000 width=140)
-> Update on lineitem_290000 lineitem
-> Seq Scan on lineitem_290000 lineitem
ROLLBACK;
BEGIN;
EXPLAIN (ANALYZE ON, COSTS OFF, TIMING OFF, SUMMARY OFF) EXECUTE multi_shard_query_param(5);
@ -2078,7 +2066,6 @@ EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT JSON) INSERT INT
"Plans": [
{
"Node Type": "Result",
"Parent Relationship": "Member",
"Parallel Aware": false,
"Actual Rows": 1,
"Actual Loops": 1
@ -2176,7 +2163,6 @@ EXPLAIN (COSTS off, ANALYZE on, TIMING off, SUMMARY off, FORMAT XML) INSERT INTO
<Plans>
<Plan>
<Node-Type>Result</Node-Type>
<Parent-Relationship>Member</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Actual-Rows>1</Actual-Rows>
<Actual-Loops>1</Actual-Loops>
@ -2784,14 +2770,14 @@ Custom Scan (Citus Adaptive) (actual rows=0 loops=1)
deallocate update_query;
-- prepared deletes
PREPARE delete_query AS DELETE FROM simple WHERE name=$1 OR name=$2;
EXPLAIN EXECUTE delete_query('x', 'y');
Custom Scan (Citus Adaptive) (cost=0.00..0.00 rows=0 width=0)
EXPLAIN (COSTS OFF) EXECUTE delete_query('x', 'y');
Custom Scan (Citus Adaptive)
Task Count: 2
Tasks Shown: One of 2
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Delete on simple_570026 simple (cost=0.00..29.05 rows=13 width=6)
-> Seq Scan on simple_570026 simple (cost=0.00..29.05 rows=13 width=6)
-> Delete on simple_570026 simple
-> Seq Scan on simple_570026 simple
Filter: ((name = 'x'::text) OR (name = 'y'::text))
EXPLAIN :default_analyze_flags EXECUTE delete_query('x', 'y');
Custom Scan (Citus Adaptive) (actual rows=0 loops=1)

View File

@ -139,7 +139,7 @@ SELECT * FROM multi_extension.print_extension_changes();
| function alter_role_if_exists(text,text) boolean
| function any_value(anyelement) anyelement
| function any_value_agg(anyelement,anyelement) anyelement
| function array_cat_agg(anyarray) anyarray
| function array_cat_agg(anyarray) anycompatiblearray
| function assign_distributed_transaction_id(integer,bigint,timestamp with time zone) void
| function authinfo_valid(text) boolean
| function broadcast_intermediate_result(text,text) bigint

View File

@ -243,7 +243,7 @@ SELECT * FROM citus_local_table ORDER BY a;
-- we should still disallow writes to local tables
INSERT INTO local VALUES (1, 1);
ERROR: cannot execute INSERT in a read-only transaction
INSERT INTO local SELECT a, b FROM the_table;
INSERT INTO local SELECT i,i FROM generate_series(0,100)i;
ERROR: cannot execute INSERT in a read-only transaction
-- we shouldn't be able to create local tables
CREATE TEMP TABLE local_copy_of_the_table AS SELECT * FROM the_table;

View File

@ -182,10 +182,10 @@ SET client_min_messages TO DEBUG1;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: stored procedure does not have co-located tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -266,10 +266,10 @@ begin;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down CALL in multi-statement transaction
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -300,10 +300,10 @@ select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -319,10 +319,10 @@ select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -354,10 +354,10 @@ select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_replica'::re
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down function call for replicated distributed tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -449,10 +449,10 @@ SET client_min_messages TO DEBUG1;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: there is no worker node with metadata
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -495,10 +495,10 @@ DETAIL: A distributed function is created. To make sure subsequent commands see
call multi_mx_call.mx_call_proc(2, mx_call_add(3, 4));
DEBUG: distribution argument value must be a constant
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -517,10 +517,10 @@ DEBUG: pushing down the procedure
call multi_mx_call.mx_call_proc(floor(random())::int, 2);
DEBUG: arguments in a distributed stored procedure must be constant expressions
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------

View File

@ -0,0 +1,533 @@
-- Test passing off CALL to mx workers
create schema multi_mx_call;
set search_path to multi_mx_call, public;
-- Create worker-local tables to test procedure calls were routed
set citus.shard_replication_factor to 2;
-- This table requires specific settings, create before getting into things
create table mx_call_dist_table_replica(id int, val int);
select create_distributed_table('mx_call_dist_table_replica', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_replica values (9,1),(8,2),(7,3),(6,4),(5,5);
set citus.shard_replication_factor to 1;
--
-- Create tables and procedures we want to use in tests
--
create table mx_call_dist_table_1(id int, val int);
select create_distributed_table('mx_call_dist_table_1', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_1 values (3,1),(4,5),(9,2),(6,5),(3,5);
create table mx_call_dist_table_2(id int, val int);
select create_distributed_table('mx_call_dist_table_2', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_2 values (1,1),(1,2),(2,2),(3,3),(3,4);
create table mx_call_dist_table_bigint(id bigint, val bigint);
select create_distributed_table('mx_call_dist_table_bigint', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_bigint values (1,1),(1,2),(2,2),(3,3),(3,4);
create table mx_call_dist_table_ref(id int, val int);
select create_reference_table('mx_call_dist_table_ref');
create_reference_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_ref values (2,7),(1,8),(2,8),(1,8),(2,8);
create type mx_call_enum as enum ('A', 'S', 'D', 'F');
create table mx_call_dist_table_enum(id int, key mx_call_enum);
select create_distributed_table('mx_call_dist_table_enum', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_enum values (1,'S'),(2,'A'),(3,'D'),(4,'F');
-- test that a distributed function can be colocated with a reference table
CREATE TABLE ref(groupid int);
SELECT create_reference_table('ref');
create_reference_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE PROCEDURE my_group_id_proc()
LANGUAGE plpgsql
SET search_path FROM CURRENT
AS $$
DECLARE
gid int;
BEGIN
SELECT groupid INTO gid
FROM pg_dist_local_group;
INSERT INTO ref(groupid) VALUES (gid);
END;
$$;
SELECT create_distributed_function('my_group_id_proc()', colocate_with := 'ref');
create_distributed_function
---------------------------------------------------------------------
(1 row)
CALL my_group_id_proc();
CALL my_group_id_proc();
SELECT DISTINCT(groupid) FROM ref ORDER BY 1;
groupid
---------------------------------------------------------------------
14
(1 row)
TRUNCATE TABLE ref;
-- test round robin task assignment policy uses different workers on consecutive procedure calls.
SET citus.task_assignment_policy TO 'round-robin';
CALL my_group_id_proc();
CALL my_group_id_proc();
CALL my_group_id_proc();
SELECT DISTINCT(groupid) FROM ref ORDER BY 1;
groupid
---------------------------------------------------------------------
14
18
(2 rows)
TRUNCATE TABLE ref;
RESET citus.task_assignment_policy;
CREATE PROCEDURE mx_call_proc(x int, INOUT y int)
LANGUAGE plpgsql AS $$
BEGIN
-- groupid is 0 in coordinator and non-zero in workers, so by using it here
-- we make sure the procedure is being executed in the worker.
y := x + (select case groupid when 0 then 1 else 0 end from pg_dist_local_group);
-- we also make sure that we can run distributed queries in the procedures
-- that are routed to the workers.
y := y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id);
END;$$;
CREATE PROCEDURE mx_call_proc_bigint(x bigint, INOUT y bigint)
LANGUAGE plpgsql AS $$
BEGIN
y := x + y * 2;
END;$$;
-- create another procedure which verifies:
-- 1. we work fine with multiple return columns
-- 2. we work fine in combination with custom types
CREATE PROCEDURE mx_call_proc_custom_types(INOUT x mx_call_enum, INOUT y mx_call_enum)
LANGUAGE plpgsql AS $$
BEGIN
y := x;
x := (select case groupid when 0 then 'F' else 'S' end from pg_dist_local_group);
END;$$;
-- Test that undistributed procedures have no issue executing
call multi_mx_call.mx_call_proc(2, 0);
y
---------------------------------------------------------------------
29
(1 row)
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
x | y
---------------------------------------------------------------------
F | S
(1 row)
-- Same for unqualified names
call mx_call_proc(2, 0);
y
---------------------------------------------------------------------
29
(1 row)
call mx_call_proc_custom_types('S', 'A');
x | y
---------------------------------------------------------------------
F | S
(1 row)
-- Mark both procedures as distributed ...
select create_distributed_function('mx_call_proc(int,int)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
select create_distributed_function('mx_call_proc_bigint(bigint,bigint)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
select create_distributed_function('mx_call_proc_custom_types(mx_call_enum,mx_call_enum)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
-- We still don't route them to the workers, because they aren't
-- colocated with any distributed tables.
SET client_min_messages TO DEBUG1;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: stored procedure does not have co-located tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
call mx_call_proc_bigint(4, 2);
DEBUG: stored procedure does not have co-located tables
y
---------------------------------------------------------------------
8
(1 row)
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
DEBUG: stored procedure does not have co-located tables
x | y
---------------------------------------------------------------------
F | S
(1 row)
-- Mark them as colocated with a table. Now we should route them to workers.
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select colocate_proc_with_table('mx_call_proc_bigint', 'mx_call_dist_table_bigint'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select colocate_proc_with_table('mx_call_proc_custom_types', 'mx_call_dist_table_enum'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: pushing down the procedure
y
---------------------------------------------------------------------
28
(1 row)
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
DEBUG: pushing down the procedure
x | y
---------------------------------------------------------------------
S | S
(1 row)
call mx_call_proc(2, 0);
DEBUG: pushing down the procedure
y
---------------------------------------------------------------------
28
(1 row)
call mx_call_proc_custom_types('S', 'A');
DEBUG: pushing down the procedure
x | y
---------------------------------------------------------------------
S | S
(1 row)
-- Test implicit cast of int to bigint
call mx_call_proc_bigint(4, 2);
DEBUG: pushing down the procedure
y
---------------------------------------------------------------------
8
(1 row)
-- We don't allow distributing calls inside transactions
begin;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down CALL in multi-statement transaction
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
commit;
-- Drop the table colocated with mx_call_proc_custom_types. Now it shouldn't
-- be routed to workers anymore.
SET client_min_messages TO NOTICE;
drop table mx_call_dist_table_enum;
SET client_min_messages TO DEBUG1;
call multi_mx_call.mx_call_proc_custom_types('S', 'A');
DEBUG: stored procedure does not have co-located tables
x | y
---------------------------------------------------------------------
F | S
(1 row)
-- Make sure we do bounds checking on distributed argument index
-- This also tests that we have cache invalidation for pg_dist_object updates
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass, -1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass, 2);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
-- We support colocating with reference tables
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_ref'::regclass, NULL);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: will push down CALL for reference tables
DEBUG: pushing down the procedure
y
---------------------------------------------------------------------
28
(1 row)
-- We don't currently support colocating with replicated tables
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_replica'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: cannot push down function call for replicated distributed tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
SET client_min_messages TO NOTICE;
drop table mx_call_dist_table_replica;
SET client_min_messages TO DEBUG1;
select colocate_proc_with_table('mx_call_proc', 'mx_call_dist_table_1'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
-- Test that we handle transactional constructs correctly inside a procedure
-- that is routed to the workers.
CREATE PROCEDURE mx_call_proc_tx(x int) LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO multi_mx_call.mx_call_dist_table_1 VALUES (x, -1), (x+1, 4);
COMMIT;
UPDATE multi_mx_call.mx_call_dist_table_1 SET val = val+1 WHERE id >= x;
ROLLBACK;
-- Now do the final update!
UPDATE multi_mx_call.mx_call_dist_table_1 SET val = val-1 WHERE id >= x;
END;$$;
-- before distribution ...
CALL multi_mx_call.mx_call_proc_tx(10);
-- after distribution ...
select create_distributed_function('mx_call_proc_tx(int)', '$1', 'mx_call_dist_table_1');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
CALL multi_mx_call.mx_call_proc_tx(20);
DEBUG: pushing down the procedure
SELECT id, val FROM mx_call_dist_table_1 ORDER BY id, val;
id | val
---------------------------------------------------------------------
3 | 1
3 | 5
4 | 5
6 | 5
9 | 2
10 | -2
11 | 3
20 | -2
21 | 3
(9 rows)
-- Test that we properly propagate errors raised from procedures.
CREATE PROCEDURE mx_call_proc_raise(x int) LANGUAGE plpgsql AS $$
BEGIN
RAISE WARNING 'warning';
RAISE EXCEPTION 'error';
END;$$;
select create_distributed_function('mx_call_proc_raise(int)', '$1', 'mx_call_dist_table_1');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
\set VERBOSITY terse
call multi_mx_call.mx_call_proc_raise(2);
DEBUG: pushing down the procedure
WARNING: warning
ERROR: error
\set VERBOSITY default
-- Test that we don't propagate to non-metadata worker nodes
SET client_min_messages TO WARNING;
select stop_metadata_sync_to_node('localhost', :worker_1_port);
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
select stop_metadata_sync_to_node('localhost', :worker_2_port);
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
SET client_min_messages TO DEBUG1;
call multi_mx_call.mx_call_proc(2, 0);
DEBUG: there is no worker node with metadata
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
SET client_min_messages TO NOTICE;
select start_metadata_sync_to_node('localhost', :worker_1_port);
start_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
select start_metadata_sync_to_node('localhost', :worker_2_port);
start_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
-- stop_metadata_sync_to_node()/start_metadata_sync_to_node() might make
-- worker backend caches inconsistent. Reconnect to coordinator to use
-- new worker connections, hence new backends.
\c - - - :master_port
SET search_path to multi_mx_call, public;
SET client_min_messages TO DEBUG1;
--
-- Test non-const parameter values
--
CREATE FUNCTION mx_call_add(int, int) RETURNS int
AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE;
SELECT create_distributed_function('mx_call_add(int,int)');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
-- non-const distribution parameters cannot be pushed down
call multi_mx_call.mx_call_proc(2, mx_call_add(3, 4));
DEBUG: distribution argument value must be a constant
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
-- non-const parameter can be pushed down
call multi_mx_call.mx_call_proc(multi_mx_call.mx_call_add(3, 4), 2);
DEBUG: pushing down the procedure
y
---------------------------------------------------------------------
33
(1 row)
-- volatile parameter cannot be pushed down
call multi_mx_call.mx_call_proc(floor(random())::int, 2);
DEBUG: arguments in a distributed stored procedure must be constant expressions
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_call.mx_call_dist_table_1 t1 JOIN multi_mx_call.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_call.mx_call_dist_table_1 t1 join multi_mx_call.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_proc(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
27
(1 row)
reset client_min_messages;
\set VERBOSITY terse
drop schema multi_mx_call cascade;
NOTICE: drop cascades to 13 other objects

View File

@ -88,13 +88,11 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Node Type": "Aggregate",
"Strategy": "Hashed",
"Partial Mode": "Simple",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Group Key": ["remote_scan.l_quantity"],
"Plans": [
{
"Node Type": "Custom Scan",
"Parent Relationship": "Outer",
"Custom Plan Provider": "Citus Adaptive",
"Parallel Aware": false,
"Distributed Query": {
@ -116,7 +114,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "lineitem_mx_1220052",
"Alias": "lineitem_mx"
@ -162,7 +159,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Node-Type>Aggregate</Node-Type>
<Strategy>Hashed</Strategy>
<Partial-Mode>Simple</Partial-Mode>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Group-Key>
<Item>remote_scan.l_quantity</Item>
@ -170,7 +166,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Custom Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Custom-Plan-Provider>Citus Adaptive</Custom-Plan-Provider>
<Parallel-Aware>false</Parallel-Aware>
<Distributed-Query>
@ -194,7 +189,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>lineitem_mx_1220052</Relation-Name>
<Alias>lineitem_mx</Alias>
@ -234,13 +228,11 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- Node Type: "Aggregate"
Strategy: "Hashed"
Partial Mode: "Simple"
Parent Relationship: "Outer"
Parallel Aware: false
Group Key:
- "remote_scan.l_quantity"
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
Custom Plan Provider: "Citus Adaptive"
Parallel Aware: false
Distributed Query:
@ -259,7 +251,6 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
- "l_quantity"
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "lineitem_mx_1220052"
Alias: "lineitem_mx"
@ -537,7 +528,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Custom Scan",
"Parent Relationship": "Outer",
"Custom Plan Provider": "Citus Adaptive",
"Parallel Aware": false,
"Distributed Query": {
@ -558,7 +548,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Hash Join",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Join Type": "Inner",
"Inner Unique": false,
@ -566,7 +555,6 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Hash Join",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Join Type": "Inner",
"Inner Unique": false,
@ -574,19 +562,16 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "supplier_mx_1220087",
"Alias": "supplier_mx"
},
{
"Node Type": "Hash",
"Parent Relationship": "Inner",
"Parallel Aware": false,
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "lineitem_mx_1220052",
"Alias": "lineitem_mx"
@ -597,12 +582,10 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
},
{
"Node Type": "Hash",
"Parent Relationship": "Inner",
"Parallel Aware": false,
"Plans": [
{
"Node Type": "Hash Join",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Join Type": "Inner",
"Inner Unique": false,
@ -610,19 +593,16 @@ EXPLAIN (COSTS FALSE, FORMAT JSON)
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "customer_mx_1220084",
"Alias": "customer_mx"
},
{
"Node Type": "Hash",
"Parent Relationship": "Inner",
"Parallel Aware": false,
"Plans": [
{
"Node Type": "Seq Scan",
"Parent Relationship": "Outer",
"Parallel Aware": false,
"Relation Name": "orders_mx_1220068",
"Alias": "orders_mx"
@ -673,7 +653,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Custom Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Custom-Plan-Provider>Citus Adaptive</Custom-Plan-Provider>
<Parallel-Aware>false</Parallel-Aware>
<Distributed-Query>
@ -694,7 +673,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Hash Join</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Join-Type>Inner</Join-Type>
<Inner-Unique>false</Inner-Unique>
@ -702,7 +680,6 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Hash Join</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Join-Type>Inner</Join-Type>
<Inner-Unique>false</Inner-Unique>
@ -710,19 +687,16 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>supplier_mx_1220087</Relation-Name>
<Alias>supplier_mx</Alias>
</Plan>
<Plan>
<Node-Type>Hash</Node-Type>
<Parent-Relationship>Inner</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>lineitem_mx_1220052</Relation-Name>
<Alias>lineitem_mx</Alias>
@ -733,12 +707,10 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
</Plan>
<Plan>
<Node-Type>Hash</Node-Type>
<Parent-Relationship>Inner</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Plans>
<Plan>
<Node-Type>Hash Join</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Join-Type>Inner</Join-Type>
<Inner-Unique>false</Inner-Unique>
@ -746,19 +718,16 @@ EXPLAIN (COSTS FALSE, FORMAT XML)
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>customer_mx_1220084</Relation-Name>
<Alias>customer_mx</Alias>
</Plan>
<Plan>
<Node-Type>Hash</Node-Type>
<Parent-Relationship>Inner</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Plans>
<Plan>
<Node-Type>Seq Scan</Node-Type>
<Parent-Relationship>Outer</Parent-Relationship>
<Parallel-Aware>false</Parallel-Aware>
<Relation-Name>orders_mx_1220068</Relation-Name>
<Alias>orders_mx</Alias>
@ -805,7 +774,6 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Parallel Aware: false
Plans:
- Node Type: "Custom Scan"
Parent Relationship: "Outer"
Custom Plan Provider: "Citus Adaptive"
Parallel Aware: false
Distributed Query:
@ -822,55 +790,45 @@ EXPLAIN (COSTS FALSE, FORMAT YAML)
Parallel Aware: false
Plans:
- Node Type: "Hash Join"
Parent Relationship: "Outer"
Parallel Aware: false
Join Type: "Inner"
Inner Unique: false
Hash Cond: "(lineitem_mx.l_orderkey = orders_mx.o_orderkey)"
Plans:
- Node Type: "Hash Join"
Parent Relationship: "Outer"
Parallel Aware: false
Join Type: "Inner"
Inner Unique: false
Hash Cond: "(supplier_mx.s_suppkey = lineitem_mx.l_suppkey)"
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "supplier_mx_1220087"
Alias: "supplier_mx"
- Node Type: "Hash"
Parent Relationship: "Inner"
Parallel Aware: false
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "lineitem_mx_1220052"
Alias: "lineitem_mx"
- Node Type: "Hash"
Parent Relationship: "Inner"
Parallel Aware: false
Plans:
- Node Type: "Hash Join"
Parent Relationship: "Outer"
Parallel Aware: false
Join Type: "Inner"
Inner Unique: false
Hash Cond: "(customer_mx.c_custkey = orders_mx.o_custkey)"
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "customer_mx_1220084"
Alias: "customer_mx"
- Node Type: "Hash"
Parent Relationship: "Inner"
Parallel Aware: false
Plans:
- Node Type: "Seq Scan"
Parent Relationship: "Outer"
Parallel Aware: false
Relation Name: "orders_mx_1220068"
Alias: "orders_mx"

View File

@ -143,10 +143,10 @@ SET client_min_messages TO DEBUG1;
select mx_call_func(2, 0);
DEBUG: function does not have co-located tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -230,26 +230,33 @@ DEBUG: pushing down the function call
(S,S)
(1 row)
-- This is currently an undetected failure when using the binary protocol
-- It should not be enabled by default until this is resolved. The tests above
-- will fail too, when changing the default to TRUE;
-- this is fixed with pg14 and this will fail prior to
-- pg 14
SET citus.enable_binary_protocol = TRUE;
select mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
ERROR: wrong data type: XXXX, expected XXXX
mx_call_func_custom_types
---------------------------------------------------------------------
(S,S)
(1 row)
select multi_mx_function_call_delegation.mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
ERROR: wrong data type: XXXX, expected XXXX
mx_call_func_custom_types
---------------------------------------------------------------------
(S,S)
(1 row)
RESET citus.enable_binary_protocol;
-- We don't allow distributing calls inside transactions
begin;
select mx_call_func(2, 0);
DEBUG: not pushing down function calls in a multi-statement transaction
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -280,10 +287,10 @@ select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass
select mx_call_func(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -299,10 +306,10 @@ select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass
select mx_call_func(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -333,10 +340,10 @@ select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_replica'::re
select mx_call_func(2, 0);
DEBUG: cannot push down function call for replicated distributed tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -515,10 +522,10 @@ SET client_min_messages TO DEBUG1;
select mx_call_func(2, 0);
DEBUG: the worker node does not have metadata
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -562,10 +569,10 @@ DETAIL: A distributed function is created. To make sure subsequent commands see
select mx_call_func((select x + 1 from mx_call_add(3, 4) x), 2);
DEBUG: arguments in a distributed function must not contain subqueries
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (9 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((9 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -576,10 +583,10 @@ PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
select mx_call_func(floor(random())::int, 2);
DEBUG: arguments in a distributed function must be constant expressions
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -589,10 +596,10 @@ PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
-- test forms we don't distribute
select * from mx_call_func(2, 0);
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
@ -615,10 +622,10 @@ select mx_call_func(2, 0) from mx_call_dist_table_1;
select mx_call_func(2, 0) where mx_call_func(0, 2) = 0;
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
@ -626,16 +633,16 @@ PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
select mx_call_func(2, 0), mx_call_func(0, 2);
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT ((1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint))))::integer
CONTEXT: PL/pgSQL assignment "y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func | mx_call_func
---------------------------------------------------------------------

View File

@ -0,0 +1,724 @@
-- Test passing off function call to mx workers
CREATE SCHEMA multi_mx_function_call_delegation;
SET search_path TO multi_mx_function_call_delegation, public;
SET citus.shard_replication_factor TO 2;
-- This table requires specific settings, create before getting into things
create table mx_call_dist_table_replica(id int, val int);
select create_distributed_table('mx_call_dist_table_replica', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_replica values (9,1),(8,2),(7,3),(6,4),(5,5);
SET citus.shard_replication_factor TO 1;
--
-- Create tables and functions we want to use in tests
--
create table mx_call_dist_table_1(id int, val int);
select create_distributed_table('mx_call_dist_table_1', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_1 values (3,1),(4,5),(9,2),(6,5),(3,5);
create table mx_call_dist_table_2(id int, val int);
select create_distributed_table('mx_call_dist_table_2', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_2 values (1,1),(1,2),(2,2),(3,3),(3,4);
create table mx_call_dist_table_bigint(id bigint, val bigint);
select create_distributed_table('mx_call_dist_table_bigint', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_bigint values (1,1),(1,2),(2,2),(3,3),(3,4);
create table mx_call_dist_table_ref(id int, val int);
select create_reference_table('mx_call_dist_table_ref');
create_reference_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_ref values (2,7),(1,8),(2,8),(1,8),(2,8);
create type mx_call_enum as enum ('A', 'S', 'D', 'F');
create table mx_call_dist_table_enum(id int, key mx_call_enum);
select create_distributed_table('mx_call_dist_table_enum', 'key');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into mx_call_dist_table_enum values (1,'S'),(2,'A'),(3,'D'),(4,'F');
CREATE FUNCTION squares(int) RETURNS SETOF RECORD
AS $$ SELECT i, i * i FROM generate_series(1, $1) i $$
LANGUAGE SQL;
CREATE FUNCTION mx_call_func(x int, INOUT y int)
LANGUAGE plpgsql AS $$
BEGIN
-- groupid is 0 in coordinator and non-zero in workers, so by using it here
-- we make sure the function is being executed in the worker.
y := x + (select case groupid when 0 then 1 else 0 end from pg_dist_local_group);
-- we also make sure that we can run distributed queries in the functions
-- that are routed to the workers.
y := y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id);
END;$$;
CREATE FUNCTION mx_call_func_bigint(x bigint, INOUT y bigint)
LANGUAGE plpgsql AS $$
BEGIN
y := x + y * 2;
END;$$;
-- create another function which verifies:
-- 1. we work fine with multiple return columns
-- 2. we work fine in combination with custom types
CREATE FUNCTION mx_call_func_custom_types(INOUT x mx_call_enum, INOUT y mx_call_enum)
LANGUAGE plpgsql AS $$
BEGIN
y := x;
x := (select case groupid when 0 then 'F' else 'S' end from pg_dist_local_group);
END;$$;
-- Test that undistributed functions have no issue executing
select multi_mx_function_call_delegation.mx_call_func(2, 0);
mx_call_func
---------------------------------------------------------------------
29
(1 row)
select multi_mx_function_call_delegation.mx_call_func_custom_types('S', 'A');
mx_call_func_custom_types
---------------------------------------------------------------------
(F,S)
(1 row)
select squares(4);
squares
---------------------------------------------------------------------
(1,1)
(2,4)
(3,9)
(4,16)
(4 rows)
-- Same for unqualified name
select mx_call_func(2, 0);
mx_call_func
---------------------------------------------------------------------
29
(1 row)
-- Mark both functions as distributed ...
select create_distributed_function('mx_call_func(int,int)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
select create_distributed_function('mx_call_func_bigint(bigint,bigint)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
select create_distributed_function('mx_call_func_custom_types(mx_call_enum,mx_call_enum)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
select create_distributed_function('squares(int)');
create_distributed_function
---------------------------------------------------------------------
(1 row)
-- We still don't route them to the workers, because they aren't
-- colocated with any distributed tables.
SET client_min_messages TO DEBUG1;
select mx_call_func(2, 0);
DEBUG: function does not have co-located tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
select multi_mx_function_call_delegation.mx_call_func_bigint(4, 2);
DEBUG: function does not have co-located tables
mx_call_func_bigint
---------------------------------------------------------------------
8
(1 row)
select mx_call_func_custom_types('S', 'A');
DEBUG: function does not have co-located tables
mx_call_func_custom_types
---------------------------------------------------------------------
(F,S)
(1 row)
-- Mark them as colocated with a table. Now we should route them to workers.
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select colocate_proc_with_table('mx_call_func_bigint', 'mx_call_dist_table_bigint'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select colocate_proc_with_table('mx_call_func_custom_types', 'mx_call_dist_table_enum'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select colocate_proc_with_table('squares', 'mx_call_dist_table_2'::regclass, 0);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select mx_call_func(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
select mx_call_func_bigint(4, 2);
DEBUG: pushing down the function call
mx_call_func_bigint
---------------------------------------------------------------------
8
(1 row)
select mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
mx_call_func_custom_types
---------------------------------------------------------------------
(S,S)
(1 row)
select squares(4);
DEBUG: pushing down the function call
ERROR: input of anonymous composite types is not implemented
select multi_mx_function_call_delegation.mx_call_func(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
select multi_mx_function_call_delegation.mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
mx_call_func_custom_types
---------------------------------------------------------------------
(S,S)
(1 row)
-- this is fixed with pg14 and this will fail prior to
-- pg 14
SET citus.enable_binary_protocol = TRUE;
select mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
ERROR: wrong data type: XXXX, expected XXXX
select multi_mx_function_call_delegation.mx_call_func_custom_types('S', 'A');
DEBUG: pushing down the function call
ERROR: wrong data type: XXXX, expected XXXX
RESET citus.enable_binary_protocol;
-- We don't allow distributing calls inside transactions
begin;
select mx_call_func(2, 0);
DEBUG: not pushing down function calls in a multi-statement transaction
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
commit;
-- Drop the table colocated with mx_call_func_custom_types. Now it shouldn't
-- be routed to workers anymore.
SET client_min_messages TO NOTICE;
drop table mx_call_dist_table_enum;
SET client_min_messages TO DEBUG1;
select mx_call_func_custom_types('S', 'A');
DEBUG: function does not have co-located tables
mx_call_func_custom_types
---------------------------------------------------------------------
(F,S)
(1 row)
-- Make sure we do bounds checking on distributed argument index
-- This also tests that we have cache invalidation for pg_dist_object updates
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass, -1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select mx_call_func(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass, 2);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select mx_call_func(2, 0);
DEBUG: cannot push down invalid distribution_argument_index
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
-- We don't currently support colocating with reference tables
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_ref'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select mx_call_func(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
-- We don't currently support colocating with replicated tables
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_replica'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
select mx_call_func(2, 0);
DEBUG: cannot push down function call for replicated distributed tables
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
SET client_min_messages TO NOTICE;
drop table mx_call_dist_table_replica;
SET client_min_messages TO DEBUG1;
select colocate_proc_with_table('mx_call_func', 'mx_call_dist_table_1'::regclass, 1);
colocate_proc_with_table
---------------------------------------------------------------------
(1 row)
-- Test table returning functions.
CREATE FUNCTION mx_call_func_tbl(x int)
RETURNS TABLE (p0 int, p1 int)
LANGUAGE plpgsql AS $$
BEGIN
INSERT INTO multi_mx_function_call_delegation.mx_call_dist_table_1 VALUES (x, -1), (x+1, 4);
UPDATE multi_mx_function_call_delegation.mx_call_dist_table_1 SET val = val+1 WHERE id >= x;
UPDATE multi_mx_function_call_delegation.mx_call_dist_table_1 SET val = val-1 WHERE id >= x;
RETURN QUERY
SELECT id, val
FROM multi_mx_function_call_delegation.mx_call_dist_table_1 t
WHERE id >= x
ORDER BY 1, 2;
END;$$;
-- before distribution ...
select mx_call_func_tbl(10);
mx_call_func_tbl
---------------------------------------------------------------------
(10,-1)
(11,4)
(2 rows)
-- after distribution ...
select create_distributed_function('mx_call_func_tbl(int)', '$1', 'mx_call_dist_table_1');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
select mx_call_func_tbl(20);
DEBUG: pushing down the function call
mx_call_func_tbl
---------------------------------------------------------------------
(20,-1)
(21,4)
(2 rows)
-- Test that we properly propagate errors raised from procedures.
CREATE FUNCTION mx_call_func_raise(x int)
RETURNS void LANGUAGE plpgsql AS $$
BEGIN
RAISE WARNING 'warning';
RAISE EXCEPTION 'error';
END;$$;
select create_distributed_function('mx_call_func_raise(int)', '$1', 'mx_call_dist_table_1');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
\set VERBOSITY terse
select mx_call_func_raise(2);
DEBUG: pushing down the function call
WARNING: warning
ERROR: error
\set VERBOSITY default
-- Don't push-down when doing INSERT INTO ... SELECT func();
SET client_min_messages TO ERROR;
CREATE TABLE test (x int primary key);
SELECT create_distributed_table('test','x');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE OR REPLACE FUNCTION delegated_function(a int)
RETURNS int
LANGUAGE plpgsql
AS $function$
DECLARE
BEGIN
INSERT INTO multi_mx_function_call_delegation.test VALUES (a);
INSERT INTO multi_mx_function_call_delegation.test VALUES (a + 1);
RETURN a+2;
END;
$function$;
SELECT create_distributed_function('delegated_function(int)', 'a');
create_distributed_function
---------------------------------------------------------------------
(1 row)
SET client_min_messages TO DEBUG1;
INSERT INTO test SELECT delegated_function(1);
DEBUG: distributed INSERT ... SELECT can only select from distributed tables
DEBUG: not pushing down function calls in INSERT ... SELECT
DEBUG: Collecting INSERT ... SELECT results on coordinator
-- Don't push down in subqueries or CTEs.
SELECT * FROM test WHERE not exists(
SELECT delegated_function(4)
);
DEBUG: not pushing down function calls in CTEs or Subqueries
DEBUG: generating subplan XXX_1 for subquery SELECT multi_mx_function_call_delegation.delegated_function(4) AS delegated_function
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT x FROM multi_mx_function_call_delegation.test WHERE (NOT (EXISTS (SELECT intermediate_result.delegated_function FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(delegated_function integer))))
x
---------------------------------------------------------------------
(0 rows)
WITH r AS (
SELECT delegated_function(7)
) SELECT * FROM test WHERE (SELECT count(*)=0 FROM r);
DEBUG: generating subplan XXX_1 for CTE r: SELECT multi_mx_function_call_delegation.delegated_function(7) AS delegated_function
DEBUG: not pushing down function calls in CTEs or Subqueries
DEBUG: generating subplan XXX_2 for subquery SELECT (count(*) OPERATOR(pg_catalog.=) 0) FROM (SELECT intermediate_result.delegated_function FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(delegated_function integer)) r
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT x FROM multi_mx_function_call_delegation.test WHERE (SELECT intermediate_result."?column?" FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result("?column?" boolean))
x
---------------------------------------------------------------------
(0 rows)
WITH r AS (
SELECT delegated_function(10)
), t AS (
SELECT count(*) c FROM r
) SELECT * FROM test, t WHERE t.c=0;
DEBUG: CTE t is going to be inlined via distributed planning
DEBUG: generating subplan XXX_1 for CTE r: SELECT multi_mx_function_call_delegation.delegated_function(10) AS delegated_function
DEBUG: not pushing down function calls in CTEs or Subqueries
DEBUG: generating subplan XXX_2 for subquery SELECT count(*) AS c FROM (SELECT intermediate_result.delegated_function FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(delegated_function integer)) r
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test.x, t.c FROM multi_mx_function_call_delegation.test, (SELECT intermediate_result.c FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(c bigint)) t WHERE (t.c OPERATOR(pg_catalog.=) 0)
x | c
---------------------------------------------------------------------
(0 rows)
WITH r AS (
SELECT count(*) FROM test
), s AS (
SELECT delegated_function(13)
), t AS (
SELECT count(*) c FROM s
) SELECT * FROM test, r, t WHERE t.c=0;
DEBUG: CTE r is going to be inlined via distributed planning
DEBUG: CTE t is going to be inlined via distributed planning
DEBUG: generating subplan XXX_1 for CTE s: SELECT multi_mx_function_call_delegation.delegated_function(13) AS delegated_function
DEBUG: not pushing down function calls in CTEs or Subqueries
DEBUG: generating subplan XXX_2 for subquery SELECT count(*) AS count FROM multi_mx_function_call_delegation.test
DEBUG: generating subplan XXX_3 for subquery SELECT count(*) AS c FROM (SELECT intermediate_result.delegated_function FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(delegated_function integer)) s
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT test.x, r.count, t.c FROM multi_mx_function_call_delegation.test, (SELECT intermediate_result.count FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(count bigint)) r, (SELECT intermediate_result.c FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(c bigint)) t WHERE (t.c OPERATOR(pg_catalog.=) 0)
x | count | c
---------------------------------------------------------------------
(0 rows)
-- Test that we don't propagate to non-metadata worker nodes
SET client_min_messages TO WARNING;
select stop_metadata_sync_to_node('localhost', :worker_1_port);
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
select stop_metadata_sync_to_node('localhost', :worker_2_port);
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
SET client_min_messages TO DEBUG1;
select mx_call_func(2, 0);
DEBUG: the worker node does not have metadata
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
29
(1 row)
SET client_min_messages TO NOTICE;
select start_metadata_sync_to_node('localhost', :worker_1_port);
start_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
select start_metadata_sync_to_node('localhost', :worker_2_port);
start_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
-- stop_metadata_sync_to_node()/start_metadata_sync_to_node() might make
-- worker backend caches inconsistent. Reconnect to coordinator to use
-- new worker connections, hence new backends.
\c - - - :master_port
SET search_path to multi_mx_function_call_delegation, public;
SET client_min_messages TO DEBUG1;
SET citus.shard_replication_factor = 1;
--
-- Test non-const parameter values
--
CREATE FUNCTION mx_call_add(int, int) RETURNS int
AS 'select $1 + $2;' LANGUAGE SQL IMMUTABLE;
SELECT create_distributed_function('mx_call_add(int,int)', '$1');
DEBUG: switching to sequential query execution mode
DETAIL: A distributed function is created. To make sure subsequent commands see the type correctly we need to make sure to use only one connection for all future commands
create_distributed_function
---------------------------------------------------------------------
(1 row)
-- subquery parameters cannot be pushed down
select mx_call_func((select x + 1 from mx_call_add(3, 4) x), 2);
DEBUG: arguments in a distributed function must not contain subqueries
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (9 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
35
(1 row)
-- volatile parameter cannot be pushed down
select mx_call_func(floor(random())::int, 2);
DEBUG: arguments in a distributed function must be constant expressions
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
27
(1 row)
-- test forms we don't distribute
select * from mx_call_func(2, 0);
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
y
---------------------------------------------------------------------
29
(1 row)
select mx_call_func(2, 0) from mx_call_dist_table_1;
mx_call_func
---------------------------------------------------------------------
28
28
28
28
28
28
28
28
28
(9 rows)
select mx_call_func(2, 0) where mx_call_func(0, 2) = 0;
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func
---------------------------------------------------------------------
(0 rows)
select mx_call_func(2, 0), mx_call_func(0, 2);
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (3 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: generating subplan XXX_1 for subquery SELECT sum((t1.val OPERATOR(pg_catalog.+) t2.val)) AS sum FROM (multi_mx_function_call_delegation.mx_call_dist_table_1 t1 JOIN multi_mx_function_call_delegation.mx_call_dist_table_2 t2 ON ((t1.id OPERATOR(pg_catalog.=) t2.id)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT (1 OPERATOR(pg_catalog.+) (SELECT intermediate_result.sum FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(sum bigint)))
CONTEXT: SQL statement "SELECT y + (select sum(t1.val + t2.val) from multi_mx_function_call_delegation.mx_call_dist_table_1 t1 join multi_mx_function_call_delegation.mx_call_dist_table_2 t2 on t1.id = t2.id)"
PL/pgSQL function mx_call_func(integer,integer) line 8 at assignment
mx_call_func | mx_call_func
---------------------------------------------------------------------
29 | 27
(1 row)
DO $$ BEGIN perform mx_call_func_tbl(40); END; $$;
DEBUG: not pushing down function calls in a multi-statement transaction
CONTEXT: SQL statement "SELECT mx_call_func_tbl(40)"
PL/pgSQL function inline_code_block line 1 at PERFORM
SELECT * FROM mx_call_dist_table_1 WHERE id >= 40 ORDER BY id, val;
id | val
---------------------------------------------------------------------
40 | -1
41 | 4
(2 rows)
-- Prepared statements. Repeat 8 times to test for generic plans
PREPARE call_plan (int, int) AS SELECT mx_call_func($1, $2);
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
EXECUTE call_plan(2, 0);
DEBUG: pushing down the function call
mx_call_func
---------------------------------------------------------------------
28
(1 row)
\c - - - :worker_1_port
SET search_path TO multi_mx_function_call_delegation, public;
-- create_distributed_function is disallowed from worker nodes
select create_distributed_function('mx_call_func(int,int)');
ERROR: operation is not allowed on this node
HINT: Connect to the coordinator and run it again.
\c - - - :master_port
SET search_path TO multi_mx_function_call_delegation, public;
RESET client_min_messages;
\set VERBOSITY terse
DROP SCHEMA multi_mx_function_call_delegation CASCADE;
NOTICE: drop cascades to 14 other objects

View File

@ -1616,194 +1616,6 @@ SELECT * FROM lockinfo;
(20 rows)
COMMIT;
-- test partition-wise join
CREATE TABLE partitioning_hash_join_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_join_test_0 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_join_test_1 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
CREATE TABLE partitioning_hash_join_test_2 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 2);
SELECT create_distributed_table('partitioning_hash_join_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT success FROM run_command_on_workers('alter system set enable_mergejoin to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_nestloop to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexonlyscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(16 rows)
-- set partition-wise join on and parallel to off
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to on');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
SET enable_partitionwise_join TO on;
ANALYZE partitioning_hash_test, partitioning_hash_join_test;
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Append
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Hash Join
Hash Cond: ((partitioning_hash_test_xxx.id = partitioning_hash_join_test_xxx.id) AND (partitioning_hash_test_xxx.subid = partitioning_hash_join_test_xxx.subid))
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(21 rows)
-- note that partition-wise joins only work when partition key is in the join
-- following join does not have that, therefore join will not be pushed down to
-- partitions
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: (partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id)
-> Append
-> Seq Scan on partitioning_hash_join_test_0_1660133 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_1660137 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_1660141 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_1660016 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_1660020 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_2_1660032 partitioning_hash_test_xxx
(16 rows)
-- reset partition-wise join
SELECT success FROM run_command_on_workers('alter system reset enable_partitionwise_join');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_mergejoin');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_nestloop');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexonlyscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
RESET enable_partitionwise_join;
DROP VIEW lockinfo;
DROP TABLE
IF EXISTS
@ -2069,10 +1881,9 @@ SELECT fix_pre_citus10_partitioned_table_constraint_names();
---------------------------------------------------------------------
partitioning_test
"schema-test"
public.partitioning_hash_join_test
public.partitioning_hash_test
public.partitioning_test_failure
(5 rows)
(4 rows)
-- the following should fail
SELECT fix_pre_citus10_partitioned_table_constraint_names('public.non_distributed_partitioned_table');
@ -2248,7 +2059,6 @@ drop cascades to table distributed_parent_table
RESET search_path;
DROP TABLE IF EXISTS
partitioning_hash_test,
partitioning_hash_join_test,
partitioning_test_failure,
non_distributed_partitioned_table,
partitioning_test_foreign_key;

View File

@ -675,7 +675,7 @@ LIMIT
2 | 1
(5 rows)
EXPLAIN (COSTS FALSE, VERBOSE TRUE)
EXPLAIN (COSTS FALSE)
SELECT *
FROM (
( SELECT user_id,
@ -709,72 +709,49 @@ EXPLAIN (COSTS FALSE, VERBOSE TRUE)
user_id)) AS ftop
ORDER BY 2 DESC, 1 DESC
LIMIT 5;
QUERY PLAN
QUERY PLAN
---------------------------------------------------------------------
Limit
Output: remote_scan.user_id, remote_scan.sum
-> Sort
Output: remote_scan.user_id, remote_scan.sum
Sort Key: remote_scan.sum DESC, remote_scan.user_id DESC
-> Custom Scan (Citus Adaptive)
Output: remote_scan.user_id, remote_scan.sum
Task Count: 4
Tasks Shown: One of 4
-> Task
Query: SELECT worker_column_1 AS user_id, worker_column_2 AS sum FROM (SELECT ftop.user_id AS worker_column_1, ftop.sum AS worker_column_2 FROM (SELECT user_id_1.user_id, sum(user_id_1.counter) AS sum FROM (SELECT users_table.user_id, sum(users_table.value_2) OVER (PARTITION BY users_table.user_id) AS counter FROM public.users_table_1400256 users_table UNION SELECT events_table.user_id, sum(events_table.value_2) OVER (PARTITION BY events_table.user_id) AS counter FROM public.events_table_1400260 events_table) user_id_1 GROUP BY user_id_1.user_id UNION SELECT user_id_2.user_id, sum(user_id_2.counter) AS sum FROM (SELECT users_table.user_id, sum(users_table.value_2) OVER (PARTITION BY users_table.user_id) AS counter FROM public.users_table_1400256 users_table UNION SELECT events_table.user_id, sum(events_table.value_2) OVER (PARTITION BY events_table.user_id) AS counter FROM public.events_table_1400260 events_table) user_id_2 GROUP BY user_id_2.user_id) ftop) worker_subquery ORDER BY worker_column_2 DESC, worker_column_1 DESC LIMIT '5'::bigint
Node: host=localhost port=xxxxx dbname=regression
-> Limit
Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?))))
-> Sort
Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?))))
Sort Key: (sum((sum(users_table.value_2) OVER (?)))) DESC, users_table.user_id DESC
-> HashAggregate
Output: users_table.user_id, (sum((sum(users_table.value_2) OVER (?))))
Group Key: users_table.user_id, (sum((sum(users_table.value_2) OVER (?))))
-> Append
-> HashAggregate
Output: users_table.user_id, sum((sum(users_table.value_2) OVER (?)))
Group Key: users_table.user_id
-> HashAggregate
Output: users_table.user_id, (sum(users_table.value_2) OVER (?))
Group Key: users_table.user_id, (sum(users_table.value_2) OVER (?))
-> Append
-> WindowAgg
Output: users_table.user_id, sum(users_table.value_2) OVER (?)
-> Sort
Output: users_table.user_id, users_table.value_2
Sort Key: users_table.user_id
-> Seq Scan on public.users_table_1400256 users_table
Output: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
-> WindowAgg
Output: events_table.user_id, sum(events_table.value_2) OVER (?)
-> Sort
Output: events_table.user_id, events_table.value_2
Sort Key: events_table.user_id
-> Seq Scan on public.events_table_1400260 events_table
Output: events_table.user_id, events_table.value_2
-> Seq Scan on events_table_1400260 events_table
-> HashAggregate
Output: users_table_1.user_id, sum((sum(users_table_1.value_2) OVER (?)))
Group Key: users_table_1.user_id
-> HashAggregate
Output: users_table_1.user_id, (sum(users_table_1.value_2) OVER (?))
Group Key: users_table_1.user_id, (sum(users_table_1.value_2) OVER (?))
-> Append
-> WindowAgg
Output: users_table_1.user_id, sum(users_table_1.value_2) OVER (?)
-> Sort
Output: users_table_1.user_id, users_table_1.value_2
Sort Key: users_table_1.user_id
-> Seq Scan on public.users_table_1400256 users_table_1
Output: users_table_1.user_id, users_table_1.value_2
-> Seq Scan on users_table_1400256 users_table_1
-> WindowAgg
Output: events_table_1.user_id, sum(events_table_1.value_2) OVER (?)
-> Sort
Output: events_table_1.user_id, events_table_1.value_2
Sort Key: events_table_1.user_id
-> Seq Scan on public.events_table_1400260 events_table_1
Output: events_table_1.user_id, events_table_1.value_2
(63 rows)
-> Seq Scan on events_table_1400260 events_table_1
(40 rows)
-- test with window functions which aren't pushed down
SELECT

View File

@ -57,6 +57,20 @@ BEGIN
END LOOP;
RETURN false;
END; $$ language plpgsql;
--helper function to check there is a single task
CREATE OR REPLACE FUNCTION explain_has_single_task(explain_command text)
RETURNS BOOLEAN AS $$
DECLARE
query_plan text;
BEGIN
FOR query_plan IN EXECUTE explain_command LOOP
IF query_plan ILIKE '%Task Count: 1%'
THEN
RETURN true;
END IF;
END LOOP;
RETURN false;
END; $$ language plpgsql;
-- helper function to quickly run SQL on the whole cluster
CREATE OR REPLACE FUNCTION run_command_on_coordinator_and_workers(p_sql text)
RETURNS void LANGUAGE plpgsql AS $$

View File

@ -0,0 +1,209 @@
CREATE SCHEMA partition_wise_join;
SET search_path to partition_wise_join;
SET citus.next_shard_id TO 360147;
CREATE TABLE partitioning_hash_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_test_0 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_test_1 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
INSERT INTO partitioning_hash_test VALUES (1, 2);
INSERT INTO partitioning_hash_test VALUES (2, 13);
INSERT INTO partitioning_hash_test VALUES (3, 7);
INSERT INTO partitioning_hash_test VALUES (4, 4);
-- distribute partitioned table
SELECT create_distributed_table('partitioning_hash_test', 'id');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$partition_wise_join.partitioning_hash_test_0$$)
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$partition_wise_join.partitioning_hash_test_1$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- test partition-wise join
CREATE TABLE partitioning_hash_join_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_join_test_0 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_join_test_1 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
CREATE TABLE partitioning_hash_join_test_2 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 2);
SELECT create_distributed_table('partitioning_hash_join_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT success FROM run_command_on_workers('alter system set enable_mergejoin to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_nestloop to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexonlyscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
(15 rows)
-- set partition-wise join on and parallel to off
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to on');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
-- SET enable_partitionwise_join TO on;
ANALYZE partitioning_hash_test, partitioning_hash_join_test;
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_test_xxx.id = partitioning_hash_join_test_xxx.id) AND (partitioning_hash_test_xxx.subid = partitioning_hash_join_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
(15 rows)
-- note that partition-wise joins only work when partition key is in the join
-- following join does not have that, therefore join will not be pushed down to
-- partitions
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: (partitioning_hash_test_xxx.id = partitioning_hash_join_test_xxx.id)
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
(15 rows)
-- reset partition-wise join
SELECT success FROM run_command_on_workers('alter system reset enable_partitionwise_join');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_mergejoin');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_nestloop');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexonlyscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
RESET enable_partitionwise_join;
DROP SCHEMA partition_wise_join CASCADE;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table partitioning_hash_test
drop cascades to table partitioning_hash_join_test

View File

@ -0,0 +1,209 @@
CREATE SCHEMA partition_wise_join;
SET search_path to partition_wise_join;
SET citus.next_shard_id TO 360147;
CREATE TABLE partitioning_hash_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_test_0 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_test_1 PARTITION OF partitioning_hash_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
INSERT INTO partitioning_hash_test VALUES (1, 2);
INSERT INTO partitioning_hash_test VALUES (2, 13);
INSERT INTO partitioning_hash_test VALUES (3, 7);
INSERT INTO partitioning_hash_test VALUES (4, 4);
-- distribute partitioned table
SELECT create_distributed_table('partitioning_hash_test', 'id');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$partition_wise_join.partitioning_hash_test_0$$)
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$partition_wise_join.partitioning_hash_test_1$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- test partition-wise join
CREATE TABLE partitioning_hash_join_test(id int, subid int) PARTITION BY HASH(subid);
CREATE TABLE partitioning_hash_join_test_0 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 0);
CREATE TABLE partitioning_hash_join_test_1 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 1);
CREATE TABLE partitioning_hash_join_test_2 PARTITION OF partitioning_hash_join_test FOR VALUES WITH (MODULUS 3, REMAINDER 2);
SELECT create_distributed_table('partitioning_hash_join_test', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT success FROM run_command_on_workers('alter system set enable_mergejoin to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_nestloop to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_indexonlyscan to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to off');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
(15 rows)
-- set partition-wise join on and parallel to off
SELECT success FROM run_command_on_workers('alter system set enable_partitionwise_join to on');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
-- SET enable_partitionwise_join TO on;
ANALYZE partitioning_hash_test, partitioning_hash_join_test;
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id, subid);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: ((partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id) AND (partitioning_hash_join_test_xxx.subid = partitioning_hash_test_xxx.subid))
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
(15 rows)
-- note that partition-wise joins only work when partition key is in the join
-- following join does not have that, therefore join will not be pushed down to
-- partitions
EXPLAIN (COSTS OFF)
SELECT * FROM partitioning_hash_test JOIN partitioning_hash_join_test USING (id);
QUERY PLAN
---------------------------------------------------------------------
Custom Scan (Citus Adaptive)
Task Count: 4
Tasks Shown: One of 4
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Hash Join
Hash Cond: (partitioning_hash_join_test_xxx.id = partitioning_hash_test_xxx.id)
-> Append
-> Seq Scan on partitioning_hash_join_test_0_360163 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_1_360167 partitioning_hash_join_test_xxx
-> Seq Scan on partitioning_hash_join_test_2_360171 partitioning_hash_join_test_xxx
-> Hash
-> Append
-> Seq Scan on partitioning_hash_test_0_360151 partitioning_hash_test_xxx
-> Seq Scan on partitioning_hash_test_1_360155 partitioning_hash_test_xxx
(15 rows)
-- reset partition-wise join
SELECT success FROM run_command_on_workers('alter system reset enable_partitionwise_join');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_mergejoin');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_nestloop');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('alter system reset enable_indexonlyscan');
success
---------------------------------------------------------------------
t
t
(2 rows)
SELECT success FROM run_command_on_workers('select pg_reload_conf()');
success
---------------------------------------------------------------------
t
t
(2 rows)
RESET enable_partitionwise_join;
DROP SCHEMA partition_wise_join CASCADE;
NOTICE: drop cascades to 2 other objects
DETAIL: drop cascades to table partitioning_hash_test
drop cascades to table partitioning_hash_join_test

View File

@ -228,39 +228,19 @@ INSERT INTO test_wal VALUES(3,33),(4,44),(5,55) RETURNING *;
(10 rows)
-- make sure WAL works in distributed subplans
-- this test has different output for pg14 and here we mostly test that
-- we don't get an error, hence we use explain_has_distributed_subplan.
SELECT public.explain_has_distributed_subplan(
$$
EXPLAIN (ANALYZE TRUE, WAL TRUE, COSTS FALSE, SUMMARY FALSE, BUFFERS FALSE, TIMING FALSE)
WITH cte_1 AS (INSERT INTO test_wal VALUES(6,66),(7,77),(8,88) RETURNING *)
SELECT * FROM cte_1;
QUERY PLAN
$$
);
explain_has_distributed_subplan
---------------------------------------------------------------------
Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
-> Distributed Subplan XXX_1
Intermediate Data Size: 54 bytes
Result destination: Write locally
-> Custom Scan (Citus Adaptive) (actual rows=3 loops=1)
Task Count: 2
Tuple data received from nodes: 9 bytes
Tasks Shown: All
-> Task
Tuple data received from node: 6 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65012 citus_table_alias (actual rows=2 loops=1)
WAL: records=2 bytes=126
-> Values Scan on "*VALUES*" (actual rows=2 loops=1)
-> Task
Tuple data received from node: 3 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Insert on test_wal_65013 citus_table_alias (actual rows=1 loops=1)
WAL: records=1 bytes=63
-> Result (actual rows=1 loops=1)
Task Count: 1
Tuple data received from nodes: 9 bytes
Tasks Shown: All
-> Task
Tuple data received from node: 9 bytes
Node: host=localhost port=xxxxx dbname=regression
-> Function Scan on read_intermediate_result intermediate_result (actual rows=3 loops=1)
(27 rows)
t
(1 row)
SET client_min_messages TO WARNING;
drop schema test_pg13 cascade;

View File

@ -0,0 +1,633 @@
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int > 13 AS server_version_above_thirteen
\gset
\if :server_version_above_thirteen
\else
\q
\endif
create schema pg14;
set search_path to pg14;
SET citus.next_shard_id TO 980000;
SET citus.shard_count TO 2;
-- test the new vacuum option, process_toast
CREATE TABLE t1 (a int);
SELECT create_distributed_table('t1','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
SET citus.log_remote_commands TO ON;
VACUUM (FULL) t1;
NOTICE: issuing VACUUM (FULL) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
VACUUM (FULL, PROCESS_TOAST) t1;
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
VACUUM (FULL, PROCESS_TOAST true) t1;
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM (FULL,PROCESS_TOAST) pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
VACUUM (FULL, PROCESS_TOAST false) t1;
ERROR: PROCESS_TOAST required with VACUUM FULL
VACUUM (PROCESS_TOAST false) t1;
NOTICE: issuing VACUUM pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM pg14.t1_980000
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing VACUUM pg14.t1_980001
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
SET citus.log_remote_commands TO OFF;
create table dist(a int, b int);
select create_distributed_table('dist','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
create index idx on dist(a);
set citus.log_remote_commands to on;
-- make sure that we send the tablespace option
SET citus.multi_shard_commit_protocol TO '1pc';
SET citus.multi_shard_modify_mode TO 'sequential';
reindex(TABLESPACE test_tablespace) index idx;
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
reindex(TABLESPACE test_tablespace, verbose) index idx;
INFO: index "idx" was reindexed
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
reindex(TABLESPACE test_tablespace, verbose false) index idx ;
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
reindex(verbose, TABLESPACE test_tablespace) index idx ;
INFO: index "idx" was reindexed
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED;SELECT assign_distributed_transaction_id(xx, xx, 'xxxxxxx');
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing REINDEX (VERBOSE, TABLESPACE test_tablespace) INDEX pg14.xxxxx
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
NOTICE: issuing COMMIT
DETAIL: on server postgres@localhost:xxxxx connectionId: xxxxxxx
-- should error saying table space doesn't exist
reindex(TABLESPACE test_tablespace1) index idx;
ERROR: tablespace "test_tablespace1" does not exist
reset citus.log_remote_commands;
-- CREATE STATISTICS only allow simple column references
CREATE TABLE tbl1(a timestamp, b int);
SELECT create_distributed_table('tbl1','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- the last one should error out
CREATE STATISTICS s1 (dependencies) ON a, b FROM tbl1;
CREATE STATISTICS s2 (mcv) ON a, b FROM tbl1;
CREATE STATISTICS s3 (ndistinct) ON date_trunc('month', a), date_trunc('day', a) FROM tbl1;
ERROR: only simple column references are allowed in CREATE STATISTICS
set citus.log_remote_commands to off;
-- error out in case of ALTER TABLE .. DETACH PARTITION .. CONCURRENTLY/FINALIZE
-- only if it's a distributed partitioned table
CREATE TABLE par (a INT UNIQUE) PARTITION BY RANGE(a);
CREATE TABLE par_1 PARTITION OF par FOR VALUES FROM (1) TO (4);
CREATE TABLE par_2 PARTITION OF par FOR VALUES FROM (5) TO (8);
-- works as it's not distributed
ALTER TABLE par DETACH PARTITION par_1 CONCURRENTLY;
-- errors out
SELECT create_distributed_table('par','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
ALTER TABLE par DETACH PARTITION par_2 CONCURRENTLY;
ERROR: ALTER TABLE .. DETACH PARTITION .. CONCURRENTLY commands are currently unsupported.
ALTER TABLE par DETACH PARTITION par_2 FINALIZE;
ERROR: ALTER TABLE .. DETACH PARTITION .. FINALIZE commands are currently unsupported.
-- test column compression propagation in distribution
SET citus.shard_replication_factor TO 1;
CREATE TABLE col_compression (a TEXT COMPRESSION pglz, b TEXT);
SELECT create_distributed_table('col_compression', 'a', shard_count:=4);
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT attname || ' ' || attcompression AS column_compression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'col\_compression%' AND attnum > 0 ORDER BY 1;
column_compression
---------------------------------------------------------------------
a p
b
(2 rows)
SELECT result AS column_compression FROM run_command_on_workers($$SELECT ARRAY(
SELECT attname || ' ' || attcompression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'pg14.col\_compression%' AND attnum > 0 ORDER BY 1
)$$);
column_compression
---------------------------------------------------------------------
{"a p","a p","b ","b "}
{"a p","a p","b ","b "}
(2 rows)
-- test column compression propagation in rebalance
SELECT shardid INTO moving_shard FROM citus_shards WHERE table_name='col_compression'::regclass AND nodeport=:worker_1_port LIMIT 1;
SELECT citus_move_shard_placement((SELECT * FROM moving_shard), :'public_worker_1_host', :worker_1_port, :'public_worker_2_host', :worker_2_port);
citus_move_shard_placement
---------------------------------------------------------------------
(1 row)
SELECT rebalance_table_shards('col_compression', rebalance_strategy := 'by_shard_count');
NOTICE: Moving shard xxxxx from localhost:xxxxx to localhost:xxxxx ...
rebalance_table_shards
---------------------------------------------------------------------
(1 row)
CALL citus_cleanup_orphaned_shards();
NOTICE: cleaned up 1 orphaned shards
SELECT result AS column_compression FROM run_command_on_workers($$SELECT ARRAY(
SELECT attname || ' ' || attcompression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'pg14.col\_compression%' AND attnum > 0 ORDER BY 1
)$$);
column_compression
---------------------------------------------------------------------
{"a p","a p","b ","b "}
{"a p","a p","b ","b "}
(2 rows)
-- test propagation of ALTER TABLE .. ALTER COLUMN .. SET COMPRESSION ..
ALTER TABLE col_compression ALTER COLUMN b SET COMPRESSION pglz;
ALTER TABLE col_compression ALTER COLUMN a SET COMPRESSION default;
SELECT result AS column_compression FROM run_command_on_workers($$SELECT ARRAY(
SELECT attname || ' ' || attcompression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'pg14.col\_compression%' AND attnum > 0 ORDER BY 1
)$$);
column_compression
---------------------------------------------------------------------
{"a ","a ","b p","b p"}
{"a ","a ","b p","b p"}
(2 rows)
-- test propagation of ALTER TABLE .. ADD COLUMN .. COMPRESSION ..
ALTER TABLE col_compression ADD COLUMN c TEXT COMPRESSION pglz;
SELECT result AS column_compression FROM run_command_on_workers($$SELECT ARRAY(
SELECT attname || ' ' || attcompression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'pg14.col\_compression%' AND attnum > 0 ORDER BY 1
)$$);
column_compression
---------------------------------------------------------------------
{"a ","a ","b p","b p","c p","c p"}
{"a ","a ","b p","b p","c p","c p"}
(2 rows)
-- test attaching to a partitioned table with column compression
CREATE TABLE col_comp_par (a TEXT COMPRESSION pglz, b TEXT) PARTITION BY RANGE (a);
SELECT create_distributed_table('col_comp_par', 'a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
CREATE TABLE col_comp_par_1 PARTITION OF col_comp_par FOR VALUES FROM ('abc') TO ('def');
SELECT result AS column_compression FROM run_command_on_workers($$SELECT ARRAY(
SELECT attname || ' ' || attcompression FROM pg_attribute WHERE attrelid::regclass::text LIKE 'pg14.col\_comp\_par\_1\_%' AND attnum > 0 ORDER BY 1
)$$);
column_compression
---------------------------------------------------------------------
{"a p","b "}
{"a p","b "}
(2 rows)
RESET citus.multi_shard_modify_mode;
-- test procedure OUT parameters with procedure pushdown
CREATE TABLE test_proc_table (a int);
create or replace procedure proc_pushdown(dist_key integer, OUT created int4[], OUT res_out text)
language plpgsql
as $$
DECLARE
res INT := 0;
begin
INSERT INTO pg14.test_proc_table VALUES (dist_key);
SELECT count(*) INTO res FROM pg14.test_proc_table;
created := created || res;
PERFORM array_prepend(res, created);
res_out := res::text;
commit;
end;$$;
-- show the behaviour before distributing
CALL proc_pushdown(1, NULL, NULL);
created | res_out
---------------------------------------------------------------------
{1} | 1
(1 row)
CALL proc_pushdown(1, ARRAY[2000,1], 'AAAA');
created | res_out
---------------------------------------------------------------------
{2} | 2
(1 row)
SELECT create_distributed_table('test_proc_table', 'a');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg14.test_proc_table$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_function('proc_pushdown(integer)', 'dist_key', 'test_proc_table' );
create_distributed_function
---------------------------------------------------------------------
(1 row)
-- make sure that metadata is synced, it may take few seconds
CREATE OR REPLACE FUNCTION wait_until_metadata_sync(timeout INTEGER DEFAULT 15000)
RETURNS void
LANGUAGE C STRICT
AS 'citus';
SELECT wait_until_metadata_sync(30000);
wait_until_metadata_sync
---------------------------------------------------------------------
(1 row)
SELECT bool_and(hasmetadata) FROM pg_dist_node WHERE nodeport IN (:worker_1_port, :worker_2_port);
bool_and
---------------------------------------------------------------------
t
(1 row)
-- still, we do not pushdown procedures with OUT parameters
SET client_min_messages TO DEBUG1;
CALL proc_pushdown(1, NULL, NULL);
DEBUG: not pushing down procedures with OUT parameters
created | res_out
---------------------------------------------------------------------
{3} | 3
(1 row)
CALL proc_pushdown(1, ARRAY[2000,1], 'AAAA');
DEBUG: not pushing down procedures with OUT parameters
created | res_out
---------------------------------------------------------------------
{4} | 4
(1 row)
RESET client_min_messages;
-- we don't need metadata syncing anymore
SELECT stop_metadata_sync_to_node('localhost', :worker_1_port);
NOTICE: dropping metadata on the node (localhost,57637)
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
SELECT stop_metadata_sync_to_node('localhost', :worker_2_port);
NOTICE: dropping metadata on the node (localhost,57638)
stop_metadata_sync_to_node
---------------------------------------------------------------------
(1 row)
-- ALTER STATISTICS .. OWNER TO CURRENT_ROLE
CREATE TABLE st1 (a int, b int);
CREATE STATISTICS role_s1 ON a, b FROM st1;
SELECT create_distributed_table('st1','a');
create_distributed_table
---------------------------------------------------------------------
(1 row)
ALTER STATISTICS role_s1 OWNER TO CURRENT_ROLE;
SET citus.enable_ddl_propagation TO off; -- for enterprise
CREATE ROLE role_1 WITH LOGIN SUPERUSER;
NOTICE: not propagating CREATE ROLE/USER commands to worker nodes
HINT: Connect to worker nodes directly to manually create all necessary users and roles.
SET citus.enable_ddl_propagation TO on;
SELECT run_command_on_workers($$CREATE ROLE role_1 WITH LOGIN SUPERUSER;$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,"CREATE ROLE")
(localhost,57638,t,"CREATE ROLE")
(2 rows)
ALTER STATISTICS role_s1 OWNER TO CURRENT_ROLE;
SELECT run_command_on_workers($$SELECT rolname FROM pg_roles WHERE oid IN (SELECT stxowner FROM pg_statistic_ext WHERE stxname LIKE 'role\_s1%');$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,postgres)
(localhost,57638,t,postgres)
(2 rows)
SET ROLE role_1;
ALTER STATISTICS role_s1 OWNER TO CURRENT_ROLE;
SELECT run_command_on_workers($$SELECT rolname FROM pg_roles WHERE oid IN (SELECT stxowner FROM pg_statistic_ext WHERE stxname LIKE 'role\_s1%');$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,role_1)
(localhost,57638,t,role_1)
(2 rows)
SET ROLE postgres;
ALTER STATISTICS role_s1 OWNER TO CURRENT_USER;
SELECT run_command_on_workers($$SELECT rolname FROM pg_roles WHERE oid IN (SELECT stxowner FROM pg_statistic_ext WHERE stxname LIKE 'role\_s1%');$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,postgres)
(localhost,57638,t,postgres)
(2 rows)
SET ROLE to NONE;
ALTER STATISTICS role_s1 OWNER TO CURRENT_ROLE;
SELECT run_command_on_workers($$SELECT rolname FROM pg_roles WHERE oid IN (SELECT stxowner FROM pg_statistic_ext WHERE stxname LIKE 'role\_s1%');$$);
run_command_on_workers
---------------------------------------------------------------------
(localhost,57637,t,postgres)
(localhost,57638,t,postgres)
(2 rows)
create TABLE test_jsonb_subscript (
id int,
test_json jsonb
);
SELECT create_distributed_table('test_jsonb_subscript', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
insert into test_jsonb_subscript values
(1, '{}'), -- empty jsonb
(2, '{"key": "value"}'); -- jsonb with data
-- update empty jsonb
update test_jsonb_subscript set test_json['a'] = '1' where id = 1;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": 1}
2 | {"key": "value"}
(2 rows)
-- update jsonb with some data
update test_jsonb_subscript set test_json['a'] = '1' where id = 2;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": 1}
2 | {"a": 1, "key": "value"}
(2 rows)
-- replace jsonb
update test_jsonb_subscript set test_json['a'] = '"test"';
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": "test"}
2 | {"a": "test", "key": "value"}
(2 rows)
-- replace by object
update test_jsonb_subscript set test_json['a'] = '{"b": 1}'::jsonb;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": {"b": 1}}
2 | {"a": {"b": 1}, "key": "value"}
(2 rows)
-- replace by array
update test_jsonb_subscript set test_json['a'] = '[1, 2, 3]'::jsonb;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": [1, 2, 3]}
2 | {"a": [1, 2, 3], "key": "value"}
(2 rows)
-- use jsonb subscription in where clause
select * from test_jsonb_subscript where test_json['key'] = '"value"' ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
2 | {"a": [1, 2, 3], "key": "value"}
(1 row)
select * from test_jsonb_subscript where test_json['key_doesnt_exists'] = '"value"' ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
(0 rows)
select * from test_jsonb_subscript where test_json['key'] = '"wrong_value"' ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
(0 rows)
-- NULL
update test_jsonb_subscript set test_json[NULL] = '1';
ERROR: jsonb subscript in assignment must not be null
CONTEXT: while executing command on localhost:xxxxx
update test_jsonb_subscript set test_json['another_key'] = NULL;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": [1, 2, 3], "another_key": null}
2 | {"a": [1, 2, 3], "key": "value", "another_key": null}
(2 rows)
-- NULL as jsonb source
insert into test_jsonb_subscript values (3, NULL);
update test_jsonb_subscript set test_json['a'] = '1' where id = 3;
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"a": [1, 2, 3], "another_key": null}
2 | {"a": [1, 2, 3], "key": "value", "another_key": null}
3 | {"a": 1}
(3 rows)
update test_jsonb_subscript set test_json = NULL where id = 3;
update test_jsonb_subscript set test_json[0] = '1';
select * from test_jsonb_subscript ORDER BY 1,2;
id | test_json
---------------------------------------------------------------------
1 | {"0": 1, "a": [1, 2, 3], "another_key": null}
2 | {"0": 1, "a": [1, 2, 3], "key": "value", "another_key": null}
3 | [1]
(3 rows)
-- JOIN ALIAS
CREATE TABLE J1_TBL (
i integer,
j integer,
t text
);
CREATE TABLE J2_TBL (
i integer,
k integer
);
INSERT INTO J1_TBL VALUES (1, 4, 'one');
INSERT INTO J1_TBL VALUES (2, 3, 'two');
INSERT INTO J1_TBL VALUES (3, 2, 'three');
INSERT INTO J1_TBL VALUES (4, 1, 'four');
INSERT INTO J1_TBL VALUES (5, 0, 'five');
INSERT INTO J1_TBL VALUES (6, 6, 'six');
INSERT INTO J1_TBL VALUES (7, 7, 'seven');
INSERT INTO J1_TBL VALUES (8, 8, 'eight');
INSERT INTO J1_TBL VALUES (0, NULL, 'zero');
INSERT INTO J2_TBL VALUES (1, -1);
INSERT INTO J2_TBL VALUES (2, 2);
INSERT INTO J2_TBL VALUES (3, -3);
INSERT INTO J2_TBL VALUES (2, 4);
INSERT INTO J2_TBL VALUES (5, -5);
INSERT INTO J2_TBL VALUES (5, -5);
INSERT INTO J2_TBL VALUES (0, NULL);
SELECT create_distributed_table('J1_TBL','i');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg14.j1_tbl$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
SELECT create_distributed_table('J2_TBL','i');
NOTICE: Copying data from local table...
NOTICE: copying the data has completed
DETAIL: The local data in the table is no longer visible, but is still on disk.
HINT: To remove the local data, run: SELECT truncate_local_data_after_distributing_table($$pg14.j2_tbl$$)
create_distributed_table
---------------------------------------------------------------------
(1 row)
-- test join using aliases
SELECT * FROM J1_TBL JOIN J2_TBL USING (i) WHERE J1_TBL.t = 'one' ORDER BY 1,2,3,4; -- ok
i | j | t | k
---------------------------------------------------------------------
1 | 4 | one | -1
(1 row)
SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one' ORDER BY 1,2,3,4; -- ok
i | j | t | k
---------------------------------------------------------------------
1 | 4 | one | -1
(1 row)
SELECT * FROM (J1_TBL JOIN J2_TBL USING (i)) AS x WHERE J1_TBL.t = 'one' ORDER BY 1,2,3,4; -- error
ERROR: invalid reference to FROM-clause entry for table "j1_tbl"
HINT: There is an entry for table "j1_tbl", but it cannot be referenced from this part of the query.
SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.i = 1 ORDER BY 1,2,3,4; -- ok
i | j | t | k
---------------------------------------------------------------------
1 | 4 | one | -1
(1 row)
SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.t = 'one' ORDER BY 1,2,3,4; -- error
ERROR: column x.t does not exist
SELECT * FROM (J1_TBL JOIN J2_TBL USING (i) AS x) AS xx WHERE x.i = 1 ORDER BY 1,2,3,4; -- error (XXX could use better hint)
ERROR: missing FROM-clause entry for table "x"
SELECT * FROM J1_TBL a1 JOIN J2_TBL a2 USING (i) AS a1 ORDER BY 1,2,3,4; -- error
ERROR: table name "a1" specified more than once
SELECT x.* FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one' ORDER BY 1;
i
---------------------------------------------------------------------
1
(1 row)
SELECT ROW(x.*) FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one' ORDER BY 1;
row
---------------------------------------------------------------------
(1)
(1 row)
SELECT * FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE x.i > 1 ORDER BY 1,2,3,4;
i | j | t | k
---------------------------------------------------------------------
2 | 3 | two | 2
2 | 3 | two | 4
3 | 2 | three | -3
5 | 0 | five | -5
5 | 0 | five | -5
(5 rows)
-- ORDER BY is not supported for json and this returns 1 row, so it is okay.
SELECT row_to_json(x.*) FROM J1_TBL JOIN J2_TBL USING (i) AS x WHERE J1_TBL.t = 'one';
row_to_json
---------------------------------------------------------------------
{"f1":1}
(1 row)
set client_min_messages to error;
drop schema pg14 cascade;

View File

@ -0,0 +1,6 @@
SHOW server_version \gset
SELECT substring(:'server_version', '\d+')::int > 13 AS server_version_above_thirteen
\gset
\if :server_version_above_thirteen
\else
\q

View File

@ -161,10 +161,11 @@ SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHE
(localhost,57637,t,1)
(1 row)
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT workers.result = pg_extension.extversion AS same_version
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers, pg_extension WHERE extname = 'seg';
same_version
---------------------------------------------------------------------
(localhost,57637,t,1.3)
t
(1 row)
-- now create the reference table
@ -254,11 +255,12 @@ SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHE
(localhost,57638,t,1)
(2 rows)
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT workers.result = pg_extension.extversion AS same_version
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers, pg_extension WHERE extname = 'seg';
same_version
---------------------------------------------------------------------
(localhost,57637,t,1.3)
(localhost,57638,t,1.3)
t
t
(2 rows)
-- check for the unpackaged extension to be created correctly
@ -376,12 +378,12 @@ BEGIN;
ROLLBACK;
-- show that the CREATE EXTENSION command propagated even if the transaction
-- block is rollbacked, that's a shortcoming of dependency creation logic
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT COUNT(DISTINCT workers.result)
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers;
count
---------------------------------------------------------------------
(localhost,57637,t,1.3)
(localhost,57638,t,1.3)
(2 rows)
1
(1 row)
-- drop the schema and all the objects
DROP SCHEMA "extension'test" CASCADE;

View File

@ -161,10 +161,11 @@ SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHE
(localhost,57637,t,1)
(1 row)
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT workers.result = pg_extension.extversion AS same_version
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers, pg_extension WHERE extname = 'seg';
same_version
---------------------------------------------------------------------
(localhost,57637,t,1.3)
t
(1 row)
-- now create the reference table
@ -253,11 +254,12 @@ SELECT run_command_on_workers($$SELECT count(extnamespace) FROM pg_extension WHE
(localhost,57638,t,1)
(2 rows)
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT workers.result = pg_extension.extversion AS same_version
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers, pg_extension WHERE extname = 'seg';
same_version
---------------------------------------------------------------------
(localhost,57637,t,1.3)
(localhost,57638,t,1.3)
t
t
(2 rows)
-- check for the unpackaged extension to be created correctly
@ -375,12 +377,12 @@ BEGIN;
ROLLBACK;
-- show that the CREATE EXTENSION command propagated even if the transaction
-- block is rollbacked, that's a shortcoming of dependency creation logic
SELECT run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$);
run_command_on_workers
SELECT COUNT(DISTINCT workers.result)
FROM run_command_on_workers($$SELECT extversion FROM pg_extension WHERE extname = 'seg'$$) workers;
count
---------------------------------------------------------------------
(localhost,57637,t,1.3)
(localhost,57638,t,1.3)
(2 rows)
1
(1 row)
-- drop the schema and all the objects
DROP SCHEMA "extension'test" CASCADE;

View File

@ -99,12 +99,7 @@ SELECT create_distributed_table('test','x');
(1 row)
CREATE STATISTICS stats_xy ON (x, y) FROM test;
ERROR: only simple column references are allowed in CREATE STATISTICS
CREATE STATISTICS stats_xy ON x+y FROM test;
ERROR: only simple column references are allowed in CREATE STATISTICS
CREATE STATISTICS stats_xy ON x,y FROM test;
CREATE STATISTICS IF NOT EXISTS stats_xy ON x+y FROM test;
\c - - - :worker_1_port
SELECT stxname
FROM pg_statistic_ext

View File

@ -126,6 +126,9 @@ DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT foo."?column?
2 | 3 | 376 | 101 | 4 | 0 | 2.5 | 273 | 101 | 2.7029702970297 | Wed Nov 22 18:19:49.944985 2017 | Thu Nov 23 17:30:34.635085 2017 | 101 | 17 | 17
(1 row)
-- we reset the client min_messages here to avoid adding an alternative output
-- for pg14 as the output slightly differs.
RESET client_min_messages;
-- Expressions inside the aggregates
-- parts of the query is inspired by TPCH queries
SELECT
@ -167,20 +170,12 @@ FROM
events_table
WHERE foo.avg != bar.cnt_1 AND baz.cnt_2 != events_table.event_type
ORDER BY 1 DESC;
DEBUG: push down of limit count: 3
DEBUG: generating subplan XXX_1 for subquery SELECT avg(((user_id)::numeric OPERATOR(pg_catalog.*) (5.0 OPERATOR(pg_catalog./) ((value_1)::numeric OPERATOR(pg_catalog.+) 0.1)))) AS avg FROM public.users_table ORDER BY (avg(((user_id)::numeric OPERATOR(pg_catalog.*) (5.0 OPERATOR(pg_catalog./) ((value_1)::numeric OPERATOR(pg_catalog.+) 0.1))))) DESC LIMIT 3
DEBUG: push down of limit count: 3
DEBUG: generating subplan XXX_2 for subquery SELECT sum(((((user_id)::numeric OPERATOR(pg_catalog.*) (5.0 OPERATOR(pg_catalog./) (((value_1 OPERATOR(pg_catalog.+) value_2))::numeric OPERATOR(pg_catalog.+) 0.1))))::double precision OPERATOR(pg_catalog.*) value_3)) AS cnt_1 FROM public.users_table ORDER BY (sum(((((user_id)::numeric OPERATOR(pg_catalog.*) (5.0 OPERATOR(pg_catalog./) (((value_1 OPERATOR(pg_catalog.+) value_2))::numeric OPERATOR(pg_catalog.+) 0.1))))::double precision OPERATOR(pg_catalog.*) value_3))) DESC LIMIT 3
DEBUG: push down of limit count: 4
DEBUG: generating subplan XXX_3 for subquery SELECT avg(CASE WHEN (user_id OPERATOR(pg_catalog.>) 4) THEN value_1 ELSE NULL::integer END) AS cnt_2, avg(CASE WHEN (user_id OPERATOR(pg_catalog.>) 500) THEN value_1 ELSE NULL::integer END) AS cnt_3, sum(CASE WHEN ((value_1 OPERATOR(pg_catalog.=) 1) OR (value_2 OPERATOR(pg_catalog.=) 1)) THEN 1 ELSE 0 END) AS sum_1, date_part('year'::text, max("time")) AS l_year, strpos((max(user_id))::text, '1'::text) AS pos FROM public.users_table ORDER BY (avg(CASE WHEN (user_id OPERATOR(pg_catalog.>) 4) THEN value_1 ELSE NULL::integer END)) DESC LIMIT 4
DEBUG: push down of limit count: 25
DEBUG: generating subplan XXX_4 for subquery SELECT COALESCE(value_3, (20)::double precision) AS count_pay FROM public.users_table ORDER BY COALESCE(value_3, (20)::double precision) OFFSET 20 LIMIT 5
DEBUG: Plan XXX query after replacing subqueries and CTEs: SELECT DISTINCT ON (foo.avg) foo.avg, bar.cnt_1, baz.cnt_2, baz.cnt_3, baz.sum_1, baz.l_year, baz.pos, tar.count_pay FROM (SELECT intermediate_result.avg FROM read_intermediate_result('XXX_1'::text, 'binary'::citus_copy_format) intermediate_result(avg numeric)) foo, (SELECT intermediate_result.cnt_1 FROM read_intermediate_result('XXX_2'::text, 'binary'::citus_copy_format) intermediate_result(cnt_1 double precision)) bar, (SELECT intermediate_result.cnt_2, intermediate_result.cnt_3, intermediate_result.sum_1, intermediate_result.l_year, intermediate_result.pos FROM read_intermediate_result('XXX_3'::text, 'binary'::citus_copy_format) intermediate_result(cnt_2 numeric, cnt_3 numeric, sum_1 bigint, l_year double precision, pos integer)) baz, (SELECT intermediate_result.count_pay FROM read_intermediate_result('XXX_4'::text, 'binary'::citus_copy_format) intermediate_result(count_pay double precision)) tar, public.events_table WHERE (((foo.avg)::double precision OPERATOR(pg_catalog.<>) bar.cnt_1) AND (baz.cnt_2 OPERATOR(pg_catalog.<>) (events_table.event_type)::numeric)) ORDER BY foo.avg DESC
avg | cnt_1 | cnt_2 | cnt_3 | sum_1 | l_year | pos | count_pay
---------------------------------------------------------------------
30.14666771571734992301 | 3308.14619815793 | 2.5000000000000000 | | 31 | 2017 | 0 | 1
(1 row)
SET client_min_messages TO DEBUG1;
-- Multiple columns in GROUP BYs
-- foo needs to be recursively planned, bar can be pushded down
SELECT

View File

@ -1386,12 +1386,16 @@ LIMIT 5;
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1))))
-> HashAggregate
Presorted Key: users_table.user_id
-> GroupAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(18 rows)
-> Incremental Sort
Sort Key: users_table.user_id, users_table.value_2
Presorted Key: users_table.user_id
-> Index Scan using is_index1_1400256 on users_table_1400256 users_table
(22 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1418,12 +1422,16 @@ LIMIT 5;
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1))))
-> HashAggregate
Presorted Key: users_table.user_id
-> GroupAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(18 rows)
-> Incremental Sort
Sort Key: users_table.user_id, users_table.value_2
Presorted Key: users_table.user_id
-> Index Scan using is_index1_1400256 on users_table_1400256 users_table
(22 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1435,7 +1443,7 @@ FROM
GROUP BY user_id, value_2
ORDER BY user_id, avg(value_1) DESC
LIMIT 5;
QUERY PLAN
QUERY PLAN
---------------------------------------------------------------------
Limit
-> Sort
@ -1450,12 +1458,16 @@ LIMIT 5;
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, ((1 / (1 + sum(users_table.value_2))))
-> HashAggregate
Presorted Key: users_table.user_id
-> GroupAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(18 rows)
-> Incremental Sort
Sort Key: users_table.user_id, users_table.value_2
Presorted Key: users_table.user_id
-> Index Scan using is_index1_1400256 on users_table_1400256 users_table
(22 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1467,7 +1479,7 @@ FROM
GROUP BY user_id, value_2
ORDER BY user_id, avg(value_1) DESC
LIMIT 5;
QUERY PLAN
QUERY PLAN
---------------------------------------------------------------------
Limit
-> Sort
@ -1482,12 +1494,16 @@ LIMIT 5;
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (sum(users_table.value_2))
-> HashAggregate
Presorted Key: users_table.user_id
-> GroupAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(18 rows)
-> Incremental Sort
Sort Key: users_table.user_id, users_table.value_2
Presorted Key: users_table.user_id
-> Index Scan using is_index1_1400256 on users_table_1400256 users_table
(22 rows)
-- Grouping can be pushed down with aggregates even when window function can't
EXPLAIN (COSTS FALSE)

View File

@ -1382,15 +1382,16 @@ LIMIT 5;
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Limit
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1))))
-> HashAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(17 rows)
(18 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1413,15 +1414,16 @@ LIMIT 5;
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Limit
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
Sort Key: users_table.user_id, (('1'::numeric / ('1'::numeric + avg(users_table.value_1))))
-> HashAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(17 rows)
(18 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1444,15 +1446,16 @@ LIMIT 5;
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Limit
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
Sort Key: users_table.user_id, ((1 / (1 + sum(users_table.value_2))))
-> HashAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(17 rows)
(18 rows)
EXPLAIN (COSTS FALSE)
SELECT
@ -1475,15 +1478,16 @@ LIMIT 5;
-> Task
Node: host=localhost port=xxxxx dbname=regression
-> Limit
-> Sort
-> Incremental Sort
Sort Key: users_table.user_id, (avg(users_table.value_1)) DESC
Presorted Key: users_table.user_id
-> WindowAgg
-> Sort
Sort Key: users_table.user_id, (sum(users_table.value_2))
-> HashAggregate
Group Key: users_table.user_id, users_table.value_2
-> Seq Scan on users_table_1400256 users_table
(17 rows)
(18 rows)
-- Grouping can be pushed down with aggregates even when window function can't
EXPLAIN (COSTS FALSE)

Some files were not shown because too many files have changed in this diff Show More